Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
97786d03
Commit
97786d03
authored
Mar 24, 2014
by
Maran
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into miner
parents
274d5cc9
6a86c517
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
786 additions
and
511 deletions
+786
-511
README.md
README.md
+1
-1
address.go
ethchain/address.go
+25
-9
block.go
ethchain/block.go
+1
-1
block_manager_test.go
ethchain/block_manager_test.go
+4
-1
closure.go
ethchain/closure.go
+90
-0
contract.go
ethchain/contract.go
+37
-15
stack.go
ethchain/stack.go
+181
-115
state.go
ethchain/state.go
+39
-16
state_manager.go
ethchain/state_manager.go
+7
-8
transaction.go
ethchain/transaction.go
+15
-6
vm.go
ethchain/vm.go
+190
-271
vm_test.go
ethchain/vm_test.go
+69
-1
common.go
ethutil/common.go
+6
-0
config.go
ethutil/config.go
+13
-6
parsing.go
ethutil/parsing.go
+102
-59
rlp.go
ethutil/rlp.go
+4
-0
trie_test.go
ethutil/trie_test.go
+1
-0
peer.go
peer.go
+1
-2
No files found.
README.md
View file @
97786d03
...
@@ -6,7 +6,7 @@ Ethereum
...
@@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof
Ethereum is currently in its testing phase. The current state is "Proof
of Concept 3". For build instructions see the
[
Wiki
](
https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go
)
).
of Concept 3
.5
". For build instructions see the
[
Wiki
](
https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go
)
).
Ethereum Go is split up in several sub packages Please refer to each
Ethereum Go is split up in several sub packages Please refer to each
individual package for more information.
individual package for more information.
...
...
ethchain/address.go
View file @
97786d03
...
@@ -6,23 +6,39 @@ import (
...
@@ -6,23 +6,39 @@ import (
)
)
type
Account
struct
{
type
Account
struct
{
address
[]
byte
Amount
*
big
.
Int
Amount
*
big
.
Int
Nonce
uint64
Nonce
uint64
}
}
func
NewAccount
(
amount
*
big
.
Int
)
*
Account
{
func
NewAccount
(
a
ddress
[]
byte
,
a
mount
*
big
.
Int
)
*
Account
{
return
&
Account
{
Amount
:
amount
,
Nonce
:
0
}
return
&
Account
{
address
,
amount
,
0
}
}
}
func
NewAccountFromData
(
data
[]
byte
)
*
Account
{
func
NewAccountFromData
(
address
,
data
[]
byte
)
*
Account
{
a
ddress
:=
&
Account
{
}
a
ccount
:=
&
Account
{
address
:
address
}
a
ddress
.
RlpDecode
(
data
)
a
ccount
.
RlpDecode
(
data
)
return
a
ddress
return
a
ccount
}
}
func
(
a
*
Account
)
AddFee
(
fee
*
big
.
Int
)
{
func
(
a
*
Account
)
AddFee
(
fee
*
big
.
Int
)
{
a
.
Amount
.
Add
(
a
.
Amount
,
fee
)
a
.
AddFunds
(
fee
)
}
func
(
a
*
Account
)
AddFunds
(
funds
*
big
.
Int
)
{
a
.
Amount
.
Add
(
a
.
Amount
,
funds
)
}
func
(
a
*
Account
)
Address
()
[]
byte
{
return
a
.
address
}
// Implements Callee
func
(
a
*
Account
)
ReturnGas
(
value
*
big
.
Int
,
state
*
State
)
{
// Return the value back to the sender
a
.
AddFunds
(
value
)
state
.
UpdateAccount
(
a
.
address
,
a
)
}
}
func
(
a
*
Account
)
RlpEncode
()
[]
byte
{
func
(
a
*
Account
)
RlpEncode
()
[]
byte
{
...
...
ethchain/block.go
View file @
97786d03
...
@@ -142,7 +142,7 @@ func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
...
@@ -142,7 +142,7 @@ func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
data
:=
block
.
state
.
trie
.
Get
(
string
(
block
.
Coinbase
))
data
:=
block
.
state
.
trie
.
Get
(
string
(
block
.
Coinbase
))
// Get the ether (Coinbase) and add the fee (gief fee to miner)
// Get the ether (Coinbase) and add the fee (gief fee to miner)
ether
:=
NewAccountFromData
([]
byte
(
data
))
ether
:=
NewAccountFromData
(
block
.
Coinbase
,
[]
byte
(
data
))
base
=
new
(
big
.
Int
)
base
=
new
(
big
.
Int
)
ether
.
Amount
=
base
.
Add
(
ether
.
Amount
,
fee
)
ether
.
Amount
=
base
.
Add
(
ether
.
Amount
,
fee
)
...
...
ethchain/block_manager_test.go
View file @
97786d03
package
ethchain
package
ethchain
/*
import (
import (
_ "fmt"
_ "fmt"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethdb"
...
@@ -14,9 +15,10 @@ func TestVm(t *testing.T) {
...
@@ -14,9 +15,10 @@ func TestVm(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
db, _ := ethdb.NewMemDatabase()
ethutil.Config.Db = db
ethutil.Config.Db = db
bm
:=
New
Block
Manager
(
nil
)
bm := New
State
Manager(nil)
block := bm.bc.genesisBlock
block := bm.bc.genesisBlock
bm.Prepare(block.State(), block.State())
script := Compile([]string{
script := Compile([]string{
"PUSH",
"PUSH",
"1",
"1",
...
@@ -31,3 +33,4 @@ func TestVm(t *testing.T) {
...
@@ -31,3 +33,4 @@ func TestVm(t *testing.T) {
tx2.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
tx2.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
bm.ApplyTransactions(block, []*Transaction{tx2})
bm.ApplyTransactions(block, []*Transaction{tx2})
}
}
*/
ethchain/closure.go
0 → 100644
View file @
97786d03
package
ethchain
// TODO Re write VM to use values instead of big integers?
import
(
"github.com/ethereum/eth-go/ethutil"
"math/big"
)
type
Callee
interface
{
ReturnGas
(
*
big
.
Int
,
*
State
)
Address
()
[]
byte
}
type
ClosureBody
interface
{
Callee
ethutil
.
RlpEncodable
GetMem
(
*
big
.
Int
)
*
ethutil
.
Value
SetMem
(
*
big
.
Int
,
*
ethutil
.
Value
)
}
// Basic inline closure object which implement the 'closure' interface
type
Closure
struct
{
callee
Callee
object
ClosureBody
State
*
State
Gas
*
big
.
Int
Value
*
big
.
Int
Args
[]
byte
}
// Create a new closure for the given data items
func
NewClosure
(
callee
Callee
,
object
ClosureBody
,
state
*
State
,
gas
,
val
*
big
.
Int
)
*
Closure
{
return
&
Closure
{
callee
,
object
,
state
,
gas
,
val
,
nil
}
}
// Retuns the x element in data slice
func
(
c
*
Closure
)
GetMem
(
x
*
big
.
Int
)
*
ethutil
.
Value
{
m
:=
c
.
object
.
GetMem
(
x
)
if
m
==
nil
{
return
ethutil
.
EmptyValue
()
}
return
m
}
func
(
c
*
Closure
)
SetMem
(
x
*
big
.
Int
,
val
*
ethutil
.
Value
)
{
c
.
object
.
SetMem
(
x
,
val
)
}
func
(
c
*
Closure
)
Address
()
[]
byte
{
return
c
.
object
.
Address
()
}
func
(
c
*
Closure
)
Call
(
vm
*
Vm
,
args
[]
byte
)
[]
byte
{
c
.
Args
=
args
return
vm
.
RunClosure
(
c
)
}
func
(
c
*
Closure
)
Return
(
ret
[]
byte
)
[]
byte
{
// Return the remaining gas to the callee
// If no callee is present return it to
// the origin (i.e. contract or tx)
if
c
.
callee
!=
nil
{
c
.
callee
.
ReturnGas
(
c
.
Gas
,
c
.
State
)
}
else
{
c
.
object
.
ReturnGas
(
c
.
Gas
,
c
.
State
)
// TODO incase it's a POST contract we gotta serialise the contract again.
// But it's not yet defined
}
return
ret
}
// Implement the Callee interface
func
(
c
*
Closure
)
ReturnGas
(
gas
*
big
.
Int
,
state
*
State
)
{
// Return the gas to the closure
c
.
Gas
.
Add
(
c
.
Gas
,
gas
)
}
func
(
c
*
Closure
)
Object
()
ClosureBody
{
return
c
.
object
}
func
(
c
*
Closure
)
Callee
()
Callee
{
return
c
.
callee
}
ethchain/contract.go
View file @
97786d03
...
@@ -10,25 +10,21 @@ type Contract struct {
...
@@ -10,25 +10,21 @@ type Contract struct {
Nonce
uint64
Nonce
uint64
//state *ethutil.Trie
//state *ethutil.Trie
state
*
State
state
*
State
address
[]
byte
}
}
func
NewContract
(
Amount
*
big
.
Int
,
root
[]
byte
)
*
Contract
{
func
NewContract
(
address
[]
byte
,
Amount
*
big
.
Int
,
root
[]
byte
)
*
Contract
{
contract
:=
&
Contract
{
Amount
:
Amount
,
Nonce
:
0
}
contract
:=
&
Contract
{
address
:
address
,
Amount
:
Amount
,
Nonce
:
0
}
contract
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
string
(
root
)))
contract
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
string
(
root
)))
return
contract
return
contract
}
}
func
(
c
*
Contract
)
RlpEncode
()
[]
byte
{
func
NewContractFromBytes
(
address
,
data
[]
byte
)
*
Contract
{
return
ethutil
.
Encode
([]
interface
{}{
c
.
Amount
,
c
.
Nonce
,
c
.
state
.
trie
.
Root
})
contract
:=
&
Contract
{
address
:
address
}
}
contract
.
RlpDecode
(
data
)
func
(
c
*
Contract
)
RlpDecode
(
data
[]
byte
)
{
return
contract
decoder
:=
ethutil
.
NewValueFromBytes
(
data
)
c
.
Amount
=
decoder
.
Get
(
0
)
.
BigInt
()
c
.
Nonce
=
decoder
.
Get
(
1
)
.
Uint
()
c
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
decoder
.
Get
(
2
)
.
Interface
()))
}
}
func
(
c
*
Contract
)
Addr
(
addr
[]
byte
)
*
ethutil
.
Value
{
func
(
c
*
Contract
)
Addr
(
addr
[]
byte
)
*
ethutil
.
Value
{
...
@@ -43,19 +39,45 @@ func (c *Contract) State() *State {
...
@@ -43,19 +39,45 @@ func (c *Contract) State() *State {
return
c
.
state
return
c
.
state
}
}
func
(
c
*
Contract
)
GetMem
(
num
i
nt
)
*
ethutil
.
Value
{
func
(
c
*
Contract
)
GetMem
(
num
*
big
.
I
nt
)
*
ethutil
.
Value
{
nb
:=
ethutil
.
BigToBytes
(
big
.
NewInt
(
int64
(
num
))
,
256
)
nb
:=
ethutil
.
BigToBytes
(
num
,
256
)
return
c
.
Addr
(
nb
)
return
c
.
Addr
(
nb
)
}
}
func
(
c
*
Contract
)
SetMem
(
num
*
big
.
Int
,
val
*
ethutil
.
Value
)
{
addr
:=
ethutil
.
BigToBytes
(
num
,
256
)
c
.
state
.
trie
.
Update
(
string
(
addr
),
string
(
val
.
Encode
()))
}
// Return the gas back to the origin. Used by the Virtual machine or Closures
func
(
c
*
Contract
)
ReturnGas
(
val
*
big
.
Int
,
state
*
State
)
{
c
.
Amount
.
Add
(
c
.
Amount
,
val
)
}
func
(
c
*
Contract
)
Address
()
[]
byte
{
return
c
.
address
}
func
(
c
*
Contract
)
RlpEncode
()
[]
byte
{
return
ethutil
.
Encode
([]
interface
{}{
c
.
Amount
,
c
.
Nonce
,
c
.
state
.
trie
.
Root
})
}
func
(
c
*
Contract
)
RlpDecode
(
data
[]
byte
)
{
decoder
:=
ethutil
.
NewValueFromBytes
(
data
)
c
.
Amount
=
decoder
.
Get
(
0
)
.
BigInt
()
c
.
Nonce
=
decoder
.
Get
(
1
)
.
Uint
()
c
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
decoder
.
Get
(
2
)
.
Interface
()))
}
func
MakeContract
(
tx
*
Transaction
,
state
*
State
)
*
Contract
{
func
MakeContract
(
tx
*
Transaction
,
state
*
State
)
*
Contract
{
// Create contract if there's no recipient
// Create contract if there's no recipient
if
tx
.
IsContract
()
{
if
tx
.
IsContract
()
{
addr
:=
tx
.
Hash
()[
12
:
]
addr
:=
tx
.
Hash
()[
12
:
]
value
:=
tx
.
Value
value
:=
tx
.
Value
contract
:=
NewContract
(
value
,
[]
byte
(
""
))
contract
:=
NewContract
(
addr
,
value
,
[]
byte
(
""
))
state
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
state
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
for
i
,
val
:=
range
tx
.
Data
{
for
i
,
val
:=
range
tx
.
Data
{
if
len
(
val
)
>
0
{
if
len
(
val
)
>
0
{
...
...
ethchain/stack.go
View file @
97786d03
...
@@ -2,6 +2,7 @@ package ethchain
...
@@ -2,6 +2,7 @@ package ethchain
import
(
import
(
"fmt"
"fmt"
_
"github.com/ethereum/eth-go/ethutil"
"math/big"
"math/big"
)
)
...
@@ -9,6 +10,7 @@ type OpCode int
...
@@ -9,6 +10,7 @@ type OpCode int
// Op codes
// Op codes
const
(
const
(
// 0x0 range - arithmetic ops
oSTOP
=
0x00
oSTOP
=
0x00
oADD
=
0x01
oADD
=
0x01
oMUL
=
0x02
oMUL
=
0x02
...
@@ -20,50 +22,65 @@ const (
...
@@ -20,50 +22,65 @@ const (
oEXP
=
0x08
oEXP
=
0x08
oNEG
=
0x09
oNEG
=
0x09
oLT
=
0x0a
oLT
=
0x0a
oLE
=
0x0b
oGT
=
0x0b
oGT
=
0x0c
oEQ
=
0x0c
oGE
=
0x0d
oNOT
=
0x0d
oEQ
=
0x0e
oNOT
=
0x0f
// 0x10 range - bit ops
oMYADDRESS
=
0x10
oAND
=
0x10
oTXSENDER
=
0x11
oOR
=
0x11
oTXVALUE
=
0x12
oXOR
=
0x12
oTXDATAN
=
0x13
oBYTE
=
0x13
oTXDATA
=
0x14
oBLK_PREVHASH
=
0x15
// 0x20 range - crypto
oBLK_COINBASE
=
0x16
oSHA3
=
0x20
oBLK_TIMESTAMP
=
0x17
oBLK_NUMBER
=
0x18
// 0x30 range - closure state
oBLK_DIFFICULTY
=
0x19
oADDRESS
=
0x30
oBLK_NONCE
=
0x1a
oBALANCE
=
0x31
oBASEFEE
=
0x1b
oORIGIN
=
0x32
oSHA256
=
0x20
oCALLER
=
0x33
oRIPEMD160
=
0x21
oCALLVALUE
=
0x34
oECMUL
=
0x22
oCALLDATA
=
0x35
oECADD
=
0x23
oCALLDATASIZE
=
0x36
oECSIGN
=
0x24
oGASPRICE
=
0x37
oECRECOVER
=
0x25
oECVALID
=
0x26
// 0x40 range - block operations
oSHA3
=
0x27
oPREVHASH
=
0x40
oPUSH
=
0x30
oCOINBASE
=
0x41
oPOP
=
0x31
oTIMESTAMP
=
0x42
oDUP
=
0x32
oNUMBER
=
0x43
oSWAP
=
0x33
oDIFFICULTY
=
0x44
oMLOAD
=
0x34
oGASLIMIT
=
0x45
oMSTORE
=
0x35
oSLOAD
=
0x36
// 0x50 range - 'storage' and execution
oSSTORE
=
0x37
oPUSH
=
0x50
oJMP
=
0x38
oPOP
=
0x51
oJMPI
=
0x39
oDUP
=
0x52
oIND
=
0x3a
oSWAP
=
0x53
oEXTRO
=
0x3b
oMLOAD
=
0x54
oBALANCE
=
0x3c
oMSTORE
=
0x55
oMKTX
=
0x3d
oMSTORE8
=
0x56
oSUICIDE
=
0x3f
oSLOAD
=
0x57
oSSTORE
=
0x58
oJUMP
=
0x59
oJUMPI
=
0x5a
oPC
=
0x5b
oMSIZE
=
0x5c
// 0x60 range - closures
oCREATE
=
0x60
oCALL
=
0x61
oRETURN
=
0x62
// 0x70 range - other
oLOG
=
0x70
// XXX Unofficial
oSUICIDE
=
0x7f
)
)
// Since the opcodes aren't all in order we can't use a regular slice
// Since the opcodes aren't all in order we can't use a regular slice
var
opCodeToString
=
map
[
OpCode
]
string
{
var
opCodeToString
=
map
[
OpCode
]
string
{
// 0x0 range - arithmetic ops
oSTOP
:
"STOP"
,
oSTOP
:
"STOP"
,
oADD
:
"ADD"
,
oADD
:
"ADD"
,
oMUL
:
"MUL"
,
oMUL
:
"MUL"
,
...
@@ -75,44 +92,59 @@ var opCodeToString = map[OpCode]string{
...
@@ -75,44 +92,59 @@ var opCodeToString = map[OpCode]string{
oEXP
:
"EXP"
,
oEXP
:
"EXP"
,
oNEG
:
"NEG"
,
oNEG
:
"NEG"
,
oLT
:
"LT"
,
oLT
:
"LT"
,
oLE
:
"LE"
,
oGT
:
"GT"
,
oGT
:
"GT"
,
oGE
:
"GE"
,
oEQ
:
"EQ"
,
oEQ
:
"EQ"
,
oNOT
:
"NOT"
,
oNOT
:
"NOT"
,
oMYADDRESS
:
"MYADDRESS"
,
oTXSENDER
:
"TXSENDER"
,
// 0x10 range - bit ops
oTXVALUE
:
"TXVALUE"
,
oAND
:
"AND"
,
oTXDATAN
:
"TXDATAN"
,
oOR
:
"OR"
,
oTXDATA
:
"TXDATA"
,
oXOR
:
"XOR"
,
oBLK_PREVHASH
:
"BLK_PREVHASH"
,
oBYTE
:
"BYTE"
,
oBLK_COINBASE
:
"BLK_COINBASE"
,
oBLK_TIMESTAMP
:
"BLK_TIMESTAMP"
,
// 0x20 range - crypto
oBLK_NUMBER
:
"BLK_NUMBER"
,
oBLK_DIFFICULTY
:
"BLK_DIFFICULTY"
,
oBASEFEE
:
"BASEFEE"
,
oSHA256
:
"SHA256"
,
oRIPEMD160
:
"RIPEMD160"
,
oECMUL
:
"ECMUL"
,
oECADD
:
"ECADD"
,
oECSIGN
:
"ECSIGN"
,
oECRECOVER
:
"ECRECOVER"
,
oECVALID
:
"ECVALID"
,
oSHA3
:
"SHA3"
,
oSHA3
:
"SHA3"
,
// 0x30 range - closure state
oADDRESS
:
"ADDRESS"
,
oBALANCE
:
"BALANCE"
,
oORIGIN
:
"ORIGIN"
,
oCALLER
:
"CALLER"
,
oCALLVALUE
:
"CALLVALUE"
,
oCALLDATA
:
"CALLDATA"
,
oCALLDATASIZE
:
"CALLDATASIZE"
,
oGASPRICE
:
"TXGASPRICE"
,
// 0x40 range - block operations
oPREVHASH
:
"PREVHASH"
,
oCOINBASE
:
"COINBASE"
,
oTIMESTAMP
:
"TIMESTAMP"
,
oNUMBER
:
"NUMBER"
,
oDIFFICULTY
:
"DIFFICULTY"
,
oGASLIMIT
:
"GASLIMIT"
,
// 0x50 range - 'storage' and execution
oPUSH
:
"PUSH"
,
oPUSH
:
"PUSH"
,
oPOP
:
"POP"
,
oPOP
:
"POP"
,
oDUP
:
"DUP"
,
oDUP
:
"DUP"
,
oSWAP
:
"SWAP"
,
oSWAP
:
"SWAP"
,
oMLOAD
:
"MLOAD"
,
oMLOAD
:
"MLOAD"
,
oMSTORE
:
"MSTORE"
,
oMSTORE
:
"MSTORE"
,
oMSTORE8
:
"MSTORE8"
,
oSLOAD
:
"SLOAD"
,
oSLOAD
:
"SLOAD"
,
oSSTORE
:
"SSTORE"
,
oSSTORE
:
"SSTORE"
,
oJMP
:
"JMP"
,
oJUMP
:
"JUMP"
,
oJMPI
:
"JMPI"
,
oJUMPI
:
"JUMPI"
,
oIND
:
"IND"
,
oPC
:
"PC"
,
oEXTRO
:
"EXTRO"
,
oMSIZE
:
"MSIZE"
,
oBALANCE
:
"BALANCE"
,
oMKTX
:
"MKTX"
,
// 0x60 range - closures
oCREATE
:
"CREATE"
,
oCALL
:
"CALL"
,
oRETURN
:
"RETURN"
,
// 0x70 range - other
oLOG
:
"LOG"
,
oSUICIDE
:
"SUICIDE"
,
oSUICIDE
:
"SUICIDE"
,
}
}
...
@@ -141,35 +173,27 @@ func NewStack() *Stack {
...
@@ -141,35 +173,27 @@ func NewStack() *Stack {
}
}
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
0
]
st
.
data
=
st
.
data
[
1
:
]
str
:=
st
.
data
[
s
-
1
]
st
.
data
=
st
.
data
[
:
s
-
1
]
return
str
return
str
}
}
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
ints
:=
st
.
data
[
:
2
]
st
.
data
=
st
.
data
[
2
:
]
ints
:=
st
.
data
[
s
-
2
:
]
st
.
data
=
st
.
data
[
:
s
-
2
]
return
ints
[
0
],
ints
[
1
]
return
ints
[
0
],
ints
[
1
]
}
}
func
(
st
*
Stack
)
Peek
()
*
big
.
Int
{
func
(
st
*
Stack
)
Peek
()
*
big
.
Int
{
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
0
]
str
:=
st
.
data
[
s
-
1
]
return
str
return
str
}
}
func
(
st
*
Stack
)
Peekn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
func
(
st
*
Stack
)
Peekn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
ints
:=
st
.
data
[
:
2
]
ints
:=
st
.
data
[
s
-
2
:
]
return
ints
[
0
],
ints
[
1
]
return
ints
[
0
],
ints
[
1
]
}
}
...
@@ -188,3 +212,45 @@ func (st *Stack) Print() {
...
@@ -188,3 +212,45 @@ func (st *Stack) Print() {
}
}
fmt
.
Println
(
"#############"
)
fmt
.
Println
(
"#############"
)
}
}
type
Memory
struct
{
store
[]
byte
}
func
(
m
*
Memory
)
Set
(
offset
,
size
int64
,
value
[]
byte
)
{
totSize
:=
offset
+
size
lenSize
:=
int64
(
len
(
m
.
store
)
-
1
)
if
totSize
>
lenSize
{
// Calculate the diff between the sizes
diff
:=
totSize
-
lenSize
if
diff
>
0
{
// Create a new empty slice and append it
newSlice
:=
make
([]
byte
,
diff
-
1
)
// Resize slice
m
.
store
=
append
(
m
.
store
,
newSlice
...
)
}
}
copy
(
m
.
store
[
offset
:
offset
+
size
],
value
)
}
func
(
m
*
Memory
)
Get
(
offset
,
size
int64
)
[]
byte
{
return
m
.
store
[
offset
:
offset
+
size
]
}
func
(
m
*
Memory
)
Len
()
int
{
return
len
(
m
.
store
)
}
func
(
m
*
Memory
)
Print
()
{
fmt
.
Println
(
"### MEM ###"
)
if
len
(
m
.
store
)
>
0
{
addr
:=
0
for
i
:=
0
;
i
+
32
<
len
(
m
.
store
);
i
+=
32
{
fmt
.
Printf
(
"%03d %v
\n
"
,
addr
,
m
.
store
[
i
:
i
+
32
])
addr
++
}
}
else
{
fmt
.
Println
(
"-- empty --"
)
}
fmt
.
Println
(
"###########"
)
}
ethchain/state.go
View file @
97786d03
...
@@ -63,8 +63,7 @@ func (s *State) GetContract(addr []byte) *Contract {
...
@@ -63,8 +63,7 @@ func (s *State) GetContract(addr []byte) *Contract {
}
}
// build contract
// build contract
contract
:=
&
Contract
{}
contract
:=
NewContractFromBytes
(
addr
,
[]
byte
(
data
))
contract
.
RlpDecode
([]
byte
(
data
))
// Check if there's a cached state for this contract
// Check if there's a cached state for this contract
cachedState
:=
s
.
states
[
string
(
addr
)]
cachedState
:=
s
.
states
[
string
(
addr
)]
...
@@ -78,27 +77,19 @@ func (s *State) GetContract(addr []byte) *Contract {
...
@@ -78,27 +77,19 @@ func (s *State) GetContract(addr []byte) *Contract {
return
contract
return
contract
}
}
func
(
s
*
State
)
UpdateContract
(
addr
[]
byte
,
contract
*
Contract
)
{
func
(
s
*
State
)
UpdateContract
(
contract
*
Contract
)
{
s
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
addr
:=
contract
.
Address
()
}
func
Compile
(
code
[]
string
)
(
script
[]
string
)
{
script
=
make
([]
string
,
len
(
code
))
for
i
,
val
:=
range
code
{
instr
,
_
:=
ethutil
.
CompileInstr
(
val
)
script
[
i
]
=
string
(
instr
)
}
return
s
.
states
[
string
(
addr
)]
=
contract
.
state
s
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
}
}
func
(
s
*
State
)
GetAccount
(
addr
[]
byte
)
(
account
*
Account
)
{
func
(
s
*
State
)
GetAccount
(
addr
[]
byte
)
(
account
*
Account
)
{
data
:=
s
.
trie
.
Get
(
string
(
addr
))
data
:=
s
.
trie
.
Get
(
string
(
addr
))
if
data
==
""
{
if
data
==
""
{
account
=
NewAccount
(
big
.
NewInt
(
0
))
account
=
NewAccount
(
addr
,
big
.
NewInt
(
0
))
}
else
{
}
else
{
account
=
NewAccountFromData
([]
byte
(
data
))
account
=
NewAccountFromData
(
addr
,
[]
byte
(
data
))
}
}
return
return
...
@@ -153,3 +144,35 @@ func (s *State) Get(key []byte) (*ethutil.Value, ObjType) {
...
@@ -153,3 +144,35 @@ func (s *State) Get(key []byte) (*ethutil.Value, ObjType) {
return
val
,
typ
return
val
,
typ
}
}
func
(
s
*
State
)
Put
(
key
,
object
[]
byte
)
{
s
.
trie
.
Update
(
string
(
key
),
string
(
object
))
}
func
(
s
*
State
)
Root
()
interface
{}
{
return
s
.
trie
.
Root
}
// Script compilation functions
// Compiles strings to machine code
func
Compile
(
code
[]
string
)
(
script
[]
string
)
{
script
=
make
([]
string
,
len
(
code
))
for
i
,
val
:=
range
code
{
instr
,
_
:=
ethutil
.
CompileInstr
(
val
)
script
[
i
]
=
string
(
instr
)
}
return
}
func
CompileToValues
(
code
[]
string
)
(
script
[]
*
ethutil
.
Value
)
{
script
=
make
([]
*
ethutil
.
Value
,
len
(
code
))
for
i
,
val
:=
range
code
{
instr
,
_
:=
ethutil
.
CompileInstr
(
val
)
script
[
i
]
=
ethutil
.
NewValue
(
instr
)
}
return
}
ethchain/state_manager.go
View file @
97786d03
...
@@ -308,18 +308,17 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
...
@@ -308,18 +308,17 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
}
}
}()
}()
*/
*/
caller
:=
sm
.
procState
.
GetAccount
(
tx
.
Sender
())
vm
:=
&
Vm
{}
closure
:=
NewClosure
(
caller
,
contract
,
sm
.
procState
,
tx
.
Gas
,
tx
.
Value
)
//vm.Process(contract, block.state, RuntimeVars{
vm
:=
NewVm
(
sm
.
procState
,
RuntimeVars
{
vm
.
Process
(
contract
,
sm
.
procState
,
RuntimeVars
{
origin
:
caller
.
Address
(),
address
:
tx
.
Hash
()[
12
:
],
blockNumber
:
block
.
BlockInfo
()
.
Number
,
blockNumber
:
block
.
BlockInfo
()
.
Number
,
sender
:
tx
.
Sender
(),
prevHash
:
block
.
PrevHash
,
prevHash
:
block
.
PrevHash
,
coinbase
:
block
.
Coinbase
,
coinbase
:
block
.
Coinbase
,
time
:
block
.
Time
,
time
:
block
.
Time
,
diff
:
block
.
Difficulty
,
diff
:
block
.
Difficulty
,
txValue
:
tx
.
Value
,
// XXX Tx data? Could be just an argument to the closure instead
txData
:
tx
.
Data
,
txData
:
nil
,
})
})
closure
.
Call
(
vm
,
nil
)
}
}
ethchain/transaction.go
View file @
97786d03
...
@@ -13,22 +13,31 @@ type Transaction struct {
...
@@ -13,22 +13,31 @@ type Transaction struct {
Nonce
uint64
Nonce
uint64
Recipient
[]
byte
Recipient
[]
byte
Value
*
big
.
Int
Value
*
big
.
Int
Gas
*
big
.
Int
Gasprice
*
big
.
Int
Data
[]
string
Data
[]
string
Memory
[]
int
v
byte
v
byte
r
,
s
[]
byte
r
,
s
[]
byte
}
}
func
NewTransaction
(
to
[]
byte
,
value
*
big
.
Int
,
data
[]
string
)
*
Transaction
{
func
NewTransaction
(
to
[]
byte
,
value
*
big
.
Int
,
data
[]
string
)
*
Transaction
{
tx
:=
Transaction
{
Recipient
:
to
,
Value
:
value
}
tx
:=
Transaction
{
Recipient
:
to
,
Value
:
value
,
Nonce
:
0
,
Data
:
data
}
tx
.
Nonce
=
0
// Serialize the data
tx
.
Data
=
data
return
&
tx
return
&
tx
}
}
func
NewContractCreationTx
(
value
,
gasprice
*
big
.
Int
,
data
[]
string
)
*
Transaction
{
return
&
Transaction
{
Value
:
value
,
Gasprice
:
gasprice
,
Data
:
data
}
}
func
NewContractMessageTx
(
to
[]
byte
,
value
,
gasprice
,
gas
*
big
.
Int
,
data
[]
string
)
*
Transaction
{
return
&
Transaction
{
Recipient
:
to
,
Value
:
value
,
Gasprice
:
gasprice
,
Gas
:
gas
,
Data
:
data
}
}
func
NewTx
(
to
[]
byte
,
value
*
big
.
Int
,
data
[]
string
)
*
Transaction
{
return
&
Transaction
{
Recipient
:
to
,
Value
:
value
,
Gasprice
:
big
.
NewInt
(
0
),
Gas
:
big
.
NewInt
(
0
),
Nonce
:
0
,
Data
:
data
}
}
// XXX Deprecated
// XXX Deprecated
func
NewTransactionFromData
(
data
[]
byte
)
*
Transaction
{
func
NewTransactionFromData
(
data
[]
byte
)
*
Transaction
{
return
NewTransactionFromBytes
(
data
)
return
NewTransactionFromBytes
(
data
)
...
...
ethchain/vm.go
View file @
97786d03
package
ethchain
package
ethchain
import
(
import
(
"bytes"
_
"bytes"
"fmt"
_
"fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go"
_
"github.com/obscuren/secp256k1-go"
"log"
"log"
"math"
_
"math"
"math/big"
"math/big"
)
)
...
@@ -18,122 +18,102 @@ type Vm struct {
...
@@ -18,122 +18,102 @@ type Vm struct {
mem
map
[
string
]
*
big
.
Int
mem
map
[
string
]
*
big
.
Int
vars
RuntimeVars
vars
RuntimeVars
state
*
State
}
}
type
RuntimeVars
struct
{
type
RuntimeVars
struct
{
address
[]
byte
origin
[]
byte
blockNumber
uint64
blockNumber
uint64
sender
[]
byte
prevHash
[]
byte
prevHash
[]
byte
coinbase
[]
byte
coinbase
[]
byte
time
int64
time
int64
diff
*
big
.
Int
diff
*
big
.
Int
txValue
*
big
.
Int
txData
[]
string
txData
[]
string
}
}
func
(
vm
*
Vm
)
Process
(
contract
*
Contract
,
state
*
State
,
vars
RuntimeVars
)
{
func
NewVm
(
state
*
State
,
vars
RuntimeVars
)
*
Vm
{
vm
.
mem
=
make
(
map
[
string
]
*
big
.
Int
)
return
&
Vm
{
vars
:
vars
,
state
:
state
}
vm
.
stack
=
NewStack
()
}
addr
:=
vars
.
address
// tx.Hash()[12:]
var
Pow256
=
ethutil
.
BigPow
(
2
,
256
)
// Instruction pointer
pc
:=
0
if
contract
==
nil
{
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
)
[]
byte
{
fmt
.
Println
(
"Contract not found"
)
// If the amount of gas supplied is less equal to 0
return
if
closure
.
Gas
.
Cmp
(
big
.
NewInt
(
0
))
<=
0
{
// TODO Do something
}
}
Pow256
:=
ethutil
.
BigPow
(
2
,
256
)
// Memory for the current closure
mem
:=
&
Memory
{}
// New stack (should this be shared?)
stack
:=
NewStack
()
// Instruction pointer
pc
:=
big
.
NewInt
(
0
)
// Current step count
step
:=
0
// The base for all big integer arithmetic
base
:=
new
(
big
.
Int
)
if
ethutil
.
Config
.
Debug
{
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
}
}
stepcount
:=
0
totalFee
:=
new
(
big
.
Int
)
out
:
for
{
for
{
stepcount
++
step
++
// The base big int for all calculations. Use this for any results.
// Get the memory location of pc
base
:=
new
(
big
.
Int
)
val
:=
closure
.
GetMem
(
pc
)
val
:=
contract
.
GetMem
(
pc
)
// Get the opcode (it must be an opcode!)
//fmt.Printf("%x = %d, %v %x\n", r, len(r), v, nb)
op
:=
OpCode
(
val
.
Uint
())
op
:=
OpCode
(
val
.
Uint
())
if
ethutil
.
Config
.
Debug
{
var
fee
*
big
.
Int
=
new
(
big
.
Int
)
ethutil
.
Config
.
Log
.
Debugf
(
"%-3d %-4s"
,
pc
,
op
.
String
())
var
fee2
*
big
.
Int
=
new
(
big
.
Int
)
if
stepcount
>
16
{
fee
.
Add
(
fee
,
StepFee
)
}
// Calculate the fees
switch
op
{
case
oSSTORE
:
y
,
x
:=
vm
.
stack
.
Peekn
()
val
:=
contract
.
Addr
(
ethutil
.
BigToBytes
(
x
,
256
))
if
val
.
IsEmpty
()
&&
len
(
y
.
Bytes
())
>
0
{
fee2
.
Add
(
DataFee
,
StoreFee
)
}
else
{
fee2
.
Sub
(
DataFee
,
StoreFee
)
}
case
oSLOAD
:
fee
.
Add
(
fee
,
StoreFee
)
case
oEXTRO
,
oBALANCE
:
fee
.
Add
(
fee
,
ExtroFee
)
case
oSHA256
,
oRIPEMD160
,
oECMUL
,
oECADD
,
oECSIGN
,
oECRECOVER
,
oECVALID
:
fee
.
Add
(
fee
,
CryptoFee
)
case
oMKTX
:
fee
.
Add
(
fee
,
ContractFee
)
}
}
tf
:=
new
(
big
.
Int
)
.
Add
(
fee
,
fee2
)
// TODO Get each instruction cost properly
if
contract
.
Amount
.
Cmp
(
tf
)
<
0
{
fee
:=
new
(
big
.
Int
)
fmt
.
Println
(
"Insufficient fees to continue running the contract"
,
tf
,
contract
.
Amount
)
fee
.
Add
(
fee
,
big
.
NewInt
(
1000
))
break
}
// Add the fee to the total fee. It's subtracted when we're done looping
totalFee
.
Add
(
totalFee
,
tf
)
if
ethutil
.
Config
.
Debug
{
if
closure
.
Gas
.
Cmp
(
fee
)
<
0
{
ethutil
.
Config
.
Log
.
Debugf
(
"%-3d %-4s"
,
pc
,
op
.
String
()
)
return
closure
.
Return
(
nil
)
}
}
switch
op
{
switch
op
{
case
oSTOP
:
case
oLOG
:
fmt
.
Println
(
""
)
stack
.
Print
()
break
out
mem
.
Print
()
case
oSTOP
:
// Stop the closure
return
closure
.
Return
(
nil
)
// 0x20 range
case
oADD
:
case
oADD
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
base
.
Add
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSUB
:
case
oSUB
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Sub
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oMUL
:
case
oMUL
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mul
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oDIV
:
case
oDIV
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// floor(x / y)
// floor(x / y)
base
.
Div
(
x
,
y
)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSDIV
:
case
oSDIV
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// n > 2**255
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
x
.
Sub
(
Pow256
,
x
)
...
@@ -147,13 +127,13 @@ out:
...
@@ -147,13 +127,13 @@ out:
z
.
Sub
(
Pow256
,
z
)
z
.
Sub
(
Pow256
,
z
)
}
}
// Push result on to the stack
// Push result on to the stack
vm
.
stack
.
Push
(
z
)
stack
.
Push
(
z
)
case
oMOD
:
case
oMOD
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
base
.
Mod
(
x
,
y
)
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oSMOD
:
case
oSMOD
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// n > 2**255
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
x
.
Sub
(
Pow256
,
x
)
...
@@ -167,213 +147,154 @@ out:
...
@@ -167,213 +147,154 @@ out:
z
.
Sub
(
Pow256
,
z
)
z
.
Sub
(
Pow256
,
z
)
}
}
// Push result on to the stack
// Push result on to the stack
vm
.
stack
.
Push
(
z
)
stack
.
Push
(
z
)
case
oEXP
:
case
oEXP
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
base
.
Exp
(
x
,
y
,
Pow256
)
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oNEG
:
case
oNEG
:
base
.
Sub
(
Pow256
,
vm
.
stack
.
Pop
())
base
.
Sub
(
Pow256
,
stack
.
Pop
())
vm
.
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
oLT
:
case
oLT
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// x < y
// x < y
if
x
.
Cmp
(
y
)
<
0
{
if
x
.
Cmp
(
y
)
<
0
{
vm
.
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
vm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oLE
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x <= y
if
x
.
Cmp
(
y
)
<
1
{
vm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oGT
:
case
oGT
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// x > y
// x > y
if
x
.
Cmp
(
y
)
>
0
{
if
x
.
Cmp
(
y
)
>
0
{
vm
.
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oGE
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x >= y
if
x
.
Cmp
(
y
)
>
-
1
{
vm
.
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
vm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oNOT
:
case
oNOT
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// x != y
// x != y
if
x
.
Cmp
(
y
)
!=
0
{
if
x
.
Cmp
(
y
)
!=
0
{
vm
.
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
case
oMYADDRESS
:
vm
.
stack
.
Push
(
ethutil
.
BigD
(
addr
))
case
oTXSENDER
:
vm
.
stack
.
Push
(
ethutil
.
BigD
(
vars
.
sender
))
case
oTXVALUE
:
vm
.
stack
.
Push
(
vars
.
txValue
)
case
oTXDATAN
:
vm
.
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
vars
.
txData
))))
case
oTXDATA
:
v
:=
vm
.
stack
.
Pop
()
// v >= len(data)
if
v
.
Cmp
(
big
.
NewInt
(
int64
(
len
(
vars
.
txData
))))
>=
0
{
vm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
))
}
else
{
vm
.
stack
.
Push
(
ethutil
.
Big
(
vars
.
txData
[
v
.
Uint64
()]))
}
case
oBLK_PREVHASH
:
vm
.
stack
.
Push
(
ethutil
.
BigD
(
vars
.
prevHash
))
case
oBLK_COINBASE
:
vm
.
stack
.
Push
(
ethutil
.
BigD
(
vars
.
coinbase
))
case
oBLK_TIMESTAMP
:
vm
.
stack
.
Push
(
big
.
NewInt
(
vars
.
time
))
case
oBLK_NUMBER
:
vm
.
stack
.
Push
(
big
.
NewInt
(
int64
(
vars
.
blockNumber
)))
case
oBLK_DIFFICULTY
:
vm
.
stack
.
Push
(
vars
.
diff
)
case
oBASEFEE
:
// e = 10^21
e
:=
big
.
NewInt
(
0
)
.
Exp
(
big
.
NewInt
(
10
),
big
.
NewInt
(
21
),
big
.
NewInt
(
0
))
d
:=
new
(
big
.
Rat
)
d
.
SetInt
(
vars
.
diff
)
c
:=
new
(
big
.
Rat
)
c
.
SetFloat64
(
0.5
)
// d = diff / 0.5
d
.
Quo
(
d
,
c
)
// base = floor(d)
base
.
Div
(
d
.
Num
(),
d
.
Denom
())
x
:=
new
(
big
.
Int
)
// 0x10 range
x
.
Div
(
e
,
base
)
case
oAND
:
case
oOR
:
case
oXOR
:
case
oBYTE
:
// x = floor(10^21 / floor(diff^0.5))
// 0x20 range
vm
.
stack
.
Push
(
x
)
case
oSHA3
:
case
oSHA256
,
oSHA3
,
oRIPEMD160
:
// This is probably save
// ceil(pop / 32)
length
:=
int
(
math
.
Ceil
(
float64
(
vm
.
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
(
vm
.
stack
.
Pop
()
.
Bytes
(),
256
)
data
.
WriteString
(
string
(
num
))
}
if
op
==
oSHA256
{
// 0x30 range
vm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Sha256Bin
(
data
.
Bytes
())))
case
oADDRESS
:
}
else
if
op
==
oSHA3
{
stack
.
Push
(
ethutil
.
BigD
(
closure
.
Object
()
.
Address
()))
vm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Sha3Bin
(
data
.
Bytes
())))
case
oBALANCE
:
}
else
{
stack
.
Push
(
closure
.
Value
)
vm
.
stack
.
Push
(
base
.
SetBytes
(
ethutil
.
Ripemd160
(
data
.
Bytes
())))
case
oORIGIN
:
}
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
origin
))
case
oECMUL
:
case
oCALLER
:
y
:=
vm
.
stack
.
Pop
()
stack
.
Push
(
ethutil
.
BigD
(
closure
.
Callee
()
.
Address
()))
x
:=
vm
.
stack
.
Pop
()
case
oCALLVALUE
:
//n := vm.stack.Pop()
// FIXME: Original value of the call, not the current value
stack
.
Push
(
closure
.
Value
)
case
oCALLDATA
:
offset
:=
stack
.
Pop
()
mem
.
Set
(
offset
.
Int64
(),
int64
(
len
(
closure
.
Args
)),
closure
.
Args
)
case
oCALLDATASIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Args
))))
case
oGASPRICE
:
// TODO
//if ethutil.Big(x).Cmp(ethutil.Big(y)) {
// 0x40 range
data
:=
new
(
bytes
.
Buffer
)
case
oPREVHASH
:
data
.
WriteString
(
x
.
String
())
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
prevHash
))
data
.
WriteString
(
y
.
String
())
case
oCOINBASE
:
if
secp256k1
.
VerifyPubkeyValidity
(
data
.
Bytes
())
==
1
{
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
coinbase
))
case
oTIMESTAMP
:
stack
.
Push
(
big
.
NewInt
(
vm
.
vars
.
time
))
case
oNUMBER
:
stack
.
Push
(
big
.
NewInt
(
int64
(
vm
.
vars
.
blockNumber
)))
case
oDIFFICULTY
:
stack
.
Push
(
vm
.
vars
.
diff
)
case
oGASLIMIT
:
// TODO
// TODO
}
else
{
// Invalid, push infinity
vm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
))
vm
.
stack
.
Push
(
ethutil
.
Big
(
"0"
))
}
//} else {
// // Invalid, push infinity
// vm.stack.Push("0")
// vm.stack.Push("0")
//}
case
oECADD
:
// 0x50 range
case
oECSIGN
:
case
oPUSH
:
// Push PC+1 on to the stack
case
oECRECOVER
:
pc
.
Add
(
pc
,
ethutil
.
Big1
)
case
oECVALID
:
case
oPUSH
:
val
:=
closure
.
GetMem
(
pc
)
.
BigInt
()
pc
++
stack
.
Push
(
val
)
vm
.
stack
.
Push
(
contract
.
GetMem
(
pc
)
.
BigInt
())
case
oPOP
:
case
oPOP
:
// Pop current value of the stack
stack
.
Pop
()
vm
.
stack
.
Pop
()
case
oDUP
:
case
oDUP
:
// Dup top stack
stack
.
Push
(
stack
.
Peek
())
x
:=
vm
.
stack
.
Pop
()
vm
.
stack
.
Push
(
x
)
vm
.
stack
.
Push
(
x
)
case
oSWAP
:
case
oSWAP
:
// Swap two top most values
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
stack
.
Push
(
y
)
vm
.
stack
.
Push
(
y
)
stack
.
Push
(
x
)
vm
.
stack
.
Push
(
x
)
case
oMLOAD
:
case
oMLOAD
:
x
:=
vm
.
stack
.
Pop
()
offset
:=
stack
.
Pop
()
vm
.
stack
.
Push
(
vm
.
mem
[
x
.
String
()])
stack
.
Push
(
ethutil
.
BigD
(
mem
.
Get
(
offset
.
Int64
(),
32
)))
case
oMSTORE
:
case
oMSTORE
:
// Store the value at stack top-1 in to memory at location stack top
x
,
y
:=
vm
.
stack
.
Popn
()
// Pop value of the stack
vm
.
mem
[
x
.
String
()]
=
y
val
,
mStart
:=
stack
.
Popn
()
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
case
oMSTORE8
:
val
,
mStart
:=
stack
.
Popn
()
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
case
oSLOAD
:
case
oSLOAD
:
// Load the value in storage and push it on the stack
loc
:=
stack
.
Pop
()
x
:=
vm
.
stack
.
Pop
()
val
:=
closure
.
GetMem
(
loc
)
// decode the object as a big integer
stack
.
Push
(
val
.
BigInt
())
decoder
:=
contract
.
Addr
(
x
.
Bytes
())
if
!
decoder
.
IsNil
()
{
vm
.
stack
.
Push
(
decoder
.
BigInt
())
}
else
{
vm
.
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
oSSTORE
:
case
oSSTORE
:
// Store Y at index X
val
,
loc
:=
stack
.
Popn
()
y
,
x
:=
vm
.
stack
.
Popn
()
closure
.
SetMem
(
loc
,
ethutil
.
NewValue
(
val
))
addr
:=
ethutil
.
BigToBytes
(
x
,
256
)
case
oJUMP
:
fmt
.
Printf
(
" => %x (%v) @ %v"
,
y
.
Bytes
(),
y
,
ethutil
.
BigD
(
addr
))
pc
=
stack
.
Pop
()
contract
.
SetAddr
(
addr
,
y
)
case
oJUMPI
:
//contract.State().Update(string(idx), string(y))
pos
,
cond
:=
stack
.
Popn
()
case
oJMP
:
if
cond
.
Cmp
(
big
.
NewInt
(
0
))
>
0
{
x
:=
int
(
vm
.
stack
.
Pop
()
.
Uint64
())
pc
=
pos
// Set pc to x - 1 (minus one so the incrementing at the end won't effect it)
pc
=
x
pc
--
case
oJMPI
:
x
:=
vm
.
stack
.
Pop
()
// Set pc to x if it's non zero
if
x
.
Cmp
(
ethutil
.
BigFalse
)
!=
0
{
pc
=
int
(
x
.
Uint64
())
pc
--
}
}
case
oIND
:
case
oPC
:
vm
.
stack
.
Push
(
big
.
NewInt
(
int64
(
pc
)))
stack
.
Push
(
pc
)
case
oEXTRO
:
case
oMSIZE
:
memAddr
:=
vm
.
stack
.
Pop
()
stack
.
Push
(
big
.
NewInt
(
int64
(
mem
.
Len
())))
contractAddr
:=
vm
.
stack
.
Pop
()
.
Bytes
()
// 0x60 range
case
oCALL
:
// Pop return size and offset
retSize
,
retOffset
:=
stack
.
Popn
()
// Pop input size and offset
inSize
,
inOffset
:=
stack
.
Popn
()
// Get the arguments from the memory
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
// Pop gas and value of the stack.
gas
,
value
:=
stack
.
Popn
()
// Closure addr
addr
:=
stack
.
Pop
()
// Fetch the contract which will serve as the closure body
contract
:=
vm
.
state
.
GetContract
(
addr
.
Bytes
())
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
contract
,
vm
.
state
,
gas
,
value
)
// Executer the closure and get the return value (if any)
ret
:=
closure
.
Call
(
vm
,
args
)
// Push the contract's memory on to the stack
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
vm
.
stack
.
Push
(
contractMemory
(
state
,
contractAddr
,
memAddr
))
case
oRETURN
:
case
oBALANCE
:
size
,
offset
:=
stack
.
Popn
()
// Pushes the balance of the popped value on to the stack
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
account
:=
state
.
GetAccount
(
vm
.
stack
.
Pop
()
.
Bytes
())
vm
.
stack
.
Push
(
account
.
Amount
)
case
oMKTX
:
addr
,
value
:=
vm
.
stack
.
Popn
()
from
,
length
:=
vm
.
stack
.
Popn
()
makeInlineTx
(
addr
.
Bytes
(),
value
,
from
,
length
,
contract
,
state
)
return
closure
.
Return
(
ret
)
case
oSUICIDE
:
case
oSUICIDE
:
recAddr
:=
vm
.
stack
.
Pop
()
.
Bytes
()
/*
recAddr := stack.Pop().Bytes()
// Purge all memory
// Purge all memory
deletedMemory := contract.state.Purge()
deletedMemory := contract.state.Purge()
// Add refunds to the pop'ed address
// Add refunds to the pop'ed address
...
@@ -387,30 +308,28 @@ out:
...
@@ -387,30 +308,28 @@ out:
ethutil.Config.Log.Debugf("(%d) => %x\n", deletedMemory, recAddr)
ethutil.Config.Log.Debugf("(%d) => %x\n", deletedMemory, recAddr)
break out
break out
*/
default
:
default
:
fmt
.
Printf
(
"Invalid OPCODE: %x
\n
"
,
op
)
ethutil
.
Config
.
Log
.
Debugln
(
"Invalid opcode"
,
op
)
}
ethutil
.
Config
.
Log
.
Debugln
(
""
)
//vm.stack.Print()
pc
++
}
}
state
.
UpdateContract
(
addr
,
contract
)
pc
.
Add
(
pc
,
ethutil
.
Big1
)
}
}
}
func
makeInlineTx
(
addr
[]
byte
,
value
,
from
,
length
*
big
.
Int
,
contract
*
Contract
,
state
*
State
)
{
func
makeInlineTx
(
addr
[]
byte
,
value
,
from
,
length
*
big
.
Int
,
contract
*
Contract
,
state
*
State
)
{
ethutil
.
Config
.
Log
.
Debugf
(
" => creating inline tx %x %v %v %v"
,
addr
,
value
,
from
,
length
)
ethutil
.
Config
.
Log
.
Debugf
(
" => creating inline tx %x %v %v %v"
,
addr
,
value
,
from
,
length
)
j
:=
0
j
:=
int64
(
0
)
dataItems
:=
make
([]
string
,
int
(
length
.
Uint64
()))
dataItems
:=
make
([]
string
,
int
(
length
.
Uint64
()))
for
i
:=
from
.
Uint64
();
i
<
length
.
Ui
nt64
();
i
++
{
for
i
:=
from
.
Int64
();
i
<
length
.
I
nt64
();
i
++
{
dataItems
[
j
]
=
contract
.
GetMem
(
j
)
.
Str
()
dataItems
[
j
]
=
contract
.
GetMem
(
big
.
NewInt
(
j
)
)
.
Str
()
j
++
j
++
}
}
tx
:=
NewTransaction
(
addr
,
value
,
dataItems
)
tx
:=
NewTransaction
(
addr
,
value
,
dataItems
)
if
tx
.
IsContract
()
{
if
tx
.
IsContract
()
{
contract
:=
MakeContract
(
tx
,
state
)
contract
:=
MakeContract
(
tx
,
state
)
state
.
UpdateContract
(
tx
.
Hash
()[
12
:
],
contract
)
state
.
UpdateContract
(
contract
)
}
else
{
}
else
{
account
:=
state
.
GetAccount
(
tx
.
Recipient
)
account
:=
state
.
GetAccount
(
tx
.
Recipient
)
account
.
Amount
.
Add
(
account
.
Amount
,
tx
.
Value
)
account
.
Amount
.
Add
(
account
.
Amount
,
tx
.
Value
)
...
...
ethchain/vm_test.go
View file @
97786d03
package
ethchain
package
ethchain
import
(
import
(
"
fmt
"
"
bytes
"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"math/big"
"testing"
"testing"
)
)
/*
func TestRun(t *testing.T) {
func TestRun(t *testing.T) {
InitFees()
InitFees()
...
@@ -104,3 +106,69 @@ func TestRun2(t *testing.T) {
...
@@ -104,3 +106,69 @@ func TestRun2(t *testing.T) {
txData: tx.Data,
txData: tx.Data,
})
})
}
}
*/
// XXX Full stack test
func
TestRun3
(
t
*
testing
.
T
)
{
ethutil
.
ReadConfig
(
""
)
db
,
_
:=
ethdb
.
NewMemDatabase
()
state
:=
NewState
(
ethutil
.
NewTrie
(
db
,
""
))
script
:=
Compile
([]
string
{
"PUSH"
,
"300"
,
"PUSH"
,
"0"
,
"MSTORE"
,
"PUSH"
,
"32"
,
"CALLDATA"
,
"PUSH"
,
"64"
,
"PUSH"
,
"0"
,
"RETURN"
,
})
tx
:=
NewTransaction
(
ContractAddr
,
ethutil
.
Big
(
"100000000000000000000000000000000000000000000000000"
),
script
)
addr
:=
tx
.
Hash
()[
12
:
]
contract
:=
MakeContract
(
tx
,
state
)
state
.
UpdateContract
(
contract
)
callerScript
:=
ethutil
.
Compile
(
"PUSH"
,
1337
,
// Argument
"PUSH"
,
65
,
// argument mem offset
"MSTORE"
,
"PUSH"
,
64
,
// ret size
"PUSH"
,
0
,
// ret offset
"PUSH"
,
32
,
// arg size
"PUSH"
,
65
,
// arg offset
"PUSH"
,
1000
,
/// Gas
"PUSH"
,
0
,
/// value
"PUSH"
,
addr
,
// Sender
"CALL"
,
"PUSH"
,
64
,
"PUSH"
,
0
,
"RETURN"
,
)
callerTx
:=
NewTransaction
(
ContractAddr
,
ethutil
.
Big
(
"100000000000000000000000000000000000000000000000000"
),
callerScript
)
// Contract addr as test address
account
:=
NewAccount
(
ContractAddr
,
big
.
NewInt
(
10000000
))
callerClosure
:=
NewClosure
(
account
,
MakeContract
(
callerTx
,
state
),
state
,
big
.
NewInt
(
1000000000
),
new
(
big
.
Int
))
vm
:=
NewVm
(
state
,
RuntimeVars
{
origin
:
account
.
Address
(),
blockNumber
:
1
,
prevHash
:
ethutil
.
FromHex
(
"5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
),
coinbase
:
ethutil
.
FromHex
(
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
),
time
:
1
,
diff
:
big
.
NewInt
(
256
),
// XXX Tx data? Could be just an argument to the closure instead
txData
:
nil
,
})
ret
:=
callerClosure
.
Call
(
vm
,
nil
)
exp
:=
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
44
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
5
,
57
}
if
bytes
.
Compare
(
ret
,
exp
)
!=
0
{
t
.
Errorf
(
"expected return value to be %v, got %v"
,
exp
,
ret
)
}
}
ethutil/common.go
View file @
97786d03
...
@@ -33,3 +33,9 @@ func CurrencyToString(num *big.Int) string {
...
@@ -33,3 +33,9 @@ func CurrencyToString(num *big.Int) string {
return
fmt
.
Sprintf
(
"%v Wei"
,
num
)
return
fmt
.
Sprintf
(
"%v Wei"
,
num
)
}
}
var
(
Big1
=
big
.
NewInt
(
1
)
Big0
=
big
.
NewInt
(
0
)
Big256
=
big
.
NewInt
(
0xff
)
)
ethutil/config.go
View file @
97786d03
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"os"
"os"
"os/user"
"os/user"
"path"
"path"
"runtime"
)
)
type
LogType
byte
type
LogType
byte
...
@@ -23,6 +24,7 @@ type config struct {
...
@@ -23,6 +24,7 @@ type config struct {
ExecPath
string
ExecPath
string
Debug
bool
Debug
bool
Ver
string
Ver
string
ClientString
string
Pubkey
[]
byte
Pubkey
[]
byte
Seed
bool
Seed
bool
}
}
...
@@ -48,11 +50,16 @@ func ReadConfig(base string) *config {
...
@@ -48,11 +50,16 @@ func ReadConfig(base string) *config {
Config
=
&
config
{
ExecPath
:
path
,
Debug
:
true
,
Ver
:
"0.3.1"
}
Config
=
&
config
{
ExecPath
:
path
,
Debug
:
true
,
Ver
:
"0.3.1"
}
Config
.
Log
=
NewLogger
(
LogFile
|
LogStd
,
LogLevelDebug
)
Config
.
Log
=
NewLogger
(
LogFile
|
LogStd
,
LogLevelDebug
)
Config
.
SetClientString
(
"/Ethereum(G)"
)
}
}
return
Config
return
Config
}
}
func
(
c
*
config
)
SetClientString
(
str
string
)
{
Config
.
ClientString
=
fmt
.
Sprintf
(
"%s nv%s/%s"
,
str
,
c
.
Ver
,
runtime
.
GOOS
)
}
type
LoggerType
byte
type
LoggerType
byte
const
(
const
(
...
...
ethutil/parsing.go
View file @
97786d03
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
// Op codes
// Op codes
var
OpCodes
=
map
[
string
]
byte
{
var
OpCodes
=
map
[
string
]
byte
{
// 0x0 range - arithmetic ops
"STOP"
:
0x00
,
"STOP"
:
0x00
,
"ADD"
:
0x01
,
"ADD"
:
0x01
,
"MUL"
:
0x02
,
"MUL"
:
0x02
,
...
@@ -18,46 +19,60 @@ var OpCodes = map[string]byte{
...
@@ -18,46 +19,60 @@ var OpCodes = map[string]byte{
"EXP"
:
0x08
,
"EXP"
:
0x08
,
"NEG"
:
0x09
,
"NEG"
:
0x09
,
"LT"
:
0x0a
,
"LT"
:
0x0a
,
"LE"
:
0x0b
,
"GT"
:
0x0b
,
"GT"
:
0x0c
,
"EQ"
:
0x0c
,
"GE"
:
0x0d
,
"NOT"
:
0x0d
,
"EQ"
:
0x0e
,
"NOT"
:
0x0f
,
// 0x10 range - bit ops
"MYADDRESS"
:
0x10
,
"AND"
:
0x10
,
"TXSENDER"
:
0x11
,
"OR"
:
0x11
,
"TXVALUE"
:
0x12
,
"XOR"
:
0x12
,
"TXDATAN"
:
0x13
,
"BYTE"
:
0x13
,
"TXDATA"
:
0x14
,
"BLK_PREVHASH"
:
0x15
,
// 0x20 range - crypto
"BLK_COINBASE"
:
0x16
,
"SHA3"
:
0x20
,
"BLK_TIMESTAMP"
:
0x17
,
"BLK_NUMBER"
:
0x18
,
// 0x30 range - closure state
"BLK_DIFFICULTY"
:
0x19
,
"ADDRESS"
:
0x30
,
"BLK_NONCE"
:
0x1a
,
"BALANCE"
:
0x31
,
"BASEFEE"
:
0x1b
,
"ORIGIN"
:
0x32
,
"SHA256"
:
0x20
,
"CALLER"
:
0x33
,
"RIPEMD160"
:
0x21
,
"CALLVALUE"
:
0x34
,
"ECMUL"
:
0x22
,
"CALLDATA"
:
0x35
,
"ECADD"
:
0x23
,
"CALLDATASIZE"
:
0x36
,
"ECSIGN"
:
0x24
,
"GASPRICE"
:
0x38
,
"ECRECOVER"
:
0x25
,
"ECVALID"
:
0x26
,
// 0x40 range - block operations
"SHA3"
:
0x27
,
"PREVHASH"
:
0x40
,
"PUSH"
:
0x30
,
"COINBASE"
:
0x41
,
"POP"
:
0x31
,
"TIMESTAMP"
:
0x42
,
"DUP"
:
0x32
,
"NUMBER"
:
0x43
,
"SWAP"
:
0x33
,
"DIFFICULTY"
:
0x44
,
"MLOAD"
:
0x34
,
"GASLIMIT"
:
0x45
,
"MSTORE"
:
0x35
,
"SLOAD"
:
0x36
,
// 0x50 range - 'storage' and execution
"SSTORE"
:
0x37
,
"PUSH"
:
0x50
,
"JMP"
:
0x38
,
"POP"
:
0x51
,
"JMPI"
:
0x39
,
"DUP"
:
0x52
,
"IND"
:
0x3a
,
"SWAP"
:
0x53
,
"EXTRO"
:
0x3b
,
"MLOAD"
:
0x54
,
"BALANCE"
:
0x3c
,
"MSTORE"
:
0x55
,
"MKTX"
:
0x3d
,
"MSTORE8"
:
0x56
,
"SUICIDE"
:
0x3f
,
"SLOAD"
:
0x57
,
"SSTORE"
:
0x58
,
"JUMP"
:
0x59
,
"JUMPI"
:
0x5a
,
"PC"
:
0x5b
,
"MSIZE"
:
0x5c
,
// 0x60 range - closures
"CREATE"
:
0x60
,
"CALL"
:
0x61
,
"RETURN"
:
0x62
,
// 0x70 range - other
"LOG"
:
0x70
,
"SUICIDE"
:
0x7f
,
}
}
func
IsOpCode
(
s
string
)
bool
{
func
IsOpCode
(
s
string
)
bool
{
...
@@ -69,16 +84,30 @@ func IsOpCode(s string) bool {
...
@@ -69,16 +84,30 @@ func IsOpCode(s string) bool {
return
false
return
false
}
}
func
CompileInstr
(
s
string
)
([]
byte
,
error
)
{
func
CompileInstr
(
s
interface
{})
([]
byte
,
error
)
{
isOp
:=
IsOpCode
(
s
)
switch
s
.
(
type
)
{
case
string
:
str
:=
s
.
(
string
)
isOp
:=
IsOpCode
(
str
)
if
isOp
{
if
isOp
{
return
[]
byte
{
OpCodes
[
s
]},
nil
return
[]
byte
{
OpCodes
[
str
]},
nil
}
}
num
:=
new
(
big
.
Int
)
num
:=
new
(
big
.
Int
)
num
.
SetString
(
s
,
0
)
_
,
success
:=
num
.
SetString
(
str
,
0
)
// Assume regular bytes during compilation
if
!
success
{
num
.
SetBytes
([]
byte
(
str
))
}
return
num
.
Bytes
(),
nil
return
num
.
Bytes
(),
nil
case
int
:
return
big
.
NewInt
(
int64
(
s
.
(
int
)))
.
Bytes
(),
nil
case
[]
byte
:
return
BigD
(
s
.
([]
byte
))
.
Bytes
(),
nil
}
return
nil
,
nil
}
}
func
Instr
(
instr
string
)
(
int
,
[]
string
,
error
)
{
func
Instr
(
instr
string
)
(
int
,
[]
string
,
error
)
{
...
@@ -99,3 +128,17 @@ func Instr(instr string) (int, []string, error) {
...
@@ -99,3 +128,17 @@ func Instr(instr string) (int, []string, error) {
return
op
,
args
[
1
:
7
],
nil
return
op
,
args
[
1
:
7
],
nil
}
}
// Script compilation functions
// Compiles strings to machine code
func
Compile
(
instructions
...
interface
{})
(
script
[]
string
)
{
script
=
make
([]
string
,
len
(
instructions
))
for
i
,
val
:=
range
instructions
{
instr
,
_
:=
CompileInstr
(
val
)
script
[
i
]
=
string
(
instr
)
}
return
}
ethutil/rlp.go
View file @
97786d03
...
@@ -9,6 +9,10 @@ import (
...
@@ -9,6 +9,10 @@ import (
"math/big"
"math/big"
)
)
type
RlpEncodable
interface
{
RlpEncode
()
[]
byte
}
type
RlpEncoder
struct
{
type
RlpEncoder
struct
{
rlpData
[]
byte
rlpData
[]
byte
}
}
...
...
ethutil/trie_test.go
View file @
97786d03
package
ethutil
package
ethutil
import
(
import
(
"fmt"
"reflect"
"reflect"
"testing"
"testing"
)
)
...
...
peer.go
View file @
97786d03
...
@@ -7,7 +7,6 @@ import (
...
@@ -7,7 +7,6 @@ import (
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"github.com/ethereum/eth-go/ethwire"
"net"
"net"
"runtime"
"strconv"
"strconv"
"strings"
"strings"
"sync/atomic"
"sync/atomic"
...
@@ -160,7 +159,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
...
@@ -160,7 +159,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
connected
:
0
,
connected
:
0
,
disconnect
:
0
,
disconnect
:
0
,
caps
:
caps
,
caps
:
caps
,
Version
:
fmt
.
Sprintf
(
"/Ethereum(G) v%s/%s"
,
ethutil
.
Config
.
Ver
,
runtime
.
GOOS
)
,
Version
:
ethutil
.
Config
.
ClientString
,
}
}
// Set up the connection in another goroutine so we don't block the main thread
// Set up the connection in another goroutine so we don't block the main thread
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment