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
Expand all
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
Ethereum Go Development package (C) Jeffrey Wilcke
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
individual package for more information.
...
...
ethchain/address.go
View file @
97786d03
...
...
@@ -6,23 +6,39 @@ import (
)
type
Account
struct
{
address
[]
byte
Amount
*
big
.
Int
Nonce
uint64
}
func
NewAccount
(
amount
*
big
.
Int
)
*
Account
{
return
&
Account
{
Amount
:
amount
,
Nonce
:
0
}
func
NewAccount
(
a
ddress
[]
byte
,
a
mount
*
big
.
Int
)
*
Account
{
return
&
Account
{
address
,
amount
,
0
}
}
func
NewAccountFromData
(
data
[]
byte
)
*
Account
{
a
ddress
:=
&
Account
{
}
a
ddress
.
RlpDecode
(
data
)
func
NewAccountFromData
(
address
,
data
[]
byte
)
*
Account
{
a
ccount
:=
&
Account
{
address
:
address
}
a
ccount
.
RlpDecode
(
data
)
return
a
ddress
return
a
ccount
}
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
{
...
...
ethchain/block.go
View file @
97786d03
...
...
@@ -142,7 +142,7 @@ func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
data
:=
block
.
state
.
trie
.
Get
(
string
(
block
.
Coinbase
))
// 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
)
ether
.
Amount
=
base
.
Add
(
ether
.
Amount
,
fee
)
...
...
ethchain/block_manager_test.go
View file @
97786d03
package
ethchain
/*
import (
_ "fmt"
"github.com/ethereum/eth-go/ethdb"
...
...
@@ -14,9 +15,10 @@ func TestVm(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
ethutil.Config.Db = db
bm
:=
New
Block
Manager
(
nil
)
bm := New
State
Manager(nil)
block := bm.bc.genesisBlock
bm.Prepare(block.State(), block.State())
script := Compile([]string{
"PUSH",
"1",
...
...
@@ -31,3 +33,4 @@ func TestVm(t *testing.T) {
tx2.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
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 {
Nonce
uint64
//state *ethutil.Trie
state
*
State
address
[]
byte
}
func
NewContract
(
Amount
*
big
.
Int
,
root
[]
byte
)
*
Contract
{
contract
:=
&
Contract
{
Amount
:
Amount
,
Nonce
:
0
}
func
NewContract
(
address
[]
byte
,
Amount
*
big
.
Int
,
root
[]
byte
)
*
Contract
{
contract
:=
&
Contract
{
address
:
address
,
Amount
:
Amount
,
Nonce
:
0
}
contract
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
string
(
root
)))
return
contract
}
func
(
c
*
Contract
)
RlpEncode
()
[]
byte
{
return
ethutil
.
Encode
([]
interface
{}{
c
.
Amount
,
c
.
Nonce
,
c
.
state
.
trie
.
Root
})
}
func
NewContractFromBytes
(
address
,
data
[]
byte
)
*
Contract
{
contract
:=
&
Contract
{
address
:
address
}
contract
.
RlpDecode
(
data
)
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
()))
return
contract
}
func
(
c
*
Contract
)
Addr
(
addr
[]
byte
)
*
ethutil
.
Value
{
...
...
@@ -43,19 +39,45 @@ func (c *Contract) State() *State {
return
c
.
state
}
func
(
c
*
Contract
)
GetMem
(
num
i
nt
)
*
ethutil
.
Value
{
nb
:=
ethutil
.
BigToBytes
(
big
.
NewInt
(
int64
(
num
))
,
256
)
func
(
c
*
Contract
)
GetMem
(
num
*
big
.
I
nt
)
*
ethutil
.
Value
{
nb
:=
ethutil
.
BigToBytes
(
num
,
256
)
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
{
// Create contract if there's no recipient
if
tx
.
IsContract
()
{
addr
:=
tx
.
Hash
()[
12
:
]
value
:=
tx
.
Value
contract
:=
NewContract
(
value
,
[]
byte
(
""
))
contract
:=
NewContract
(
addr
,
value
,
[]
byte
(
""
))
state
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
for
i
,
val
:=
range
tx
.
Data
{
if
len
(
val
)
>
0
{
...
...
ethchain/stack.go
View file @
97786d03
...
...
@@ -2,6 +2,7 @@ package ethchain
import
(
"fmt"
_
"github.com/ethereum/eth-go/ethutil"
"math/big"
)
...
...
@@ -9,6 +10,7 @@ type OpCode int
// Op codes
const
(
// 0x0 range - arithmetic ops
oSTOP
=
0x00
oADD
=
0x01
oMUL
=
0x02
...
...
@@ -20,50 +22,65 @@ const (
oEXP
=
0x08
oNEG
=
0x09
oLT
=
0x0a
oLE
=
0x0b
oGT
=
0x0c
oGE
=
0x0d
oEQ
=
0x0e
oNOT
=
0x0f
oMYADDRESS
=
0x10
oTXSENDER
=
0x11
oTXVALUE
=
0x12
oTXDATAN
=
0x13
oTXDATA
=
0x14
oBLK_PREVHASH
=
0x15
oBLK_COINBASE
=
0x16
oBLK_TIMESTAMP
=
0x17
oBLK_NUMBER
=
0x18
oBLK_DIFFICULTY
=
0x19
oBLK_NONCE
=
0x1a
oBASEFEE
=
0x1b
oSHA256
=
0x20
oRIPEMD160
=
0x21
oECMUL
=
0x22
oECADD
=
0x23
oECSIGN
=
0x24
oECRECOVER
=
0x25
oECVALID
=
0x26
oSHA3
=
0x27
oPUSH
=
0x30
oPOP
=
0x31
oDUP
=
0x32
oSWAP
=
0x33
oMLOAD
=
0x34
oMSTORE
=
0x35
oSLOAD
=
0x36
oSSTORE
=
0x37
oJMP
=
0x38
oJMPI
=
0x39
oIND
=
0x3a
oEXTRO
=
0x3b
oBALANCE
=
0x3c
oMKTX
=
0x3d
oSUICIDE
=
0x3f
oGT
=
0x0b
oEQ
=
0x0c
oNOT
=
0x0d
// 0x10 range - bit ops
oAND
=
0x10
oOR
=
0x11
oXOR
=
0x12
oBYTE
=
0x13
// 0x20 range - crypto
oSHA3
=
0x20
// 0x30 range - closure state
oADDRESS
=
0x30
oBALANCE
=
0x31
oORIGIN
=
0x32
oCALLER
=
0x33
oCALLVALUE
=
0x34
oCALLDATA
=
0x35
oCALLDATASIZE
=
0x36
oGASPRICE
=
0x37
// 0x40 range - block operations
oPREVHASH
=
0x40
oCOINBASE
=
0x41
oTIMESTAMP
=
0x42
oNUMBER
=
0x43
oDIFFICULTY
=
0x44
oGASLIMIT
=
0x45
// 0x50 range - 'storage' and execution
oPUSH
=
0x50
oPOP
=
0x51
oDUP
=
0x52
oSWAP
=
0x53
oMLOAD
=
0x54
oMSTORE
=
0x55
oMSTORE8
=
0x56
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
var
opCodeToString
=
map
[
OpCode
]
string
{
// 0x0 range - arithmetic ops
oSTOP
:
"STOP"
,
oADD
:
"ADD"
,
oMUL
:
"MUL"
,
...
...
@@ -75,44 +92,59 @@ var opCodeToString = map[OpCode]string{
oEXP
:
"EXP"
,
oNEG
:
"NEG"
,
oLT
:
"LT"
,
oLE
:
"LE"
,
oGT
:
"GT"
,
oGE
:
"GE"
,
oEQ
:
"EQ"
,
oNOT
:
"NOT"
,
oMYADDRESS
:
"MYADDRESS"
,
oTXSENDER
:
"TXSENDER"
,
oTXVALUE
:
"TXVALUE"
,
oTXDATAN
:
"TXDATAN"
,
oTXDATA
:
"TXDATA"
,
oBLK_PREVHASH
:
"BLK_PREVHASH"
,
oBLK_COINBASE
:
"BLK_COINBASE"
,
oBLK_TIMESTAMP
:
"BLK_TIMESTAMP"
,
oBLK_NUMBER
:
"BLK_NUMBER"
,
oBLK_DIFFICULTY
:
"BLK_DIFFICULTY"
,
oBASEFEE
:
"BASEFEE"
,
oSHA256
:
"SHA256"
,
oRIPEMD160
:
"RIPEMD160"
,
oECMUL
:
"ECMUL"
,
oECADD
:
"ECADD"
,
oECSIGN
:
"ECSIGN"
,
oECRECOVER
:
"ECRECOVER"
,
oECVALID
:
"ECVALID"
,
// 0x10 range - bit ops
oAND
:
"AND"
,
oOR
:
"OR"
,
oXOR
:
"XOR"
,
oBYTE
:
"BYTE"
,
// 0x20 range - crypto
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"
,
oPOP
:
"POP"
,
oDUP
:
"DUP"
,
oSWAP
:
"SWAP"
,
oMLOAD
:
"MLOAD"
,
oMSTORE
:
"MSTORE"
,
oMSTORE8
:
"MSTORE8"
,
oSLOAD
:
"SLOAD"
,
oSSTORE
:
"SSTORE"
,
oJMP
:
"JMP"
,
oJMPI
:
"JMPI"
,
oIND
:
"IND"
,
oEXTRO
:
"EXTRO"
,
oBALANCE
:
"BALANCE"
,
oMKTX
:
"MKTX"
,
oJUMP
:
"JUMP"
,
oJUMPI
:
"JUMPI"
,
oPC
:
"PC"
,
oMSIZE
:
"MSIZE"
,
// 0x60 range - closures
oCREATE
:
"CREATE"
,
oCALL
:
"CALL"
,
oRETURN
:
"RETURN"
,
// 0x70 range - other
oLOG
:
"LOG"
,
oSUICIDE
:
"SUICIDE"
,
}
...
...
@@ -141,35 +173,27 @@ func NewStack() *Stack {
}
func
(
st
*
Stack
)
Pop
()
*
big
.
Int
{
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
s
-
1
]
st
.
data
=
st
.
data
[
:
s
-
1
]
str
:=
st
.
data
[
0
]
st
.
data
=
st
.
data
[
1
:
]
return
str
}
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
ints
:=
st
.
data
[
s
-
2
:
]
st
.
data
=
st
.
data
[
:
s
-
2
]
ints
:=
st
.
data
[
:
2
]
st
.
data
=
st
.
data
[
2
:
]
return
ints
[
0
],
ints
[
1
]
}
func
(
st
*
Stack
)
Peek
()
*
big
.
Int
{
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
s
-
1
]
str
:=
st
.
data
[
0
]
return
str
}
func
(
st
*
Stack
)
Peekn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
ints
:=
st
.
data
[
s
-
2
:
]
ints
:=
st
.
data
[
:
2
]
return
ints
[
0
],
ints
[
1
]
}
...
...
@@ -188,3 +212,45 @@ func (st *Stack) Print() {
}
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 {
}
// build contract
contract
:=
&
Contract
{}
contract
.
RlpDecode
([]
byte
(
data
))
contract
:=
NewContractFromBytes
(
addr
,
[]
byte
(
data
))
// Check if there's a cached state for this contract
cachedState
:=
s
.
states
[
string
(
addr
)]
...
...
@@ -78,27 +77,19 @@ func (s *State) GetContract(addr []byte) *Contract {
return
contract
}
func
(
s
*
State
)
UpdateContract
(
addr
[]
byte
,
contract
*
Contract
)
{
s
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
}
func
Compile
(
code
[]
string
)
(
script
[]
string
)
{
script
=
make
([]
string
,
len
(
code
))
for
i
,
val
:=
range
code
{
instr
,
_
:=
ethutil
.
CompileInstr
(
val
)
script
[
i
]
=
string
(
instr
)
}
func
(
s
*
State
)
UpdateContract
(
contract
*
Contract
)
{
addr
:=
contract
.
Address
()
return
s
.
states
[
string
(
addr
)]
=
contract
.
state
s
.
trie
.
Update
(
string
(
addr
),
string
(
contract
.
RlpEncode
()))
}
func
(
s
*
State
)
GetAccount
(
addr
[]
byte
)
(
account
*
Account
)
{
data
:=
s
.
trie
.
Get
(
string
(
addr
))
if
data
==
""
{
account
=
NewAccount
(
big
.
NewInt
(
0
))
account
=
NewAccount
(
addr
,
big
.
NewInt
(
0
))
}
else
{
account
=
NewAccountFromData
([]
byte
(
data
))
account
=
NewAccountFromData
(
addr
,
[]
byte
(
data
))
}
return
...
...
@@ -153,3 +144,35 @@ func (s *State) Get(key []byte) (*ethutil.Value, ObjType) {
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
}
}()
*/
vm
:=
&
Vm
{}
//vm.Process(contract, block.state, RuntimeVars{
vm
.
Process
(
contract
,
sm
.
procState
,
RuntimeVars
{
address
:
tx
.
Hash
()[
12
:
],
caller
:=
sm
.
procState
.
GetAccount
(
tx
.
Sender
())
closure
:=
NewClosure
(
caller
,
contract
,
sm
.
procState
,
tx
.
Gas
,
tx
.
Value
)
vm
:=
NewVm
(
sm
.
procState
,
RuntimeVars
{
origin
:
caller
.
Address
(),
blockNumber
:
block
.
BlockInfo
()
.
Number
,
sender
:
tx
.
Sender
(),
prevHash
:
block
.
PrevHash
,
coinbase
:
block
.
Coinbase
,
time
:
block
.
Time
,
diff
:
block
.
Difficulty
,
txValue
:
tx
.
Value
,
txData
:
tx
.
Data
,
// XXX Tx data? Could be just an argument to the closure instead
txData
:
nil
,
})
closure
.
Call
(
vm
,
nil
)
}
ethchain/transaction.go
View file @
97786d03
...
...
@@ -13,22 +13,31 @@ type Transaction struct {
Nonce
uint64
Recipient
[]
byte
Value
*
big
.
Int
Gas
*
big
.
Int
Gasprice
*
big
.
Int
Data
[]
string
Memory
[]
int
v
byte
r
,
s
[]
byte
}
func
NewTransaction
(
to
[]
byte
,
value
*
big
.
Int
,
data
[]
string
)
*
Transaction
{
tx
:=
Transaction
{
Recipient
:
to
,
Value
:
value
}
tx
.
Nonce
=
0
// Serialize the data
tx
.
Data
=
data
tx
:=
Transaction
{
Recipient
:
to
,
Value
:
value
,
Nonce
:
0
,
Data
:
data
}
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
func
NewTransactionFromData
(
data
[]
byte
)
*
Transaction
{
return
NewTransactionFromBytes
(
data
)
...
...
ethchain/vm.go
View file @
97786d03
This diff is collapsed.
Click to expand it.
ethchain/vm_test.go
View file @
97786d03
package
ethchain
import
(
"
fmt
"
"
bytes
"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"testing"
)
/*
func TestRun(t *testing.T) {
InitFees()
...
...
@@ -104,3 +106,69 @@ func TestRun2(t *testing.T) {
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 {
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 (
"os"
"os/user"
"path"
"runtime"
)
type
LogType
byte
...
...
@@ -23,6 +24,7 @@ type config struct {
ExecPath
string
Debug
bool
Ver
string
ClientString
string
Pubkey
[]
byte
Seed
bool
}
...
...
@@ -48,11 +50,16 @@ func ReadConfig(base string) *config {
Config
=
&
config
{
ExecPath
:
path
,
Debug
:
true
,
Ver
:
"0.3.1"
}
Config
.
Log
=
NewLogger
(
LogFile
|
LogStd
,
LogLevelDebug
)
Config
.
SetClientString
(
"/Ethereum(G)"
)
}
return
Config
}
func
(
c
*
config
)
SetClientString
(
str
string
)
{
Config
.
ClientString
=
fmt
.
Sprintf
(
"%s nv%s/%s"
,
str
,
c
.
Ver
,
runtime
.
GOOS
)
}
type
LoggerType
byte
const
(
...
...
ethutil/parsing.go
View file @
97786d03
...
...
@@ -7,6 +7,7 @@ import (
// Op codes
var
OpCodes
=
map
[
string
]
byte
{
// 0x0 range - arithmetic ops
"STOP"
:
0x00
,
"ADD"
:
0x01
,
"MUL"
:
0x02
,
...
...
@@ -18,46 +19,60 @@ var OpCodes = map[string]byte{
"EXP"
:
0x08
,
"NEG"
:
0x09
,
"LT"
:
0x0a
,
"LE"
:
0x0b
,
"GT"
:
0x0c
,
"GE"
:
0x0d
,
"EQ"
:
0x0e
,
"NOT"
:
0x0f
,
"MYADDRESS"
:
0x10
,
"TXSENDER"
:
0x11
,
"TXVALUE"
:
0x12
,
"TXDATAN"
:
0x13
,
"TXDATA"
:
0x14
,
"BLK_PREVHASH"
:
0x15
,
"BLK_COINBASE"
:
0x16
,
"BLK_TIMESTAMP"
:
0x17
,
"BLK_NUMBER"
:
0x18
,
"BLK_DIFFICULTY"
:
0x19
,
"BLK_NONCE"
:
0x1a
,
"BASEFEE"
:
0x1b
,
"SHA256"
:
0x20
,
"RIPEMD160"
:
0x21
,
"ECMUL"
:
0x22
,
"ECADD"
:
0x23
,
"ECSIGN"
:
0x24
,
"ECRECOVER"
:
0x25
,
"ECVALID"
:
0x26
,
"SHA3"
:
0x27
,
"PUSH"
:
0x30
,
"POP"
:
0x31
,
"DUP"
:
0x32
,
"SWAP"
:
0x33
,
"MLOAD"
:
0x34
,
"MSTORE"
:
0x35
,
"SLOAD"
:
0x36
,
"SSTORE"
:
0x37
,
"JMP"
:
0x38
,
"JMPI"
:
0x39
,
"IND"
:
0x3a
,
"EXTRO"
:
0x3b
,
"BALANCE"
:
0x3c
,
"MKTX"
:
0x3d
,
"SUICIDE"
:
0x3f
,
"GT"
:
0x0b
,
"EQ"
:
0x0c
,
"NOT"
:
0x0d
,
// 0x10 range - bit ops
"AND"
:
0x10
,
"OR"
:
0x11
,
"XOR"
:
0x12
,
"BYTE"
:
0x13
,
// 0x20 range - crypto
"SHA3"
:
0x20
,
// 0x30 range - closure state
"ADDRESS"
:
0x30
,
"BALANCE"
:
0x31
,
"ORIGIN"
:
0x32
,
"CALLER"
:
0x33
,
"CALLVALUE"
:
0x34
,
"CALLDATA"
:
0x35
,
"CALLDATASIZE"
:
0x36
,
"GASPRICE"
:
0x38
,
// 0x40 range - block operations
"PREVHASH"
:
0x40
,
"COINBASE"
:
0x41
,
"TIMESTAMP"
:
0x42
,
"NUMBER"
:
0x43
,
"DIFFICULTY"
:
0x44
,
"GASLIMIT"
:
0x45
,
// 0x50 range - 'storage' and execution
"PUSH"
:
0x50
,
"POP"
:
0x51
,
"DUP"
:
0x52
,
"SWAP"
:
0x53
,
"MLOAD"
:
0x54
,
"MSTORE"
:
0x55
,
"MSTORE8"
:
0x56
,
"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
{
...
...
@@ -69,16 +84,30 @@ func IsOpCode(s string) bool {
return
false
}
func
CompileInstr
(
s
string
)
([]
byte
,
error
)
{
isOp
:=
IsOpCode
(
s
)
func
CompileInstr
(
s
interface
{})
([]
byte
,
error
)
{
switch
s
.
(
type
)
{
case
string
:
str
:=
s
.
(
string
)
isOp
:=
IsOpCode
(
str
)
if
isOp
{
return
[]
byte
{
OpCodes
[
s
]},
nil
return
[]
byte
{
OpCodes
[
str
]},
nil
}
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
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
)
{
...
...
@@ -99,3 +128,17 @@ func Instr(instr string) (int, []string, error) {
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 (
"math/big"
)
type
RlpEncodable
interface
{
RlpEncode
()
[]
byte
}
type
RlpEncoder
struct
{
rlpData
[]
byte
}
...
...
ethutil/trie_test.go
View file @
97786d03
package
ethutil
import
(
"fmt"
"reflect"
"testing"
)
...
...
peer.go
View file @
97786d03
...
...
@@ -7,7 +7,6 @@ import (
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"net"
"runtime"
"strconv"
"strings"
"sync/atomic"
...
...
@@ -160,7 +159,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
connected
:
0
,
disconnect
:
0
,
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
...
...
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