good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
489576b6
Commit
489576b6
authored
Jan 18, 2014
by
Jeffrey Wilcke
Browse files
Options
Downloads
Patches
Plain Diff
More opcodes
parent
ee61cfcf
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
block_manager.go
+80
-53
80 additions, 53 deletions
block_manager.go
stack.go
+5
-6
5 additions, 6 deletions
stack.go
with
85 additions
and
59 deletions
block_manager.go
+
80
−
53
View file @
489576b6
...
...
@@ -9,6 +9,7 @@ import (
"log"
"math"
"math/big"
"strconv"
)
type
BlockChain
struct
{
...
...
@@ -52,14 +53,14 @@ type BlockManager struct {
// Stack for processing contracts
stack
*
Stack
// non-persistent key/value memory storage
mem
map
[
string
]
string
mem
map
[
string
]
*
big
.
Int
}
func
NewBlockManager
()
*
BlockManager
{
bm
:=
&
BlockManager
{
bc
:
NewBlockChain
(),
stack
:
NewStack
(),
mem
:
make
(
map
[
string
]
string
),
mem
:
make
(
map
[
string
]
*
big
.
Int
),
}
// Set the last known block number based on the blockchains last
...
...
@@ -276,27 +277,27 @@ out:
base
.
Add
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
bm
.
stack
.
Push
(
base
.
String
()
)
bm
.
stack
.
Push
(
base
)
case
oSUB
:
x
,
y
:=
bm
.
stack
.
Popn
()
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
bm
.
stack
.
Push
(
base
.
String
()
)
bm
.
stack
.
Push
(
base
)
case
oMUL
:
x
,
y
:=
bm
.
stack
.
Popn
()
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
bm
.
stack
.
Push
(
base
.
String
()
)
bm
.
stack
.
Push
(
base
)
case
oDIV
:
x
,
y
:=
bm
.
stack
.
Popn
()
// floor(x / y)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
bm
.
stack
.
Push
(
base
.
String
()
)
bm
.
stack
.
Push
(
base
)
case
oSDIV
:
x
,
y
:=
bm
.
stack
.
Popn
()
// n > 2**255
...
...
@@ -312,11 +313,11 @@ out:
z
.
Sub
(
Pow256
,
z
)
}
// Push result on to the stack
bm
.
stack
.
Push
(
z
.
String
()
)
bm
.
stack
.
Push
(
z
)
case
oMOD
:
x
,
y
:=
bm
.
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
bm
.
stack
.
Push
(
base
.
String
()
)
bm
.
stack
.
Push
(
base
)
case
oSMOD
:
x
,
y
:=
bm
.
stack
.
Popn
()
// n > 2**255
...
...
@@ -332,87 +333,85 @@ out:
z
.
Sub
(
Pow256
,
z
)
}
// Push result on to the stack
bm
.
stack
.
Push
(
z
.
String
()
)
bm
.
stack
.
Push
(
z
)
case
oEXP
:
x
,
y
:=
bm
.
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
bm
.
stack
.
Push
(
base
.
String
()
)
bm
.
stack
.
Push
(
base
)
case
oNEG
:
base
.
Sub
(
Pow256
,
ethutil
.
Big
(
bm
.
stack
.
Pop
())
)
bm
.
stack
.
Push
(
base
.
String
()
)
base
.
Sub
(
Pow256
,
bm
.
stack
.
Pop
())
bm
.
stack
.
Push
(
base
)
case
oLT
:
x
,
y
:=
bm
.
stack
.
Popn
()
// x < y
if
x
.
Cmp
(
y
)
<
0
{
bm
.
stack
.
Push
(
"1"
)
bm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oLE
:
x
,
y
:=
bm
.
stack
.
Popn
()
// x <= y
if
x
.
Cmp
(
y
)
<
1
{
bm
.
stack
.
Push
(
"1"
)
bm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oGT
:
x
,
y
:=
bm
.
stack
.
Popn
()
// x > y
if
x
.
Cmp
(
y
)
>
0
{
bm
.
stack
.
Push
(
"1"
)
bm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oGE
:
x
,
y
:=
bm
.
stack
.
Popn
()
// x >= y
if
x
.
Cmp
(
y
)
>
-
1
{
bm
.
stack
.
Push
(
"1"
)
bm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oNOT
:
x
,
y
:=
bm
.
stack
.
Popn
()
// x != y
if
x
.
Cmp
(
y
)
!=
0
{
bm
.
stack
.
Push
(
"1"
)
bm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
// Please note that the following code contains some
// ugly string casting. This will have to change to big
// ints. TODO :)
case
oMYADDRESS
:
bm
.
stack
.
Push
(
string
(
tx
.
Hash
()))
bm
.
stack
.
Push
(
ethutil
.
BigD
(
tx
.
Hash
()))
case
oTXSENDER
:
bm
.
stack
.
Push
(
string
(
tx
.
Sender
()))
bm
.
stack
.
Push
(
ethutil
.
BigD
(
tx
.
Sender
()))
case
oTXVALUE
:
bm
.
stack
.
Push
(
tx
.
Value
.
String
()
)
bm
.
stack
.
Push
(
tx
.
Value
)
case
oTXDATAN
:
bm
.
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
tx
.
Data
)))
.
String
()
)
bm
.
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
tx
.
Data
))))
case
oTXDATA
:
v
:=
ethutil
.
Big
(
bm
.
stack
.
Pop
()
)
v
:=
bm
.
stack
.
Pop
()
// v >= len(data)
if
v
.
Cmp
(
big
.
NewInt
(
int64
(
len
(
tx
.
Data
))))
>=
0
{
//I know this will change. It makes no
//sense. Read comment above
bm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
)
.
String
())
bm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
))
}
else
{
bm
.
stack
.
Push
(
ethutil
.
Big
(
tx
.
Data
[
v
.
Uint64
()])
.
String
()
)
bm
.
stack
.
Push
(
ethutil
.
Big
(
tx
.
Data
[
v
.
Uint64
()]))
}
case
oBLK_PREVHASH
:
bm
.
stack
.
Push
(
strin
g
(
block
.
PrevHash
))
bm
.
stack
.
Push
(
ethutil
.
Bi
g
(
block
.
PrevHash
))
case
oBLK_COINBASE
:
bm
.
stack
.
Push
(
block
.
Coinbase
)
bm
.
stack
.
Push
(
ethutil
.
Big
(
block
.
Coinbase
)
)
case
oBLK_TIMESTAMP
:
bm
.
stack
.
Push
(
big
.
NewInt
(
block
.
Time
)
.
String
()
)
bm
.
stack
.
Push
(
big
.
NewInt
(
block
.
Time
))
case
oBLK_NUMBER
:
bm
.
stack
.
Push
(
blockInfo
.
Number
.
String
()
)
bm
.
stack
.
Push
(
blockInfo
.
Number
)
case
oBLK_DIFFICULTY
:
bm
.
stack
.
Push
(
block
.
Difficulty
.
String
()
)
bm
.
stack
.
Push
(
block
.
Difficulty
)
case
oBASEFEE
:
// e = 10^21
e
:=
big
.
NewInt
(
0
)
.
Exp
(
big
.
NewInt
(
10
),
big
.
NewInt
(
21
),
big
.
NewInt
(
0
))
...
...
@@ -429,23 +428,23 @@ out:
x
.
Div
(
e
,
base
)
// x = floor(10^21 / floor(diff^0.5))
bm
.
stack
.
Push
(
x
.
String
()
)
bm
.
stack
.
Push
(
x
)
case
oSHA256
,
oRIPEMD160
:
// This is probably save
// ceil(pop / 32)
length
:=
int
(
math
.
Ceil
(
float64
(
ethutil
.
Big
(
bm
.
stack
.
Pop
()
)
.
Uint64
())
/
32.0
))
length
:=
int
(
math
.
Ceil
(
float64
(
bm
.
stack
.
Pop
()
.
Uint64
())
/
32.0
))
// New buffer which will contain the concatenated popped items
data
:=
new
(
bytes
.
Buffer
)
for
i
:=
0
;
i
<
length
;
i
++
{
// Encode the number to bytes and have it 32bytes long
num
:=
ethutil
.
NumberToBytes
(
ethutil
.
Big
(
bm
.
stack
.
Pop
()
)
.
Bytes
(),
256
)
num
:=
ethutil
.
NumberToBytes
(
bm
.
stack
.
Pop
()
.
Bytes
(),
256
)
data
.
WriteString
(
string
(
num
))
}
if
op
==
oSHA256
{
bm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Sha256Bin
(
data
.
Bytes
()))
.
String
()
)
bm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Sha256Bin
(
data
.
Bytes
())))
}
else
{
bm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Ripemd160
(
data
.
Bytes
()))
.
String
()
)
bm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Ripemd160
(
data
.
Bytes
())))
}
case
oECMUL
:
y
:=
bm
.
stack
.
Pop
()
...
...
@@ -454,14 +453,14 @@ out:
//if ethutil.Big(x).Cmp(ethutil.Big(y)) {
data
:=
new
(
bytes
.
Buffer
)
data
.
WriteString
(
x
)
data
.
WriteString
(
y
)
data
.
WriteString
(
x
.
String
()
)
data
.
WriteString
(
y
.
String
()
)
if
secp256k1
.
VerifyPubkeyValidity
(
data
.
Bytes
())
==
1
{
// TODO
}
else
{
// Invalid, push infinity
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
"0"
)
bm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
)
)
bm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
)
)
}
//} else {
// // Invalid, push infinity
...
...
@@ -475,31 +474,59 @@ out:
case
oECVALID
:
case
oSHA3
:
case
oPUSH
:
// Get the next entry and pushes the value on the stack
pc
++
bm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
)))
)
bm
.
stack
.
Push
(
bm
.
mem
[
strconv
.
Itoa
(
pc
)]
)
case
oPOP
:
// Pop current value of the stack
bm
.
stack
.
Pop
()
case
oDUP
:
// Dup top stack
x
:=
bm
.
stack
.
Pop
()
bm
.
stack
.
Push
(
x
)
bm
.
stack
.
Push
(
x
)
case
oSWAP
:
// Swap two top most values
x
,
y
:=
bm
.
stack
.
Popn
()
bm
.
stack
.
Push
(
y
)
bm
.
stack
.
Push
(
x
)
case
oMLOAD
:
x
:=
bm
.
stack
.
Pop
()
bm
.
stack
.
Push
(
bm
.
mem
[
x
.
String
()])
case
oMSTORE
:
x
,
y
:=
bm
.
stack
.
Popn
()
bm
.
mem
[
x
.
String
()]
=
y
case
oSLOAD
:
// Load the value in storage and push it on the stack
x
:=
bm
.
stack
.
Pop
()
// decode the object as a big integer
decoder
:=
ethutil
.
NewRlpDecoder
([]
byte
(
contract
.
State
()
.
Get
(
x
.
String
())))
if
!
decoder
.
IsNil
()
{
bm
.
stack
.
Push
(
decoder
.
AsBigInt
())
}
else
{
bm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oSSTORE
:
// Store Y at index X
x
,
y
:=
bm
.
stack
.
Popn
()
contract
.
State
()
.
Update
(
x
.
String
(),
string
(
ethutil
.
Encode
(
y
)))
case
oJMP
:
x
:=
int
(
bm
.
stack
.
Pop
()
.
Uint64
())
// Set pc to x - 1 (minus one so the incrementing at the end won't effect it)
pc
=
x
pc
--
case
oJMPI
:
x
:=
bm
.
stack
.
Pop
()
// Set pc to x if it's non zero
if
x
.
Cmp
(
ethutil
.
BigFalse
)
!=
0
{
pc
=
int
(
x
.
Uint64
())
pc
--
}
case
oIND
:
bm
.
stack
.
Push
(
big
.
NewInt
(
int64
(
pc
)))
case
oEXTRO
:
case
oBALANCE
:
case
oMKTX
:
case
oSUICIDE
:
/*
case oLOAD:
// Load instruction X on the stack
i, _ := strconv.Atoi(bm.stack.Pop())
bm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32))))
*/
}
pc
++
}
...
...
This diff is collapsed.
Click to expand it.
stack.go
+
5
−
6
View file @
489576b6
...
...
@@ -2,7 +2,6 @@ package main
import
(
"fmt"
"github.com/ethereum/ethutil-go"
"math/big"
)
...
...
@@ -135,14 +134,14 @@ type TxCallback func(opType OpType) bool
// Simple push/pop stack mechanism
type
Stack
struct
{
data
[]
string
data
[]
*
big
.
Int
}
func
NewStack
()
*
Stack
{
return
&
Stack
{}
}
func
(
st
*
Stack
)
Pop
()
string
{
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
s
-
1
]
...
...
@@ -154,13 +153,13 @@ func (st *Stack) Pop() string {
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
str
s
:=
st
.
data
[
s
-
2
:
]
int
s
:=
st
.
data
[
s
-
2
:
]
st
.
data
=
st
.
data
[
:
s
-
2
]
return
ethutil
.
Big
(
str
s
[
0
]
)
,
ethutil
.
Big
(
str
s
[
1
]
)
return
int
s
[
0
],
int
s
[
1
]
}
func
(
st
*
Stack
)
Push
(
d
string
)
{
func
(
st
*
Stack
)
Push
(
d
*
big
.
Int
)
{
st
.
data
=
append
(
st
.
data
,
d
)
}
func
(
st
*
Stack
)
Print
()
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment