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
3f1f8438
Commit
3f1f8438
authored
Jun 19, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'release/0.5.14'
parents
5a0e7517
7ad073fb
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
419 additions
and
466 deletions
+419
-466
README.md
README.md
+1
-1
asm.go
ethchain/asm.go
+1
-1
deprecated.go
ethchain/deprecated.go
+0
-236
stack.go
ethchain/stack.go
+8
-2
state.go
ethchain/state.go
+37
-12
state_manager.go
ethchain/state_manager.go
+22
-9
state_object.go
ethchain/state_object.go
+37
-12
state_transition.go
ethchain/state_transition.go
+73
-70
transaction.go
ethchain/transaction.go
+6
-2
types.go
ethchain/types.go
+2
-1
vm.go
ethchain/vm.go
+169
-91
ethereum.go
ethereum.go
+4
-10
miner.go
ethminer/miner.go
+2
-0
pub.go
ethpub/pub.go
+0
-5
types.go
ethpub/types.go
+4
-3
bytes.go
ethutil/bytes.go
+2
-1
config.go
ethutil/config.go
+1
-1
trie_test.go
ethutil/trie_test.go
+16
-7
value.go
ethutil/value.go
+2
-0
peer.go
peer.go
+32
-2
No files found.
README.md
View file @
3f1f8438
...
@@ -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 5.0 RC1
3
". For build instructions see the
[
Wiki
](
https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go
)
).
of Concept 5.0 RC1
4
". 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/asm.go
View file @
3f1f8438
...
@@ -28,7 +28,7 @@ func Disassemble(script []byte) (asm []string) {
...
@@ -28,7 +28,7 @@ func Disassemble(script []byte) (asm []string) {
if
len
(
data
)
==
0
{
if
len
(
data
)
==
0
{
data
=
[]
byte
{
0
}
data
=
[]
byte
{
0
}
}
}
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"
%#
x"
,
data
))
asm
=
append
(
asm
,
fmt
.
Sprintf
(
"
0x%
x"
,
data
))
pc
.
Add
(
pc
,
big
.
NewInt
(
a
-
1
))
pc
.
Add
(
pc
,
big
.
NewInt
(
a
-
1
))
}
}
...
...
ethchain/deprecated.go
deleted
100644 → 0
View file @
5a0e7517
package
ethchain
import
(
"bytes"
"fmt"
"github.com/ethereum/eth-go/ethutil"
"math/big"
)
func
(
sm
*
StateManager
)
MakeStateObject
(
state
*
State
,
tx
*
Transaction
)
*
StateObject
{
contract
:=
MakeContract
(
tx
,
state
)
if
contract
!=
nil
{
state
.
states
[
string
(
tx
.
CreationAddress
())]
=
contract
.
state
return
contract
}
return
nil
}
func
(
sm
*
StateManager
)
EvalScript
(
state
*
State
,
script
[]
byte
,
object
*
StateObject
,
tx
*
Transaction
,
block
*
Block
)
(
ret
[]
byte
,
gas
*
big
.
Int
,
err
error
)
{
account
:=
state
.
GetAccount
(
tx
.
Sender
())
err
=
account
.
ConvertGas
(
tx
.
Gas
,
tx
.
GasPrice
)
if
err
!=
nil
{
ethutil
.
Config
.
Log
.
Debugln
(
err
)
return
}
closure
:=
NewClosure
(
account
,
object
,
script
,
state
,
tx
.
Gas
,
tx
.
GasPrice
)
vm
:=
NewVm
(
state
,
sm
,
RuntimeVars
{
Origin
:
account
.
Address
(),
BlockNumber
:
block
.
BlockInfo
()
.
Number
,
PrevHash
:
block
.
PrevHash
,
Coinbase
:
block
.
Coinbase
,
Time
:
block
.
Time
,
Diff
:
block
.
Difficulty
,
Value
:
tx
.
Value
,
//Price: tx.GasPrice,
})
ret
,
gas
,
err
=
closure
.
Call
(
vm
,
tx
.
Data
,
nil
)
// Update the account (refunds)
state
.
UpdateStateObject
(
account
)
state
.
UpdateStateObject
(
object
)
return
}
func
(
self
*
StateManager
)
ProcessTransaction
(
tx
*
Transaction
,
coinbase
*
StateObject
,
state
*
State
,
toContract
bool
)
(
gas
*
big
.
Int
,
err
error
)
{
fmt
.
Printf
(
"state root before update %x
\n
"
,
state
.
Root
())
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
ethutil
.
Config
.
Log
.
Infoln
(
r
)
err
=
fmt
.
Errorf
(
"%v"
,
r
)
}
}()
gas
=
new
(
big
.
Int
)
addGas
:=
func
(
g
*
big
.
Int
)
{
gas
.
Add
(
gas
,
g
)
}
addGas
(
GasTx
)
// Get the sender
sender
:=
state
.
GetAccount
(
tx
.
Sender
())
if
sender
.
Nonce
!=
tx
.
Nonce
{
err
=
NonceError
(
tx
.
Nonce
,
sender
.
Nonce
)
return
}
sender
.
Nonce
+=
1
defer
func
()
{
//state.UpdateStateObject(sender)
// Notify all subscribers
self
.
Ethereum
.
Reactor
()
.
Post
(
"newTx:post"
,
tx
)
}()
txTotalBytes
:=
big
.
NewInt
(
int64
(
len
(
tx
.
Data
)))
//fmt.Println("txTotalBytes", txTotalBytes)
//txTotalBytes.Div(txTotalBytes, ethutil.Big32)
addGas
(
new
(
big
.
Int
)
.
Mul
(
txTotalBytes
,
GasData
))
rGas
:=
new
(
big
.
Int
)
.
Set
(
gas
)
rGas
.
Mul
(
gas
,
tx
.
GasPrice
)
// Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it.
totAmount
:=
new
(
big
.
Int
)
.
Add
(
tx
.
Value
,
rGas
)
if
sender
.
Amount
.
Cmp
(
totAmount
)
<
0
{
state
.
UpdateStateObject
(
sender
)
err
=
fmt
.
Errorf
(
"[TXPL] Insufficient amount in sender's (%x) account"
,
tx
.
Sender
())
return
}
coinbase
.
BuyGas
(
gas
,
tx
.
GasPrice
)
state
.
UpdateStateObject
(
coinbase
)
fmt
.
Printf
(
"1. root %x
\n
"
,
state
.
Root
())
// Get the receiver
receiver
:=
state
.
GetAccount
(
tx
.
Recipient
)
// Send Tx to self
if
bytes
.
Compare
(
tx
.
Recipient
,
tx
.
Sender
())
==
0
{
// Subtract the fee
sender
.
SubAmount
(
rGas
)
}
else
{
// Subtract the amount from the senders account
sender
.
SubAmount
(
totAmount
)
state
.
UpdateStateObject
(
sender
)
fmt
.
Printf
(
"3. root %x
\n
"
,
state
.
Root
())
// Add the amount to receivers account which should conclude this transaction
receiver
.
AddAmount
(
tx
.
Value
)
state
.
UpdateStateObject
(
receiver
)
fmt
.
Printf
(
"2. root %x
\n
"
,
state
.
Root
())
}
ethutil
.
Config
.
Log
.
Infof
(
"[TXPL] Processed Tx %x
\n
"
,
tx
.
Hash
())
return
}
func
(
sm
*
StateManager
)
ApplyTransaction
(
coinbase
[]
byte
,
state
*
State
,
block
*
Block
,
tx
*
Transaction
)
(
totalGasUsed
*
big
.
Int
,
err
error
)
{
/*
Applies transactions to the given state and creates new
state objects where needed.
If said objects needs to be created
run the initialization script provided by the transaction and
assume there's a return value. The return value will be set to
the script section of the state object.
*/
var
(
addTotalGas
=
func
(
gas
*
big
.
Int
)
{
totalGasUsed
.
Add
(
totalGasUsed
,
gas
)
}
gas
=
new
(
big
.
Int
)
script
[]
byte
)
totalGasUsed
=
big
.
NewInt
(
0
)
snapshot
:=
state
.
Snapshot
()
ca
:=
state
.
GetAccount
(
coinbase
)
// Apply the transaction to the current state
gas
,
err
=
sm
.
ProcessTransaction
(
tx
,
ca
,
state
,
false
)
addTotalGas
(
gas
)
fmt
.
Println
(
"gas used by tx"
,
gas
)
if
tx
.
CreatesContract
()
{
if
err
==
nil
{
// Create a new state object and the transaction
// as it's data provider.
contract
:=
sm
.
MakeStateObject
(
state
,
tx
)
if
contract
!=
nil
{
fmt
.
Println
(
Disassemble
(
contract
.
Init
()))
// Evaluate the initialization script
// and use the return value as the
// script section for the state object.
script
,
gas
,
err
=
sm
.
EvalScript
(
state
,
contract
.
Init
(),
contract
,
tx
,
block
)
fmt
.
Println
(
"gas used by eval"
,
gas
)
addTotalGas
(
gas
)
fmt
.
Println
(
"total ="
,
totalGasUsed
)
fmt
.
Println
(
"script len ="
,
len
(
script
))
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"[STATE] Error during init script run %v"
,
err
)
return
}
contract
.
script
=
script
state
.
UpdateStateObject
(
contract
)
}
else
{
err
=
fmt
.
Errorf
(
"[STATE] Unable to create contract"
)
}
}
else
{
err
=
fmt
.
Errorf
(
"[STATE] contract creation tx: %v for sender %x"
,
err
,
tx
.
Sender
())
}
}
else
{
// Find the state object at the "recipient" address. If
// there's an object attempt to run the script.
stateObject
:=
state
.
GetStateObject
(
tx
.
Recipient
)
if
err
==
nil
&&
stateObject
!=
nil
&&
len
(
stateObject
.
Script
())
>
0
{
_
,
gas
,
err
=
sm
.
EvalScript
(
state
,
stateObject
.
Script
(),
stateObject
,
tx
,
block
)
addTotalGas
(
gas
)
}
}
parent
:=
sm
.
bc
.
GetBlock
(
block
.
PrevHash
)
total
:=
new
(
big
.
Int
)
.
Add
(
block
.
GasUsed
,
totalGasUsed
)
limit
:=
block
.
CalcGasLimit
(
parent
)
if
total
.
Cmp
(
limit
)
>
0
{
state
.
Revert
(
snapshot
)
err
=
GasLimitError
(
total
,
limit
)
}
return
}
// Apply transactions uses the transaction passed to it and applies them onto
// the current processing state.
func
(
sm
*
StateManager
)
ApplyTransactions
(
coinbase
[]
byte
,
state
*
State
,
block
*
Block
,
txs
[]
*
Transaction
)
([]
*
Receipt
,
[]
*
Transaction
)
{
// Process each transaction/contract
var
receipts
[]
*
Receipt
var
validTxs
[]
*
Transaction
var
ignoredTxs
[]
*
Transaction
// Transactions which go over the gasLimit
totalUsedGas
:=
big
.
NewInt
(
0
)
for
_
,
tx
:=
range
txs
{
usedGas
,
err
:=
sm
.
ApplyTransaction
(
coinbase
,
state
,
block
,
tx
)
if
err
!=
nil
{
if
IsNonceErr
(
err
)
{
continue
}
if
IsGasLimitErr
(
err
)
{
ignoredTxs
=
append
(
ignoredTxs
,
tx
)
// We need to figure out if we want to do something with thse txes
ethutil
.
Config
.
Log
.
Debugln
(
"Gastlimit:"
,
err
)
continue
}
ethutil
.
Config
.
Log
.
Infoln
(
err
)
}
accumelative
:=
new
(
big
.
Int
)
.
Set
(
totalUsedGas
.
Add
(
totalUsedGas
,
usedGas
))
receipt
:=
&
Receipt
{
tx
,
ethutil
.
CopyBytes
(
state
.
Root
()
.
([]
byte
)),
accumelative
}
receipts
=
append
(
receipts
,
receipt
)
validTxs
=
append
(
validTxs
,
tx
)
}
fmt
.
Println
(
"################# MADE
\n
"
,
receipts
,
"
\n
############################"
)
// Update the total gas used for the block (to be mined)
block
.
GasUsed
=
totalUsedGas
return
receipts
,
validTxs
}
ethchain/stack.go
View file @
3f1f8438
...
@@ -2,7 +2,7 @@ package ethchain
...
@@ -2,7 +2,7 @@ package ethchain
import
(
import
(
"fmt"
"fmt"
_
"github.com/ethereum/eth-go/ethutil
"
"math
"
"math/big"
"math/big"
)
)
...
@@ -118,7 +118,13 @@ func (m *Memory) Resize(size uint64) {
...
@@ -118,7 +118,13 @@ func (m *Memory) Resize(size uint64) {
}
}
func
(
m
*
Memory
)
Get
(
offset
,
size
int64
)
[]
byte
{
func
(
m
*
Memory
)
Get
(
offset
,
size
int64
)
[]
byte
{
return
m
.
store
[
offset
:
offset
+
size
]
if
len
(
m
.
store
)
>
int
(
offset
)
{
end
:=
int
(
math
.
Min
(
float64
(
len
(
m
.
store
)),
float64
(
offset
+
size
)))
return
m
.
store
[
offset
:
end
]
}
return
nil
}
}
func
(
m
*
Memory
)
Len
()
int
{
func
(
m
*
Memory
)
Len
()
int
{
...
...
ethchain/state.go
View file @
3f1f8438
...
@@ -13,8 +13,6 @@ import (
...
@@ -13,8 +13,6 @@ import (
type
State
struct
{
type
State
struct
{
// The trie for this structure
// The trie for this structure
trie
*
ethutil
.
Trie
trie
*
ethutil
.
Trie
// Nested states
states
map
[
string
]
*
State
stateObjects
map
[
string
]
*
StateObject
stateObjects
map
[
string
]
*
StateObject
...
@@ -23,7 +21,7 @@ type State struct {
...
@@ -23,7 +21,7 @@ type State struct {
// Create a new state from a given trie
// Create a new state from a given trie
func
NewState
(
trie
*
ethutil
.
Trie
)
*
State
{
func
NewState
(
trie
*
ethutil
.
Trie
)
*
State
{
return
&
State
{
trie
:
trie
,
state
s
:
make
(
map
[
string
]
*
State
),
state
Objects
:
make
(
map
[
string
]
*
StateObject
),
manifest
:
NewManifest
()}
return
&
State
{
trie
:
trie
,
stateObjects
:
make
(
map
[
string
]
*
StateObject
),
manifest
:
NewManifest
()}
}
}
// Resets the trie and all siblings
// Resets the trie and all siblings
...
@@ -38,12 +36,16 @@ func (s *State) Reset() {
...
@@ -38,12 +36,16 @@ func (s *State) Reset() {
stateObject
.
state
.
Reset
()
stateObject
.
state
.
Reset
()
}
}
s
.
Empty
()
}
}
// Syncs the trie and all siblings
// Syncs the trie and all siblings
func
(
s
*
State
)
Sync
()
{
func
(
s
*
State
)
Sync
()
{
// Sync all nested states
// Sync all nested states
for
_
,
stateObject
:=
range
s
.
stateObjects
{
for
_
,
stateObject
:=
range
s
.
stateObjects
{
s
.
UpdateStateObject
(
stateObject
)
if
stateObject
.
state
==
nil
{
if
stateObject
.
state
==
nil
{
continue
continue
}
}
...
@@ -52,6 +54,18 @@ func (s *State) Sync() {
...
@@ -52,6 +54,18 @@ func (s *State) Sync() {
}
}
s
.
trie
.
Sync
()
s
.
trie
.
Sync
()
s
.
Empty
()
}
func
(
self
*
State
)
Empty
()
{
self
.
stateObjects
=
make
(
map
[
string
]
*
StateObject
)
}
func
(
self
*
State
)
Update
()
{
for
_
,
stateObject
:=
range
self
.
stateObjects
{
self
.
UpdateStateObject
(
stateObject
)
}
}
}
// Purges the current trie.
// Purges the current trie.
...
@@ -64,6 +78,12 @@ func (s *State) EachStorage(cb ethutil.EachCallback) {
...
@@ -64,6 +78,12 @@ func (s *State) EachStorage(cb ethutil.EachCallback) {
it
.
Each
(
cb
)
it
.
Each
(
cb
)
}
}
func
(
self
*
State
)
ResetStateObject
(
stateObject
*
StateObject
)
{
delete
(
self
.
stateObjects
,
string
(
stateObject
.
Address
()))
stateObject
.
state
.
Reset
()
}
func
(
self
*
State
)
UpdateStateObject
(
stateObject
*
StateObject
)
{
func
(
self
*
State
)
UpdateStateObject
(
stateObject
*
StateObject
)
{
addr
:=
stateObject
.
Address
()
addr
:=
stateObject
.
Address
()
...
@@ -98,13 +118,21 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
...
@@ -98,13 +118,21 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
func
(
self
*
State
)
GetOrNewStateObject
(
addr
[]
byte
)
*
StateObject
{
func
(
self
*
State
)
GetOrNewStateObject
(
addr
[]
byte
)
*
StateObject
{
stateObject
:=
self
.
GetStateObject
(
addr
)
stateObject
:=
self
.
GetStateObject
(
addr
)
if
stateObject
==
nil
{
if
stateObject
==
nil
{
stateObject
=
NewStateObject
(
addr
)
stateObject
=
self
.
NewStateObject
(
addr
)
self
.
stateObjects
[
string
(
addr
)]
=
stateObject
}
}
return
stateObject
return
stateObject
}
}
func
(
self
*
State
)
NewStateObject
(
addr
[]
byte
)
*
StateObject
{
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevelInfo
,
"(+) %x
\n
"
,
addr
)
stateObject
:=
NewStateObject
(
addr
)
self
.
stateObjects
[
string
(
addr
)]
=
stateObject
return
stateObject
}
func
(
self
*
State
)
GetAccount
(
addr
[]
byte
)
*
StateObject
{
func
(
self
*
State
)
GetAccount
(
addr
[]
byte
)
*
StateObject
{
return
self
.
GetOrNewStateObject
(
addr
)
return
self
.
GetOrNewStateObject
(
addr
)
}
}
...
@@ -126,13 +154,10 @@ func (self *State) Copy() *State {
...
@@ -126,13 +154,10 @@ func (self *State) Copy() *State {
return
nil
return
nil
}
}
func
(
s
*
State
)
Snapshot
()
*
State
{
func
(
self
*
State
)
Set
(
state
*
State
)
{
return
s
.
Copy
()
//s.trie = snapshot.trie
}
//s.stateObjects = snapshot.stateObjects
self
=
state
func
(
s
*
State
)
Revert
(
snapshot
*
State
)
{
s
.
trie
=
snapshot
.
trie
s
.
states
=
snapshot
.
states
}
}
func
(
s
*
State
)
Put
(
key
,
object
[]
byte
)
{
func
(
s
*
State
)
Put
(
key
,
object
[]
byte
)
{
...
...
ethchain/state_manager.go
View file @
3f1f8438
...
@@ -127,6 +127,9 @@ done:
...
@@ -127,6 +127,9 @@ done:
// Notify all subscribers
// Notify all subscribers
self
.
Ethereum
.
Reactor
()
.
Post
(
"newTx:post"
,
tx
)
self
.
Ethereum
.
Reactor
()
.
Post
(
"newTx:post"
,
tx
)
// Update the state with pending changes
state
.
Update
()
txGas
.
Sub
(
txGas
,
st
.
gas
)
txGas
.
Sub
(
txGas
,
st
.
gas
)
accumelative
:=
new
(
big
.
Int
)
.
Set
(
totalUsedGas
.
Add
(
totalUsedGas
,
txGas
))
accumelative
:=
new
(
big
.
Int
)
.
Set
(
totalUsedGas
.
Add
(
totalUsedGas
,
txGas
))
receipt
:=
&
Receipt
{
tx
,
ethutil
.
CopyBytes
(
state
.
Root
()
.
([]
byte
)),
accumelative
}
receipt
:=
&
Receipt
{
tx
,
ethutil
.
CopyBytes
(
state
.
Root
()
.
([]
byte
)),
accumelative
}
...
@@ -135,8 +138,6 @@ done:
...
@@ -135,8 +138,6 @@ done:
handled
=
append
(
handled
,
tx
)
handled
=
append
(
handled
,
tx
)
}
}
fmt
.
Println
(
"################# MADE
\n
"
,
receipts
,
"
\n
############################"
)
parent
.
GasUsed
=
totalUsedGas
parent
.
GasUsed
=
totalUsedGas
return
receipts
,
handled
,
unhandled
,
err
return
receipts
,
handled
,
unhandled
,
err
...
@@ -154,7 +155,7 @@ func (sm *StateManager) Process(block *Block, dontReact bool) error {
...
@@ -154,7 +155,7 @@ func (sm *StateManager) Process(block *Block, dontReact bool) error {
}
}
// Block processing and validating with a given (temporarily) state
// Block processing and validating with a given (temporarily) state
func
(
sm
*
StateManager
)
ProcessBlock
(
state
*
State
,
parent
,
block
*
Block
,
dontReact
bool
)
error
{
func
(
sm
*
StateManager
)
ProcessBlock
(
state
*
State
,
parent
,
block
*
Block
,
dontReact
bool
)
(
err
error
)
{
// Processing a blocks may never happen simultaneously
// Processing a blocks may never happen simultaneously
sm
.
mutex
.
Lock
()
sm
.
mutex
.
Lock
()
defer
sm
.
mutex
.
Unlock
()
defer
sm
.
mutex
.
Unlock
()
...
@@ -175,30 +176,40 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
...
@@ -175,30 +176,40 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
if
!
sm
.
bc
.
HasBlock
(
block
.
PrevHash
)
&&
sm
.
bc
.
CurrentBlock
!=
nil
{
if
!
sm
.
bc
.
HasBlock
(
block
.
PrevHash
)
&&
sm
.
bc
.
CurrentBlock
!=
nil
{
return
ParentError
(
block
.
PrevHash
)
return
ParentError
(
block
.
PrevHash
)
}
}
fmt
.
Println
(
block
.
Receipts
())
coinbase
:=
state
.
GetOrNewStateObject
(
block
.
Coinbase
)
coinbase
:=
state
.
GetOrNewStateObject
(
block
.
Coinbase
)
coinbase
.
SetGasPool
(
block
.
CalcGasLimit
(
parent
))
coinbase
.
SetGasPool
(
block
.
CalcGasLimit
(
parent
))
// Process the transactions on to current block
// Process the transactions on to current block
//sm.ApplyTransactions(block.Coinbase, state, parent, block.Transactions())
receipts
,
_
,
_
,
_
:=
sm
.
ProcessTransactions
(
coinbase
,
state
,
block
,
parent
,
block
.
Transactions
())
sm
.
ProcessTransactions
(
coinbase
,
state
,
block
,
parent
,
block
.
Transactions
())
defer
func
()
{
if
err
!=
nil
{
if
len
(
receipts
)
==
len
(
block
.
Receipts
())
{
for
i
,
receipt
:=
range
block
.
Receipts
()
{
ethutil
.
Config
.
Log
.
Debugf
(
"diff (r) %v ~ %x <=> (c) %v ~ %x (%x)
\n
"
,
receipt
.
CumulativeGasUsed
,
receipt
.
PostState
[
0
:
4
],
receipts
[
i
]
.
CumulativeGasUsed
,
receipts
[
i
]
.
PostState
[
0
:
4
],
receipt
.
Tx
.
Hash
())
}
}
else
{
ethutil
.
Config
.
Log
.
Debugln
(
"Unable to print receipt diff. Length didn't match"
,
len
(
receipts
),
"for"
,
len
(
block
.
Receipts
()))
}
}
}()
// Block validation
// Block validation
if
err
:
=
sm
.
ValidateBlock
(
block
);
err
!=
nil
{
if
err
=
sm
.
ValidateBlock
(
block
);
err
!=
nil
{
fmt
.
Println
(
"[SM] Error validating block:"
,
err
)
fmt
.
Println
(
"[SM] Error validating block:"
,
err
)
return
err
return
err
}
}
// I'm not sure, but I don't know if there should be thrown
// I'm not sure, but I don't know if there should be thrown
// any errors at this time.
// any errors at this time.
if
err
:
=
sm
.
AccumelateRewards
(
state
,
block
);
err
!=
nil
{
if
err
=
sm
.
AccumelateRewards
(
state
,
block
);
err
!=
nil
{
fmt
.
Println
(
"[SM] Error accumulating reward"
,
err
)
fmt
.
Println
(
"[SM] Error accumulating reward"
,
err
)
return
err
return
err
}
}
if
!
block
.
State
()
.
Cmp
(
state
)
{
if
!
block
.
State
()
.
Cmp
(
state
)
{
return
fmt
.
Errorf
(
"Invalid merkle root.
\n
rec: %x
\n
is: %x"
,
block
.
State
()
.
trie
.
Root
,
state
.
trie
.
Root
)
err
=
fmt
.
Errorf
(
"Invalid merkle root.
\n
rec: %x
\n
is: %x"
,
block
.
State
()
.
trie
.
Root
,
state
.
trie
.
Root
)
return
}
}
// Calculate the new total difficulty and sync back to the db
// Calculate the new total difficulty and sync back to the db
...
@@ -270,10 +281,12 @@ func (sm *StateManager) ValidateBlock(block *Block) error {
...
@@ -270,10 +281,12 @@ func (sm *StateManager) ValidateBlock(block *Block) error {
return
ValidationError
(
"Block timestamp less then prev block %v"
,
diff
)
return
ValidationError
(
"Block timestamp less then prev block %v"
,
diff
)
}
}
/* XXX
// New blocks must be within the 15 minute range of the last block.
// New blocks must be within the 15 minute range of the last block.
if diff > int64(15*time.Minute) {
if diff > int64(15*time.Minute) {
return ValidationError("Block is too far in the future of last block (> 15 minutes)")
return ValidationError("Block is too far in the future of last block (> 15 minutes)")
}
}
*/
// Verify the nonce of the block. Return an error if it's not valid
// Verify the nonce of the block. Return an error if it's not valid
if
!
sm
.
Pow
.
Verify
(
block
.
HashNoNonce
(),
block
.
Difficulty
,
block
.
Nonce
)
{
if
!
sm
.
Pow
.
Verify
(
block
.
HashNoNonce
(),
block
.
Difficulty
,
block
.
Nonce
)
{
...
...
ethchain/state_object.go
View file @
3f1f8438
...
@@ -4,8 +4,15 @@ import (
...
@@ -4,8 +4,15 @@ import (
"fmt"
"fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"math/big"
"strings"
)
)
type
Code
[]
byte
func
(
self
Code
)
String
()
string
{
return
strings
.
Join
(
Disassemble
(
self
),
" "
)
}
type
StateObject
struct
{
type
StateObject
struct
{
// Address of the object
// Address of the object
address
[]
byte
address
[]
byte
...
@@ -15,8 +22,8 @@ type StateObject struct {
...
@@ -15,8 +22,8 @@ type StateObject struct {
Nonce
uint64
Nonce
uint64
// Contract related attributes
// Contract related attributes
state
*
State
state
*
State
script
[]
byt
e
script
Cod
e
initScript
[]
byt
e
initScript
Cod
e
// Total gas pool is the total amount of gas currently
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
// left if this object is the coinbase. Gas is directly
...
@@ -30,12 +37,9 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
...
@@ -30,12 +37,9 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
if
tx
.
IsContract
()
{
if
tx
.
IsContract
()
{
addr
:=
tx
.
CreationAddress
()
addr
:=
tx
.
CreationAddress
()
value
:=
tx
.
Value
contract
:=
state
.
NewStateObject
(
addr
)
contract
:=
NewContract
(
addr
,
value
,
ZeroHash256
)
contract
.
initScript
=
tx
.
Data
contract
.
initScript
=
tx
.
Data
contract
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
""
))
state
.
UpdateStateObject
(
contract
)
return
contract
return
contract
}
}
...
@@ -44,7 +48,7 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
...
@@ -44,7 +48,7 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
}
}
func
NewStateObject
(
addr
[]
byte
)
*
StateObject
{
func
NewStateObject
(
addr
[]
byte
)
*
StateObject
{
return
&
StateObject
{
address
:
addr
,
Amount
:
new
(
big
.
Int
)}
return
&
StateObject
{
address
:
addr
,
Amount
:
new
(
big
.
Int
)
,
gasPool
:
new
(
big
.
Int
)
}
}
}
func
NewContract
(
address
[]
byte
,
Amount
*
big
.
Int
,
root
[]
byte
)
*
StateObject
{
func
NewContract
(
address
[]
byte
,
Amount
*
big
.
Int
,
root
[]
byte
)
*
StateObject
{
...
@@ -120,13 +124,13 @@ func (c *StateObject) ReturnGas(gas, price *big.Int, state *State) {
...
@@ -120,13 +124,13 @@ func (c *StateObject) ReturnGas(gas, price *big.Int, state *State) {
func
(
c
*
StateObject
)
AddAmount
(
amount
*
big
.
Int
)
{
func
(
c
*
StateObject
)
AddAmount
(
amount
*
big
.
Int
)
{
c
.
SetAmount
(
new
(
big
.
Int
)
.
Add
(
c
.
Amount
,
amount
))
c
.
SetAmount
(
new
(
big
.
Int
)
.
Add
(
c
.
Amount
,
amount
))
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevel
System
,
"%x: #%d %v (+ %v)
\n
"
,
c
.
Address
(),
c
.
Nonce
,
c
.
Amount
,
amount
)
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevel
Info
,
"%x: #%d %v (+ %v)
\n
"
,
c
.
Address
(),
c
.
Nonce
,
c
.
Amount
,
amount
)
}
}
func
(
c
*
StateObject
)
SubAmount
(
amount
*
big
.
Int
)
{
func
(
c
*
StateObject
)
SubAmount
(
amount
*
big
.
Int
)
{
c
.
SetAmount
(
new
(
big
.
Int
)
.
Sub
(
c
.
Amount
,
amount
))
c
.
SetAmount
(
new
(
big
.
Int
)
.
Sub
(
c
.
Amount
,
amount
))
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevel
System
,
"%x: #%d %v (- %v)
\n
"
,
c
.
Address
(),
c
.
Nonce
,
c
.
Amount
,
amount
)
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevel
Info
,
"%x: #%d %v (- %v)
\n
"
,
c
.
Address
(),
c
.
Nonce
,
c
.
Amount
,
amount
)
}
}
func
(
c
*
StateObject
)
SetAmount
(
amount
*
big
.
Int
)
{
func
(
c
*
StateObject
)
SetAmount
(
amount
*
big
.
Int
)
{
...
@@ -172,6 +176,26 @@ func (self *StateObject) RefundGas(gas, price *big.Int) {
...
@@ -172,6 +176,26 @@ func (self *StateObject) RefundGas(gas, price *big.Int) {
self
.
Amount
.
Sub
(
self
.
Amount
,
rGas
)
self
.
Amount
.
Sub
(
self
.
Amount
,
rGas
)
}
}
func
(
self
*
StateObject
)
Copy
()
*
StateObject
{
stateObject
:=
NewStateObject
(
self
.
Address
())
stateObject
.
Amount
.
Set
(
self
.
Amount
)
stateObject
.
ScriptHash
=
ethutil
.
CopyBytes
(
self
.
ScriptHash
)
stateObject
.
Nonce
=
self
.
Nonce
if
self
.
state
!=
nil
{
stateObject
.
state
=
self
.
state
.
Copy
()
}
stateObject
.
script
=
ethutil
.
CopyBytes
(
self
.
script
)
stateObject
.
initScript
=
ethutil
.
CopyBytes
(
self
.
initScript
)
//stateObject.gasPool.Set(self.gasPool)
return
self
}
func
(
self
*
StateObject
)
Set
(
stateObject
*
StateObject
)
{
self
=
stateObject
}
/*
func (self *StateObject) Copy() *StateObject {
func (self *StateObject) Copy() *StateObject {
stCopy := &StateObject{}
stCopy := &StateObject{}
stCopy.address = make([]byte, len(self.address))
stCopy.address = make([]byte, len(self.address))
...
@@ -190,6 +214,7 @@ func (self *StateObject) Copy() *StateObject {
...
@@ -190,6 +214,7 @@ func (self *StateObject) Copy() *StateObject {
return stCopy
return stCopy
}
}
*/
// Returns the address of the contract/account
// Returns the address of the contract/account
func
(
c
*
StateObject
)
Address
()
[]
byte
{
func
(
c
*
StateObject
)
Address
()
[]
byte
{
...
@@ -197,12 +222,12 @@ func (c *StateObject) Address() []byte {
...
@@ -197,12 +222,12 @@ func (c *StateObject) Address() []byte {
}
}
// Returns the main script body
// Returns the main script body
func
(
c
*
StateObject
)
Script
()
[]
byt
e
{
func
(
c
*
StateObject
)
Script
()
Cod
e
{
return
c
.
script
return
c
.
script
}
}
// Returns the initialization script
// Returns the initialization script
func
(
c
*
StateObject
)
Init
()
[]
byt
e
{
func
(
c
*
StateObject
)
Init
()
Cod
e
{
return
c
.
initScript
return
c
.
initScript
}
}
...
...
ethchain/state_transition.go
View file @
3f1f8438
...
@@ -23,9 +23,11 @@ import (
...
@@ -23,9 +23,11 @@ import (
* 6) Derive new state root
* 6) Derive new state root
*/
*/
type
StateTransition
struct
{
type
StateTransition
struct
{
coinbase
[]
byte
coinbase
,
receiver
[]
byte
tx
*
Transaction
tx
*
Transaction
gas
*
big
.
Int
gas
,
gasPrice
*
big
.
Int
value
*
big
.
Int
data
[]
byte
state
*
State
state
*
State
block
*
Block
block
*
Block
...
@@ -33,7 +35,7 @@ type StateTransition struct {
...
@@ -33,7 +35,7 @@ type StateTransition struct {
}
}
func
NewStateTransition
(
coinbase
*
StateObject
,
tx
*
Transaction
,
state
*
State
,
block
*
Block
)
*
StateTransition
{
func
NewStateTransition
(
coinbase
*
StateObject
,
tx
*
Transaction
,
state
*
State
,
block
*
Block
)
*
StateTransition
{
return
&
StateTransition
{
coinbase
.
Address
(),
tx
,
new
(
big
.
Int
)
,
state
,
block
,
coinbase
,
nil
,
nil
}
return
&
StateTransition
{
coinbase
.
Address
(),
tx
.
Recipient
,
tx
,
new
(
big
.
Int
),
new
(
big
.
Int
)
.
Set
(
tx
.
GasPrice
),
tx
.
Value
,
tx
.
Data
,
state
,
block
,
coinbase
,
nil
,
nil
}
}
}
func
(
self
*
StateTransition
)
Coinbase
()
*
StateObject
{
func
(
self
*
StateTransition
)
Coinbase
()
*
StateObject
{
...
@@ -53,7 +55,7 @@ func (self *StateTransition) Sender() *StateObject {
...
@@ -53,7 +55,7 @@ func (self *StateTransition) Sender() *StateObject {
return
self
.
sen
return
self
.
sen
}
}
func
(
self
*
StateTransition
)
Receiver
()
*
StateObject
{
func
(
self
*
StateTransition
)
Receiver
()
*
StateObject
{
if
self
.
tx
.
CreatesContract
()
{
if
self
.
tx
!=
nil
&&
self
.
tx
.
CreatesContract
()
{
return
nil
return
nil
}
}
...
@@ -67,13 +69,8 @@ func (self *StateTransition) Receiver() *StateObject {
...
@@ -67,13 +69,8 @@ func (self *StateTransition) Receiver() *StateObject {
func
(
self
*
StateTransition
)
MakeStateObject
(
state
*
State
,
tx
*
Transaction
)
*
StateObject
{
func
(
self
*
StateTransition
)
MakeStateObject
(
state
*
State
,
tx
*
Transaction
)
*
StateObject
{
contract
:=
MakeContract
(
tx
,
state
)
contract
:=
MakeContract
(
tx
,
state
)
if
contract
!=
nil
{
state
.
states
[
string
(
tx
.
CreationAddress
())]
=
contract
.
state
return
contract
return
contract
}
return
nil
}
}
func
(
self
*
StateTransition
)
UseGas
(
amount
*
big
.
Int
)
error
{
func
(
self
*
StateTransition
)
UseGas
(
amount
*
big
.
Int
)
error
{
...
@@ -94,7 +91,7 @@ func (self *StateTransition) BuyGas() error {
...
@@ -94,7 +91,7 @@ func (self *StateTransition) BuyGas() error {
sender
:=
self
.
Sender
()
sender
:=
self
.
Sender
()
if
sender
.
Amount
.
Cmp
(
self
.
tx
.
GasValue
())
<
0
{
if
sender
.
Amount
.
Cmp
(
self
.
tx
.
GasValue
())
<
0
{
return
fmt
.
Errorf
(
"Insufficient funds to pre-pay gas. Req %v, has %v"
,
self
.
tx
.
GasValue
(),
se
lf
.
tx
.
Value
)
return
fmt
.
Errorf
(
"Insufficient funds to pre-pay gas. Req %v, has %v"
,
self
.
tx
.
GasValue
(),
se
nder
.
Amount
)
}
}
coinbase
:=
self
.
Coinbase
()
coinbase
:=
self
.
Coinbase
()
...
@@ -102,7 +99,6 @@ func (self *StateTransition) BuyGas() error {
...
@@ -102,7 +99,6 @@ func (self *StateTransition) BuyGas() error {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
//self.state.UpdateStateObject(coinbase)
self
.
AddGas
(
self
.
tx
.
Gas
)
self
.
AddGas
(
self
.
tx
.
Gas
)
sender
.
SubAmount
(
self
.
tx
.
GasValue
())
sender
.
SubAmount
(
self
.
tx
.
GasValue
())
...
@@ -119,22 +115,10 @@ func (self *StateTransition) RefundGas() {
...
@@ -119,22 +115,10 @@ func (self *StateTransition) RefundGas() {
sender
.
AddAmount
(
remaining
)
sender
.
AddAmount
(
remaining
)
}
}
func
(
self
*
StateTransition
)
TransitionState
()
(
err
error
)
{
func
(
self
*
StateTransition
)
preCheck
()
(
err
error
)
{
//snapshot := st.state.Snapshot()
/*
defer func() {
if r := recover(); r != nil {
ethutil.Config.Log.Infoln(r)
err = fmt.Errorf("state transition err %v", r)
}
}()
*/
var
(
var
(
tx
=
self
.
tx
tx
=
self
.
tx
sender
=
self
.
Sender
()
sender
=
self
.
Sender
()
receiver
*
StateObject
)
)
// Make sure this transaction's nonce is correct
// Make sure this transaction's nonce is correct
...
@@ -147,38 +131,49 @@ func (self *StateTransition) TransitionState() (err error) {
...
@@ -147,38 +131,49 @@ func (self *StateTransition) TransitionState() (err error) {
return
err
return
err
}
}
// XXX Transactions after this point are considered valid.
return
nil
}
defer
func
(
)
{
func
(
self
*
StateTransition
)
TransitionState
()
(
err
error
)
{
self
.
RefundGas
(
)
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevelInfo
,
"(~) %x
\n
"
,
self
.
tx
.
Hash
()
)
if
sender
!=
nil
{
/*
self
.
state
.
UpdateStateObject
(
sender
)
defer func() {
if r := recover(); r != nil {
ethutil.Config.Log.Infoln(r)
err = fmt.Errorf("state transition err %v", r)
}
}
}()
*/
if
receiver
!=
nil
{
// XXX Transactions after this point are considered valid.
self
.
state
.
UpdateStateObject
(
receiver
)
if
err
=
self
.
preCheck
();
err
!=
nil
{
return
}
}
self
.
state
.
UpdateStateObject
(
self
.
Coinbase
())
var
(
}()
tx
=
self
.
tx
sender
=
self
.
Sender
()
receiver
*
StateObject
)
defer
self
.
RefundGas
()
// Increment the nonce for the next transaction
// Increment the nonce for the next transaction
sender
.
Nonce
+=
1
sender
.
Nonce
+=
1
// Get the receiver (TODO fix this, if coinbase is the receiver we need to save/retrieve)
receiver
=
self
.
Receiver
()
receiver
=
self
.
Receiver
()
// Transaction gas
// Transaction gas
if
err
=
self
.
UseGas
(
GasTx
);
err
!=
nil
{
if
err
=
self
.
UseGas
(
GasTx
);
err
!=
nil
{
return
err
return
}
}
// Pay data gas
// Pay data gas
dataPrice
:=
big
.
NewInt
(
int64
(
len
(
tx
.
D
ata
)))
dataPrice
:=
big
.
NewInt
(
int64
(
len
(
self
.
d
ata
)))
dataPrice
.
Mul
(
dataPrice
,
GasData
)
dataPrice
.
Mul
(
dataPrice
,
GasData
)
if
err
=
self
.
UseGas
(
dataPrice
);
err
!=
nil
{
if
err
=
self
.
UseGas
(
dataPrice
);
err
!=
nil
{
return
err
return
}
}
// If the receiver is nil it's a contract (\0*32).
// If the receiver is nil it's a contract (\0*32).
...
@@ -186,75 +181,83 @@ func (self *StateTransition) TransitionState() (err error) {
...
@@ -186,75 +181,83 @@ func (self *StateTransition) TransitionState() (err error) {
// Create a new state object for the contract
// Create a new state object for the contract
receiver
=
self
.
MakeStateObject
(
self
.
state
,
tx
)
receiver
=
self
.
MakeStateObject
(
self
.
state
,
tx
)
if
receiver
==
nil
{
if
receiver
==
nil
{
return
fmt
.
Errorf
(
"
ERR. Unable to create contract with transaction %v"
,
tx
)
return
fmt
.
Errorf
(
"
Unable to create contract"
)
}
}
}
}
// Transfer value from sender to receiver
// Transfer value from sender to receiver
if
err
=
self
.
transferValue
(
sender
,
receiver
);
err
!=
nil
{
if
err
=
self
.
transferValue
(
sender
,
receiver
);
err
!=
nil
{
return
err
return
}
}
// Process the init code and create 'valid' contract
// Process the init code and create 'valid' contract
if
tx
.
CreatesContract
(
)
{
if
IsContractAddr
(
self
.
receiver
)
{
// Evaluate the initialization script
// Evaluate the initialization script
// and use the return value as the
// and use the return value as the
// script section for the state object.
// script section for the state object.
//script, gas, err = sm.Eval(state, contract.Init(), contract, tx, block)
self
.
data
=
nil
code
,
err
:=
self
.
Eval
(
receiver
.
Init
(),
receiver
)
if
err
!=
nil
{
code
,
err
,
deepErr
:=
self
.
Eval
(
receiver
.
Init
(),
receiver
)
return
fmt
.
Errorf
(
"Error during init script run %v"
,
err
)
if
err
!=
nil
||
deepErr
{
self
.
state
.
ResetStateObject
(
receiver
)
return
fmt
.
Errorf
(
"Error during init script run %v (deepErr = %v)"
,
err
,
deepErr
)
}
}
receiver
.
script
=
code
receiver
.
script
=
code
}
else
{
}
else
{
if
len
(
receiver
.
Script
())
>
0
{
if
len
(
receiver
.
Script
())
>
0
{
_
,
err
:=
self
.
Eval
(
receiver
.
Script
(),
receiver
)
var
deepErr
bool
_
,
err
,
deepErr
=
self
.
Eval
(
receiver
.
Script
(),
receiver
)
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error during code execution %v"
,
err
)
self
.
state
.
ResetStateObject
(
receiver
)
return
fmt
.
Errorf
(
"Error during code execution %v (deepErr = %v)"
,
err
,
deepErr
)
}
}
}
}
}
}
return
nil
return
}
}
func
(
self
*
StateTransition
)
transferValue
(
sender
,
receiver
*
StateObject
)
error
{
func
(
self
*
StateTransition
)
transferValue
(
sender
,
receiver
*
StateObject
)
error
{
if
sender
.
Amount
.
Cmp
(
self
.
tx
.
V
alue
)
<
0
{
if
sender
.
Amount
.
Cmp
(
self
.
v
alue
)
<
0
{
return
fmt
.
Errorf
(
"Insufficient funds to transfer value. Req %v, has %v"
,
self
.
tx
.
V
alue
,
sender
.
Amount
)
return
fmt
.
Errorf
(
"Insufficient funds to transfer value. Req %v, has %v"
,
self
.
v
alue
,
sender
.
Amount
)
}
}
if
self
.
tx
.
V
alue
.
Cmp
(
ethutil
.
Big0
)
>
0
{
//if self.v
alue.Cmp(ethutil.Big0) > 0 {
// Subtract the amount from the senders account
// Subtract the amount from the senders account
sender
.
SubAmount
(
self
.
tx
.
V
alue
)
sender
.
SubAmount
(
self
.
v
alue
)
// Add the amount to receivers account which should conclude this transaction
// Add the amount to receivers account which should conclude this transaction
receiver
.
AddAmount
(
self
.
tx
.
V
alue
)
receiver
.
AddAmount
(
self
.
v
alue
)
ethutil
.
Config
.
Log
.
Debugf
(
"%x => %x (%v) %x
\n
"
,
sender
.
Address
()[
:
4
],
receiver
.
Address
()[
:
4
],
self
.
tx
.
Value
,
self
.
tx
.
Hash
()
)
//ethutil.Config.Log.Debugf("%x => %x (%v)\n", sender.Address()[:4], receiver.Address()[:4], self.value
)
}
//
}
return
nil
return
nil
}
}
func
(
self
*
StateTransition
)
Eval
(
script
[]
byte
,
context
*
StateObject
)
(
ret
[]
byte
,
err
error
)
{
func
(
self
*
StateTransition
)
Eval
(
script
[]
byte
,
context
*
StateObject
)
(
ret
[]
byte
,
err
error
,
deepErr
bool
)
{
var
(
var
(
tx
=
self
.
tx
block
=
self
.
block
block
=
self
.
block
initiator
=
self
.
Sender
()
initiator
=
self
.
Sender
()
state
=
self
.
state
state
=
self
.
state
)
)
closure
:=
NewClosure
(
initiator
,
context
,
script
,
state
,
self
.
gas
,
tx
.
G
asPrice
)
closure
:=
NewClosure
(
initiator
,
context
,
script
,
state
,
self
.
gas
,
self
.
g
asPrice
)
vm
:=
NewVm
(
state
,
nil
,
RuntimeVars
{
vm
:=
NewVm
(
state
,
nil
,
RuntimeVars
{
Origin
:
initiator
.
Address
(),
Origin
:
initiator
.
Address
(),
BlockNumber
:
block
.
BlockInfo
()
.
Number
,
Block
:
block
,
BlockNumber
:
block
.
Number
,
PrevHash
:
block
.
PrevHash
,
PrevHash
:
block
.
PrevHash
,
Coinbase
:
block
.
Coinbase
,
Coinbase
:
block
.
Coinbase
,
Time
:
block
.
Time
,
Time
:
block
.
Time
,
Diff
:
block
.
Difficulty
,
Diff
:
block
.
Difficulty
,
Value
:
tx
.
V
alue
,
Value
:
self
.
v
alue
,
})
})
ret
,
_
,
err
=
closure
.
Call
(
vm
,
tx
.
Data
,
nil
)
vm
.
Verbose
=
true
ret
,
_
,
err
=
closure
.
Call
(
vm
,
self
.
data
,
nil
)
deepErr
=
vm
.
err
!=
nil
return
return
}
}
ethchain/transaction.go
View file @
3f1f8438
...
@@ -10,6 +10,10 @@ import (
...
@@ -10,6 +10,10 @@ import (
var
ContractAddr
=
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}
var
ContractAddr
=
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}
func
IsContractAddr
(
addr
[]
byte
)
bool
{
return
bytes
.
Compare
(
addr
,
ContractAddr
)
==
0
}
type
Transaction
struct
{
type
Transaction
struct
{
Nonce
uint64
Nonce
uint64
Recipient
[]
byte
Recipient
[]
byte
...
@@ -65,7 +69,7 @@ func (tx *Transaction) CreatesContract() bool {
...
@@ -65,7 +69,7 @@ func (tx *Transaction) CreatesContract() bool {
return
tx
.
contractCreation
return
tx
.
contractCreation
}
}
/* Depr
i
cated */
/* Depr
e
cated */
func
(
tx
*
Transaction
)
IsContract
()
bool
{
func
(
tx
*
Transaction
)
IsContract
()
bool
{
return
tx
.
CreatesContract
()
return
tx
.
CreatesContract
()
}
}
...
@@ -149,7 +153,7 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
...
@@ -149,7 +153,7 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx
.
r
=
decoder
.
Get
(
7
)
.
Bytes
()
tx
.
r
=
decoder
.
Get
(
7
)
.
Bytes
()
tx
.
s
=
decoder
.
Get
(
8
)
.
Bytes
()
tx
.
s
=
decoder
.
Get
(
8
)
.
Bytes
()
if
bytes
.
Compare
(
tx
.
Recipient
,
ContractAddr
)
==
0
{
if
IsContractAddr
(
tx
.
Recipient
)
{
tx
.
contractCreation
=
true
tx
.
contractCreation
=
true
}
}
}
}
...
...
ethchain/types.go
View file @
3f1f8438
...
@@ -166,6 +166,7 @@ var opCodeToString = map[OpCode]string{
...
@@ -166,6 +166,7 @@ var opCodeToString = map[OpCode]string{
GASLIMIT
:
"GASLIMIT"
,
GASLIMIT
:
"GASLIMIT"
,
// 0x50 range - 'storage' and execution
// 0x50 range - 'storage' and execution
POP
:
"POP"
,
DUP
:
"DUP"
,
DUP
:
"DUP"
,
SWAP
:
"SWAP"
,
SWAP
:
"SWAP"
,
MLOAD
:
"MLOAD"
,
MLOAD
:
"MLOAD"
,
...
@@ -226,7 +227,7 @@ var opCodeToString = map[OpCode]string{
...
@@ -226,7 +227,7 @@ var opCodeToString = map[OpCode]string{
func
(
o
OpCode
)
String
()
string
{
func
(
o
OpCode
)
String
()
string
{
str
:=
opCodeToString
[
o
]
str
:=
opCodeToString
[
o
]
if
len
(
str
)
==
0
{
if
len
(
str
)
==
0
{
return
fmt
.
Sprintf
(
"Missing opcode
%#
x"
,
int
(
o
))
return
fmt
.
Sprintf
(
"Missing opcode
0x%
x"
,
int
(
o
))
}
}
return
str
return
str
...
...
ethchain/vm.go
View file @
3f1f8438
package
ethchain
package
ethchain
import
(
import
(
_
"bytes"
"fmt"
"fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
_
"github.com/obscuren/secp256k1-go"
"math"
"math"
_
"math"
"math/big"
"math/big"
)
)
...
@@ -45,11 +42,18 @@ type Vm struct {
...
@@ -45,11 +42,18 @@ type Vm struct {
state
*
State
state
*
State
stateManager
*
StateManager
stateManager
*
StateManager
Verbose
bool
logStr
string
err
error
}
}
type
RuntimeVars
struct
{
type
RuntimeVars
struct
{
Origin
[]
byte
Origin
[]
byte
BlockNumber
uint64
Block
*
Block
BlockNumber
*
big
.
Int
PrevHash
[]
byte
PrevHash
[]
byte
Coinbase
[]
byte
Coinbase
[]
byte
Time
int64
Time
int64
...
@@ -58,6 +62,23 @@ type RuntimeVars struct {
...
@@ -58,6 +62,23 @@ type RuntimeVars struct {
Value
*
big
.
Int
Value
*
big
.
Int
}
}
func
(
self
*
Vm
)
Printf
(
format
string
,
v
...
interface
{})
*
Vm
{
if
self
.
Verbose
{
self
.
logStr
+=
fmt
.
Sprintf
(
format
,
v
...
)
}
return
self
}
func
(
self
*
Vm
)
Endl
()
*
Vm
{
if
self
.
Verbose
{
ethutil
.
Config
.
Log
.
Infoln
(
self
.
logStr
)
self
.
logStr
=
""
}
return
self
}
func
NewVm
(
state
*
State
,
stateManager
*
StateManager
,
vars
RuntimeVars
)
*
Vm
{
func
NewVm
(
state
*
State
,
stateManager
*
StateManager
,
vars
RuntimeVars
)
*
Vm
{
return
&
Vm
{
vars
:
vars
,
state
:
state
,
stateManager
:
stateManager
}
return
&
Vm
{
vars
:
vars
,
state
:
state
,
stateManager
:
stateManager
}
}
}
...
@@ -69,14 +90,14 @@ var isRequireError = false
...
@@ -69,14 +90,14 @@ var isRequireError = false
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
,
hook
DebugHook
)
(
ret
[]
byte
,
err
error
)
{
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
,
hook
DebugHook
)
(
ret
[]
byte
,
err
error
)
{
// Recover from any require exception
// Recover from any require exception
defer
func
()
{
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
/*&& isRequireError*/
{
if
r
:=
recover
();
r
!=
nil
{
ret
=
closure
.
Return
(
nil
)
ret
=
closure
.
Return
(
nil
)
err
=
fmt
.
Errorf
(
"%v"
,
r
)
err
=
fmt
.
Errorf
(
"%v"
,
r
)
fmt
.
Println
(
"vm err"
,
err
)
fmt
.
Println
(
"vm err"
,
err
)
}
}
}()
}()
ethutil
.
Config
.
Log
.
Debugf
(
"[VM]
Running closure %x
\n
"
,
closure
.
object
.
Address
()
)
ethutil
.
Config
.
Log
.
Debugf
(
"[VM]
(~) %x gas: %v (d) %x
\n
"
,
closure
.
object
.
Address
(),
closure
.
Gas
,
closure
.
Args
)
// Memory for the current closure
// Memory for the current closure
mem
:=
&
Memory
{}
mem
:=
&
Memory
{}
...
@@ -95,10 +116,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -95,10 +116,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
step
:=
0
step
:=
0
prevStep
:=
0
prevStep
:=
0
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
}
for
{
for
{
prevStep
=
step
prevStep
=
step
// The base for all big integer arithmetic
// The base for all big integer arithmetic
...
@@ -109,21 +126,22 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -109,21 +126,22 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
val
:=
closure
.
Get
(
pc
)
val
:=
closure
.
Get
(
pc
)
// Get the opcode (it must be an opcode!)
// Get the opcode (it must be an opcode!)
op
:=
OpCode
(
val
.
Uint
())
op
:=
OpCode
(
val
.
Uint
())
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"%-3d %-4s"
,
pc
,
op
.
String
())
}
gas
:=
new
(
big
.
Int
)
gas
:=
new
(
big
.
Int
)
addStepGasUsage
:=
func
(
amount
*
big
.
Int
)
{
addStepGasUsage
:=
func
(
amount
*
big
.
Int
)
{
if
amount
.
Cmp
(
ethutil
.
Big0
)
>=
0
{
gas
.
Add
(
gas
,
amount
)
gas
.
Add
(
gas
,
amount
)
}
}
}
addStepGasUsage
(
GasStep
)
addStepGasUsage
(
GasStep
)
var
newMemSize
uint64
=
0
var
newMemSize
uint64
=
0
switch
op
{
switch
op
{
case
STOP
:
case
STOP
:
gas
.
Set
(
ethutil
.
Big0
)
case
SUICIDE
:
case
SUICIDE
:
gas
.
Set
(
ethutil
.
Big0
)
case
SLOAD
:
case
SLOAD
:
gas
.
Set
(
GasSLoad
)
gas
.
Set
(
GasSLoad
)
case
SSTORE
:
case
SSTORE
:
...
@@ -169,7 +187,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -169,7 +187,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
CALL
:
case
CALL
:
require
(
7
)
require
(
7
)
gas
.
Set
(
GasCall
)
gas
.
Set
(
GasCall
)
addStepGasUsage
(
stack
.
data
[
stack
.
Len
()
-
2
])
addStepGasUsage
(
stack
.
data
[
stack
.
Len
()
-
1
])
x
:=
stack
.
data
[
stack
.
Len
()
-
6
]
.
Uint64
()
+
stack
.
data
[
stack
.
Len
()
-
7
]
.
Uint64
()
x
:=
stack
.
data
[
stack
.
Len
()
-
6
]
.
Uint64
()
+
stack
.
data
[
stack
.
Len
()
-
7
]
.
Uint64
()
y
:=
stack
.
data
[
stack
.
Len
()
-
4
]
.
Uint64
()
+
stack
.
data
[
stack
.
Len
()
-
5
]
.
Uint64
()
y
:=
stack
.
data
[
stack
.
Len
()
-
4
]
.
Uint64
()
+
stack
.
data
[
stack
.
Len
()
-
5
]
.
Uint64
()
...
@@ -189,11 +207,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -189,11 +207,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
}
if
!
closure
.
UseGas
(
gas
)
{
if
!
closure
.
UseGas
(
gas
)
{
e
thutil
.
Config
.
Log
.
Debugln
(
"Insufficient gas"
,
closure
.
Gas
,
g
as
)
e
rr
:=
fmt
.
Errorf
(
"Insufficient gas for %v. req %v has %v"
,
op
,
gas
,
closure
.
G
as
)
return
closure
.
Return
(
nil
),
fmt
.
Errorf
(
"insufficient gas %v %v"
,
closure
.
Gas
,
gas
)
closure
.
UseGas
(
closure
.
Gas
)
return
closure
.
Return
(
nil
),
err
}
}
vm
.
Printf
(
"(pc) %-3d -o- %-14s"
,
pc
,
op
.
String
())
vm
.
Printf
(
" (g) %-3v (%v)"
,
gas
,
closure
.
Gas
)
mem
.
Resize
(
newMemSize
)
mem
.
Resize
(
newMemSize
)
switch
op
{
switch
op
{
...
@@ -204,29 +227,41 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -204,29 +227,41 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
ADD
:
case
ADD
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
vm
.
Printf
(
" %v + %v"
,
y
,
x
)
base
.
Add
(
x
,
y
)
base
.
Add
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
SUB
:
case
SUB
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
vm
.
Printf
(
" %v - %v"
,
y
,
x
)
base
.
Sub
(
x
,
y
)
base
.
Sub
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
MUL
:
case
MUL
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
vm
.
Printf
(
" %v * %v"
,
y
,
x
)
base
.
Mul
(
x
,
y
)
base
.
Mul
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
DIV
:
case
DIV
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
// floor(x / y)
vm
.
Printf
(
" %v / %v"
,
y
,
x
)
base
.
Div
(
x
,
y
)
base
.
Div
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
// Pop result back on the stack
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
SDIV
:
case
SDIV
:
...
@@ -249,7 +284,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -249,7 +284,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
MOD
:
case
MOD
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
vm
.
Printf
(
" %v %% %v"
,
y
,
x
)
base
.
Mod
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
SMOD
:
case
SMOD
:
require
(
2
)
require
(
2
)
...
@@ -271,7 +311,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -271,7 +311,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
EXP
:
case
EXP
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
vm
.
Printf
(
" %v ** %v"
,
y
,
x
)
base
.
Exp
(
y
,
x
,
Pow256
)
vm
.
Printf
(
" = %v"
,
base
)
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
NEG
:
case
NEG
:
...
@@ -280,7 +325,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -280,7 +325,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack
.
Push
(
base
)
stack
.
Push
(
base
)
case
LT
:
case
LT
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
y
,
x
:=
stack
.
Popn
()
vm
.
Printf
(
" %v < %v"
,
x
,
y
)
// x < y
// x < y
if
x
.
Cmp
(
y
)
<
0
{
if
x
.
Cmp
(
y
)
<
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
...
@@ -289,7 +335,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -289,7 +335,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
}
case
GT
:
case
GT
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
y
,
x
:=
stack
.
Popn
()
vm
.
Printf
(
" %v > %v"
,
x
,
y
)
// x > y
// x > y
if
x
.
Cmp
(
y
)
>
0
{
if
x
.
Cmp
(
y
)
>
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
...
@@ -299,6 +347,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -299,6 +347,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
EQ
:
case
EQ
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
vm
.
Printf
(
" %v == %v"
,
y
,
x
)
// x == y
// x == y
if
x
.
Cmp
(
y
)
==
0
{
if
x
.
Cmp
(
y
)
==
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
...
@@ -318,24 +368,21 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -318,24 +368,21 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
AND
:
case
AND
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
&&
(
y
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
{
vm
.
Printf
(
" %v & %v"
,
y
,
x
)
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
stack
.
Push
(
base
.
And
(
y
,
x
))
case
OR
:
case
OR
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
||
(
y
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
{
vm
.
Printf
(
" %v | %v"
,
y
,
x
)
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
base
.
Or
(
y
,
x
))
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
XOR
:
case
XOR
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
stack
.
Push
(
base
.
Xor
(
x
,
y
))
vm
.
Printf
(
" %v ^ %v"
,
y
,
x
)
stack
.
Push
(
base
.
Xor
(
y
,
x
))
case
BYTE
:
case
BYTE
:
require
(
2
)
require
(
2
)
val
,
th
:=
stack
.
Popn
()
val
,
th
:=
stack
.
Popn
()
...
@@ -360,25 +407,35 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -360,25 +407,35 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
ORIGIN
:
case
ORIGIN
:
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
Origin
))
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
Origin
))
case
CALLER
:
case
CALLER
:
stack
.
Push
(
ethutil
.
BigD
(
closure
.
caller
.
Address
()))
caller
:=
closure
.
caller
.
Address
()
stack
.
Push
(
ethutil
.
BigD
(
caller
))
vm
.
Printf
(
" => %x"
,
caller
)
case
CALLVALUE
:
case
CALLVALUE
:
stack
.
Push
(
vm
.
vars
.
Value
)
stack
.
Push
(
vm
.
vars
.
Value
)
case
CALLDATALOAD
:
case
CALLDATALOAD
:
require
(
1
)
require
(
1
)
offset
:=
stack
.
Pop
()
.
Int64
()
offset
:=
stack
.
Pop
()
.
Int64
()
var
data
[]
byte
data
:=
make
([]
byte
,
32
)
if
len
(
closure
.
Args
)
>=
int
(
offset
+
32
)
{
if
len
(
closure
.
Args
)
>=
int
(
offset
)
{
data
=
closure
.
Args
[
offset
:
offset
+
32
]
l
:=
int64
(
math
.
Min
(
float64
(
offset
+
32
),
float64
(
len
(
closure
.
Args
))))
}
else
{
data
=
[]
byte
{
0
}
copy
(
data
,
closure
.
Args
[
offset
:
l
])
}
}
vm
.
Printf
(
" => 0x%x"
,
data
)
stack
.
Push
(
ethutil
.
BigD
(
data
))
stack
.
Push
(
ethutil
.
BigD
(
data
))
case
CALLDATASIZE
:
case
CALLDATASIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Args
))))
l
:=
int64
(
len
(
closure
.
Args
))
stack
.
Push
(
big
.
NewInt
(
l
))
vm
.
Printf
(
" => %d"
,
l
)
case
CALLDATACOPY
:
case
CALLDATACOPY
:
panic
(
"not implemented"
)
case
CODESIZE
:
case
CODESIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Script
))))
case
CODECOPY
:
case
CODECOPY
:
var
(
var
(
size
=
int64
(
len
(
closure
.
Script
))
size
=
int64
(
len
(
closure
.
Script
))
...
@@ -408,7 +465,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -408,7 +465,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
TIMESTAMP
:
case
TIMESTAMP
:
stack
.
Push
(
big
.
NewInt
(
vm
.
vars
.
Time
))
stack
.
Push
(
big
.
NewInt
(
vm
.
vars
.
Time
))
case
NUMBER
:
case
NUMBER
:
stack
.
Push
(
big
.
NewInt
(
int64
(
vm
.
vars
.
BlockNumber
))
)
stack
.
Push
(
vm
.
vars
.
BlockNumber
)
case
DIFFICULTY
:
case
DIFFICULTY
:
stack
.
Push
(
vm
.
vars
.
Diff
)
stack
.
Push
(
vm
.
vars
.
Diff
)
case
GASLIMIT
:
case
GASLIMIT
:
...
@@ -426,12 +483,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -426,12 +483,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
pc
.
Add
(
pc
,
a
.
Sub
(
a
,
big
.
NewInt
(
1
)))
pc
.
Add
(
pc
,
a
.
Sub
(
a
,
big
.
NewInt
(
1
)))
step
+=
int
(
op
)
-
int
(
PUSH1
)
+
1
step
+=
int
(
op
)
-
int
(
PUSH1
)
+
1
vm
.
Printf
(
" => 0x%x"
,
data
.
Bytes
())
case
POP
:
case
POP
:
require
(
1
)
require
(
1
)
stack
.
Pop
()
stack
.
Pop
()
case
DUP
:
case
DUP
:
require
(
1
)
require
(
1
)
stack
.
Push
(
stack
.
Peek
())
stack
.
Push
(
stack
.
Peek
())
vm
.
Printf
(
" => 0x%x"
,
stack
.
Peek
()
.
Bytes
())
case
SWAP
:
case
SWAP
:
require
(
2
)
require
(
2
)
x
,
y
:=
stack
.
Popn
()
x
,
y
:=
stack
.
Popn
()
...
@@ -446,38 +507,53 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -446,38 +507,53 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Pop value of the stack
// Pop value of the stack
val
,
mStart
:=
stack
.
Popn
()
val
,
mStart
:=
stack
.
Popn
()
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
vm
.
Printf
(
" => 0x%x"
,
val
)
case
MSTORE8
:
case
MSTORE8
:
require
(
2
)
require
(
2
)
val
,
mStart
:=
stack
.
Popn
()
val
,
mStart
:=
stack
.
Popn
()
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
vm
.
Printf
(
" => 0x%x"
,
val
)
case
SLOAD
:
case
SLOAD
:
require
(
1
)
require
(
1
)
loc
:=
stack
.
Pop
()
loc
:=
stack
.
Pop
()
val
:=
closure
.
GetMem
(
loc
)
val
:=
closure
.
GetMem
(
loc
)
//fmt.Println("get", val.BigInt(), "@", loc)
stack
.
Push
(
val
.
BigInt
())
stack
.
Push
(
val
.
BigInt
())
vm
.
Printf
(
" {} 0x%x"
,
val
)
case
SSTORE
:
case
SSTORE
:
require
(
2
)
require
(
2
)
val
,
loc
:=
stack
.
Popn
()
val
,
loc
:=
stack
.
Popn
()
//fmt.Println("storing", val, "@", loc)
// FIXME This should be handled in the Trie it self
if
val
.
Cmp
(
big
.
NewInt
(
0
))
!=
0
{
closure
.
SetStorage
(
loc
,
ethutil
.
NewValue
(
val
))
closure
.
SetStorage
(
loc
,
ethutil
.
NewValue
(
val
))
}
// Add the change to manifest
// Add the change to manifest
vm
.
state
.
manifest
.
AddStorageChange
(
closure
.
Object
(),
loc
.
Bytes
(),
val
)
vm
.
state
.
manifest
.
AddStorageChange
(
closure
.
Object
(),
loc
.
Bytes
(),
val
)
vm
.
Printf
(
" {0x%x} 0x%x"
,
loc
,
val
)
case
JUMP
:
case
JUMP
:
require
(
1
)
require
(
1
)
pc
=
stack
.
Pop
()
pc
=
stack
.
Pop
()
// Reduce pc by one because of the increment that's at the end of this for loop
// Reduce pc by one because of the increment that's at the end of this for loop
//pc.Sub(pc, ethutil.Big1)
vm
.
Printf
(
" ~> %v"
,
pc
)
.
Endl
()
continue
continue
case
JUMPI
:
case
JUMPI
:
require
(
2
)
require
(
2
)
cond
,
pos
:=
stack
.
Popn
()
cond
,
pos
:=
stack
.
Popn
()
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
=
=
0
{
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
>
=
0
{
pc
=
pos
pc
=
pos
//pc.Sub(pc, ethutil.Big1)
vm
.
Printf
(
" ~> %v (t)"
,
pc
)
.
Endl
()
continue
continue
}
else
{
vm
.
Printf
(
" (f)"
)
}
}
case
PC
:
case
PC
:
stack
.
Push
(
pc
)
stack
.
Push
(
pc
)
...
@@ -494,7 +570,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -494,7 +570,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Snapshot the current stack so we are able to
// Snapshot the current stack so we are able to
// revert back to it later.
// revert back to it later.
snapshot
:=
vm
.
state
.
Snapshot
()
snapshot
:=
vm
.
state
.
Copy
()
// Generate a new address
// Generate a new address
addr
:=
ethutil
.
CreateAddress
(
closure
.
caller
.
Address
(),
closure
.
caller
.
N
())
addr
:=
ethutil
.
CreateAddress
(
closure
.
caller
.
Address
(),
closure
.
caller
.
N
())
...
@@ -522,19 +598,18 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -522,19 +598,18 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
// Revert the state as it was before.
// Revert the state as it was before.
vm
.
state
.
Rever
t
(
snapshot
)
vm
.
state
.
Se
t
(
snapshot
)
}
else
{
}
else
{
stack
.
Push
(
ethutil
.
BigD
(
addr
))
stack
.
Push
(
ethutil
.
BigD
(
addr
))
vm
.
state
.
UpdateStateObject
(
contract
)
}
}
case
CALL
:
case
CALL
:
// TODO RE-WRITE
require
(
7
)
require
(
7
)
// Closure addr
addr
:=
stack
.
Pop
()
vm
.
Endl
()
gas
:=
stack
.
Pop
()
// Pop gas and value of the stack.
// Pop gas and value of the stack.
gas
,
value
:=
stack
.
Popn
()
value
,
addr
:=
stack
.
Popn
()
// Pop input size and offset
// Pop input size and offset
inSize
,
inOffset
:=
stack
.
Popn
()
inSize
,
inOffset
:=
stack
.
Popn
()
// Pop return size and offset
// Pop return size and offset
...
@@ -543,58 +618,59 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -543,58 +618,59 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Get the arguments from the memory
// Get the arguments from the memory
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
snapshot
:=
vm
.
state
.
Snapshot
()
closure
.
object
.
Nonce
+=
1
if
closure
.
object
.
Amount
.
Cmp
(
value
)
<
0
{
if
closure
.
object
.
Amount
.
Cmp
(
value
)
<
0
{
ethutil
.
Config
.
Log
.
Debugf
(
"Insufficient funds to transfer value. Req %v, has %v"
,
value
,
closure
.
object
.
Amount
)
ethutil
.
Config
.
Log
.
Debugf
(
"Insufficient funds to transfer value. Req %v, has %v"
,
value
,
closure
.
object
.
Amount
)
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
else
{
}
else
{
// Fetch the contract which will serve as the closure body
snapshot
:=
vm
.
state
.
Copy
()
contract
:=
vm
.
state
.
GetStateObject
(
addr
.
Bytes
())
stateObject
:=
vm
.
state
.
GetOrNewStateObject
(
addr
.
Bytes
())
if
contract
!=
nil
{
closure
.
object
.
SubAmount
(
value
)
// Add the value to the state object
// Add the value to the state object
contra
ct
.
AddAmount
(
value
)
stateObje
ct
.
AddAmount
(
value
)
// Create a new callable closure
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
contract
,
contra
ct
.
script
,
vm
.
state
,
gas
,
closure
.
Price
)
closure
:=
NewClosure
(
closure
,
stateObject
,
stateObje
ct
.
script
,
vm
.
state
,
gas
,
closure
.
Price
)
// Executer the closure and get the return value (if any)
// Executer the closure and get the return value (if any)
ret
,
_
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
ret
,
_
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
if
err
!=
nil
{
if
err
!=
nil
{
stack
.
Push
(
ethutil
.
BigFalse
)
stack
.
Push
(
ethutil
.
BigFalse
)
// Reset the changes applied this object
vm
.
state
.
Revert
(
snapshot
)
ethutil
.
Config
.
Log
.
Debugf
(
"Closure execution failed. %v
\n
"
,
err
)
vm
.
err
=
err
vm
.
state
.
Set
(
snapshot
)
}
else
{
}
else
{
stack
.
Push
(
ethutil
.
BigTrue
)
stack
.
Push
(
ethutil
.
BigTrue
)
vm
.
state
.
UpdateStateObject
(
contract
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
}
}
}
else
{
ethutil
.
Config
.
Log
.
Debugf
(
"Contract %x not found
\n
"
,
addr
.
Bytes
())
stack
.
Push
(
ethutil
.
BigFalse
)
}
}
}
case
RETURN
:
case
RETURN
:
require
(
2
)
require
(
2
)
size
,
offset
:=
stack
.
Popn
()
size
,
offset
:=
stack
.
Popn
()
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
vm
.
Printf
(
" => (%d) 0x%x"
,
len
(
ret
),
ret
)
.
Endl
()
return
closure
.
Return
(
ret
),
nil
return
closure
.
Return
(
ret
),
nil
case
SUICIDE
:
case
SUICIDE
:
require
(
1
)
require
(
1
)
receiver
:=
vm
.
state
.
GetAccount
(
stack
.
Pop
()
.
Bytes
())
receiver
:=
vm
.
state
.
GetAccount
(
stack
.
Pop
()
.
Bytes
())
receiver
.
AddAmount
(
closure
.
object
.
Amount
)
receiver
.
AddAmount
(
closure
.
object
.
Amount
)
vm
.
state
.
UpdateStateObject
(
receiver
)
closure
.
object
.
state
.
Purge
()
trie
:=
closure
.
object
.
state
.
trie
trie
.
NewIterator
()
.
Each
(
func
(
key
string
,
v
*
ethutil
.
Value
)
{
trie
.
Delete
(
key
)
})
fallthrough
fallthrough
case
STOP
:
// Stop the closure
case
STOP
:
// Stop the closure
vm
.
Printf
(
" (g) %v"
,
closure
.
Gas
)
.
Endl
()
return
closure
.
Return
(
nil
),
nil
return
closure
.
Return
(
nil
),
nil
default
:
default
:
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid opcode %x
\n
"
,
op
)
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid opcode %x
\n
"
,
op
)
...
@@ -604,6 +680,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
...
@@ -604,6 +680,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
pc
.
Add
(
pc
,
ethutil
.
Big1
)
pc
.
Add
(
pc
,
ethutil
.
Big1
)
vm
.
Endl
()
if
hook
!=
nil
{
if
hook
!=
nil
{
if
!
hook
(
prevStep
,
op
,
mem
,
stack
,
closure
.
Object
())
{
if
!
hook
(
prevStep
,
op
,
mem
,
stack
,
closure
.
Object
())
{
return
nil
,
nil
return
nil
,
nil
...
...
ethereum.go
View file @
3f1f8438
...
@@ -149,7 +149,9 @@ func (s *Ethereum) IsUpToDate() bool {
...
@@ -149,7 +149,9 @@ func (s *Ethereum) IsUpToDate() bool {
})
})
return
upToDate
return
upToDate
}
}
func
(
s
*
Ethereum
)
PushPeer
(
peer
*
Peer
)
{
s
.
peers
.
PushBack
(
peer
)
}
func
(
s
*
Ethereum
)
IsListening
()
bool
{
func
(
s
*
Ethereum
)
IsListening
()
bool
{
return
s
.
listening
return
s
.
listening
}
}
...
@@ -159,14 +161,11 @@ func (s *Ethereum) AddPeer(conn net.Conn) {
...
@@ -159,14 +161,11 @@ func (s *Ethereum) AddPeer(conn net.Conn) {
if
peer
!=
nil
{
if
peer
!=
nil
{
if
s
.
peers
.
Len
()
<
s
.
MaxPeers
{
if
s
.
peers
.
Len
()
<
s
.
MaxPeers
{
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
peer
.
Start
()
}
else
{
}
else
{
ethutil
.
Config
.
Log
.
Debugf
(
"[SERV] Max connected peers reached. Not adding incoming peer."
)
ethutil
.
Config
.
Log
.
Debugf
(
"[SERV] Max connected peers reached. Not adding incoming peer."
)
}
}
}
}
s
.
reactor
.
Post
(
"peerList"
,
s
.
peers
)
}
}
func
(
s
*
Ethereum
)
ProcessPeerList
(
addrs
[]
string
)
{
func
(
s
*
Ethereum
)
ProcessPeerList
(
addrs
[]
string
)
{
...
@@ -233,12 +232,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error {
...
@@ -233,12 +232,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error {
return
nil
return
nil
}
}
peer
:=
NewOutboundPeer
(
addr
,
s
,
s
.
serverCaps
)
NewOutboundPeer
(
addr
,
s
,
s
.
serverCaps
)
s
.
peers
.
PushBack
(
peer
)
ethutil
.
Config
.
Log
.
Infof
(
"[SERV] Adding peer (%s) %d / %d
\n
"
,
addr
,
s
.
peers
.
Len
(),
s
.
MaxPeers
)
s
.
reactor
.
Post
(
"peerList"
,
s
.
peers
)
}
}
return
nil
return
nil
...
...
ethminer/miner.go
View file @
3f1f8438
...
@@ -154,6 +154,8 @@ func (self *Miner) mineNewBlock() {
...
@@ -154,6 +154,8 @@ func (self *Miner) mineNewBlock() {
// Accumulate the rewards included for this block
// Accumulate the rewards included for this block
stateManager
.
AccumelateRewards
(
self
.
block
.
State
(),
self
.
block
)
stateManager
.
AccumelateRewards
(
self
.
block
.
State
(),
self
.
block
)
self
.
block
.
State
()
.
Update
()
ethutil
.
Config
.
Log
.
Infoln
(
"[MINER] Mining on block. Includes"
,
len
(
self
.
txs
),
"transactions"
)
ethutil
.
Config
.
Log
.
Infoln
(
"[MINER] Mining on block. Includes"
,
len
(
self
.
txs
),
"transactions"
)
// Find a valid nonce
// Find a valid nonce
...
...
ethpub/pub.go
View file @
3f1f8438
...
@@ -170,11 +170,6 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, sc
...
@@ -170,11 +170,6 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, sc
tx
=
ethchain
.
NewContractCreationTx
(
value
,
gas
,
gasPrice
,
script
)
tx
=
ethchain
.
NewContractCreationTx
(
value
,
gas
,
gasPrice
,
script
)
}
else
{
}
else
{
// Just in case it was submitted as a 0x prefixed string
if
len
(
scriptStr
)
>
0
&&
scriptStr
[
0
:
2
]
==
"0x"
{
scriptStr
=
scriptStr
[
2
:
len
(
scriptStr
)]
}
data
:=
ethutil
.
StringToByteFunc
(
scriptStr
,
func
(
s
string
)
(
ret
[]
byte
)
{
data
:=
ethutil
.
StringToByteFunc
(
scriptStr
,
func
(
s
string
)
(
ret
[]
byte
)
{
slice
:=
strings
.
Split
(
s
,
"
\n
"
)
slice
:=
strings
.
Split
(
s
,
"
\n
"
)
for
_
,
dataItem
:=
range
slice
{
for
_
,
dataItem
:=
range
slice
{
...
...
ethpub/types.go
View file @
3f1f8438
...
@@ -104,16 +104,17 @@ type PTx struct {
...
@@ -104,16 +104,17 @@ type PTx struct {
func
NewPTx
(
tx
*
ethchain
.
Transaction
)
*
PTx
{
func
NewPTx
(
tx
*
ethchain
.
Transaction
)
*
PTx
{
hash
:=
hex
.
EncodeToString
(
tx
.
Hash
())
hash
:=
hex
.
EncodeToString
(
tx
.
Hash
())
receiver
:=
hex
.
EncodeToString
(
tx
.
Recipient
)
receiver
:=
hex
.
EncodeToString
(
tx
.
Recipient
)
if
receiver
==
"0000000000000000000000000000000000000000"
{
if
receiver
==
""
{
receiver
=
hex
.
EncodeToString
(
tx
.
CreationAddress
())
receiver
=
hex
.
EncodeToString
(
tx
.
CreationAddress
())
}
}
sender
:=
hex
.
EncodeToString
(
tx
.
Sender
())
sender
:=
hex
.
EncodeToString
(
tx
.
Sender
())
createsContract
:=
tx
.
CreatesContract
()
createsContract
:=
tx
.
CreatesContract
()
data
:=
string
(
tx
.
Data
)
var
data
string
if
tx
.
CreatesContract
()
{
if
tx
.
CreatesContract
()
{
data
=
strings
.
Join
(
ethchain
.
Disassemble
(
tx
.
Data
),
"
\n
"
)
data
=
strings
.
Join
(
ethchain
.
Disassemble
(
tx
.
Data
),
"
\n
"
)
}
else
{
data
=
hex
.
EncodeToString
(
tx
.
Data
)
}
}
return
&
PTx
{
ref
:
tx
,
Hash
:
hash
,
Value
:
ethutil
.
CurrencyToString
(
tx
.
Value
),
Address
:
receiver
,
Contract
:
tx
.
CreatesContract
(),
Gas
:
tx
.
Gas
.
String
(),
GasPrice
:
tx
.
GasPrice
.
String
(),
Data
:
data
,
Sender
:
sender
,
CreatesContract
:
createsContract
,
RawData
:
hex
.
EncodeToString
(
tx
.
Data
)}
return
&
PTx
{
ref
:
tx
,
Hash
:
hash
,
Value
:
ethutil
.
CurrencyToString
(
tx
.
Value
),
Address
:
receiver
,
Contract
:
tx
.
CreatesContract
(),
Gas
:
tx
.
Gas
.
String
(),
GasPrice
:
tx
.
GasPrice
.
String
(),
Data
:
data
,
Sender
:
sender
,
CreatesContract
:
createsContract
,
RawData
:
hex
.
EncodeToString
(
tx
.
Data
)}
...
...
ethutil/bytes.go
View file @
3f1f8438
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"encoding/binary"
"fmt"
"fmt"
"math/big"
"math/big"
"strings"
)
)
// Number to bytes
// Number to bytes
...
@@ -91,7 +92,7 @@ func IsHex(str string) bool {
...
@@ -91,7 +92,7 @@ func IsHex(str string) bool {
}
}
func
StringToByteFunc
(
str
string
,
cb
func
(
str
string
)
[]
byte
)
(
ret
[]
byte
)
{
func
StringToByteFunc
(
str
string
,
cb
func
(
str
string
)
[]
byte
)
(
ret
[]
byte
)
{
if
len
(
str
)
>
1
&&
str
[
0
:
2
]
==
"0x"
{
if
len
(
str
)
>
1
&&
str
[
0
:
2
]
==
"0x"
&&
!
strings
.
Contains
(
str
,
"
\n
"
)
{
ret
=
FromHex
(
str
[
2
:
])
ret
=
FromHex
(
str
[
2
:
])
}
else
{
}
else
{
ret
=
cb
(
str
)
ret
=
cb
(
str
)
...
...
ethutil/config.go
View file @
3f1f8438
...
@@ -75,7 +75,7 @@ func ReadConfig(base string, logTypes LoggerType, g *globalconf.GlobalConf, id s
...
@@ -75,7 +75,7 @@ func ReadConfig(base string, logTypes LoggerType, g *globalconf.GlobalConf, id s
if
Config
==
nil
{
if
Config
==
nil
{
path
:=
ApplicationFolder
(
base
)
path
:=
ApplicationFolder
(
base
)
Config
=
&
config
{
ExecPath
:
path
,
Debug
:
true
,
Ver
:
"0.5.1
3
"
}
Config
=
&
config
{
ExecPath
:
path
,
Debug
:
true
,
Ver
:
"0.5.1
4
"
}
Config
.
conf
=
g
Config
.
conf
=
g
Config
.
Identifier
=
id
Config
.
Identifier
=
id
Config
.
Log
=
NewLogger
(
logTypes
,
LogLevelDebug
)
Config
.
Log
=
NewLogger
(
logTypes
,
LogLevelDebug
)
...
...
ethutil/trie_test.go
View file @
3f1f8438
...
@@ -173,12 +173,21 @@ func TestTriePurge(t *testing.T) {
...
@@ -173,12 +173,21 @@ func TestTriePurge(t *testing.T) {
func
TestTrieIt
(
t
*
testing
.
T
)
{
func
TestTrieIt
(
t
*
testing
.
T
)
{
_
,
trie
:=
New
()
_
,
trie
:=
New
()
trie
.
Update
(
"c"
,
LONG_WORD
)
trie
.
Update
(
"ca"
,
LONG_WORD
)
trie
.
Update
(
"cat"
,
LONG_WORD
)
it
:=
trie
.
NewIterator
()
data
:=
[][]
string
{
it
.
Each
(
func
(
key
string
,
node
*
Value
)
{
{
"do"
,
"verb"
},
fmt
.
Println
(
key
,
":"
,
node
.
Str
())
{
"ether"
,
"wookiedoo"
},
})
{
"horse"
,
"stallion"
},
{
"shaman"
,
"horse"
},
{
"doge"
,
"coin"
},
{
"ether"
,
""
},
{
"dog"
,
"puppy"
},
{
"shaman"
,
""
},
}
for
_
,
item
:=
range
data
{
trie
.
Update
(
item
[
0
],
item
[
1
])
}
fmt
.
Printf
(
"root %x"
,
trie
.
Root
)
}
}
ethutil/value.go
View file @
3f1f8438
...
@@ -114,6 +114,8 @@ func (val *Value) Str() string {
...
@@ -114,6 +114,8 @@ func (val *Value) Str() string {
func
(
val
*
Value
)
Bytes
()
[]
byte
{
func
(
val
*
Value
)
Bytes
()
[]
byte
{
if
a
,
ok
:=
val
.
Val
.
([]
byte
);
ok
{
if
a
,
ok
:=
val
.
Val
.
([]
byte
);
ok
{
return
a
return
a
}
else
if
s
,
ok
:=
val
.
Val
.
(
byte
);
ok
{
return
[]
byte
{
s
}
}
}
return
[]
byte
{}
return
[]
byte
{}
...
...
peer.go
View file @
3f1f8438
...
@@ -2,6 +2,7 @@ package eth
...
@@ -2,6 +2,7 @@ package eth
import
(
import
(
"bytes"
"bytes"
"container/list"
"fmt"
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethutil"
...
@@ -124,6 +125,7 @@ type Peer struct {
...
@@ -124,6 +125,7 @@ type Peer struct {
port
uint16
port
uint16
caps
Caps
caps
Caps
// This peer's public key
pubkey
[]
byte
pubkey
[]
byte
// Indicated whether the node is catching up or not
// Indicated whether the node is catching up or not
...
@@ -171,7 +173,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
...
@@ -171,7 +173,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
// 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
go
func
()
{
go
func
()
{
conn
,
err
:=
net
.
DialTimeout
(
"tcp"
,
addr
,
3
0
*
time
.
Second
)
conn
,
err
:=
net
.
DialTimeout
(
"tcp"
,
addr
,
1
0
*
time
.
Second
)
if
err
!=
nil
{
if
err
!=
nil
{
ethutil
.
Config
.
Log
.
Debugln
(
"Connection to peer failed"
,
err
)
ethutil
.
Config
.
Log
.
Debugln
(
"Connection to peer failed"
,
err
)
...
@@ -614,6 +616,30 @@ func (p *Peer) pushPeers() {
...
@@ -614,6 +616,30 @@ func (p *Peer) pushPeers() {
func
(
p
*
Peer
)
handleHandshake
(
msg
*
ethwire
.
Msg
)
{
func
(
p
*
Peer
)
handleHandshake
(
msg
*
ethwire
.
Msg
)
{
c
:=
msg
.
Data
c
:=
msg
.
Data
// Set pubkey
p
.
pubkey
=
c
.
Get
(
5
)
.
Bytes
()
if
p
.
pubkey
==
nil
{
//ethutil.Config.Log.Debugln("Pubkey required, not supplied in handshake.")
p
.
Stop
()
return
}
usedPub
:=
0
// This peer is already added to the peerlist so we expect to find a double pubkey at least once
eachPeer
(
p
.
ethereum
.
Peers
(),
func
(
peer
*
Peer
,
e
*
list
.
Element
)
{
if
bytes
.
Compare
(
p
.
pubkey
,
peer
.
pubkey
)
==
0
{
usedPub
++
}
})
if
usedPub
>
0
{
//ethutil.Config.Log.Debugf("Pubkey %x found more then once. Already connected to client.", p.pubkey)
p
.
Stop
()
return
}
if
c
.
Get
(
0
)
.
Uint
()
!=
ProtocolVersion
{
if
c
.
Get
(
0
)
.
Uint
()
!=
ProtocolVersion
{
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid peer version. Require protocol: %d. Received: %d
\n
"
,
ProtocolVersion
,
c
.
Get
(
0
)
.
Uint
())
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid peer version. Require protocol: %d. Received: %d
\n
"
,
ProtocolVersion
,
c
.
Get
(
0
)
.
Uint
())
p
.
Stop
()
p
.
Stop
()
...
@@ -625,7 +651,6 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
...
@@ -625,7 +651,6 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
// If this is an inbound connection send an ack back
// If this is an inbound connection send an ack back
if
p
.
inbound
{
if
p
.
inbound
{
p
.
pubkey
=
c
.
Get
(
5
)
.
Bytes
()
p
.
port
=
uint16
(
c
.
Get
(
4
)
.
Uint
())
p
.
port
=
uint16
(
c
.
Get
(
4
)
.
Uint
())
// Self connect detection
// Self connect detection
...
@@ -647,6 +672,11 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
...
@@ -647,6 +672,11 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
p
.
SetVersion
(
c
.
Get
(
2
)
.
Str
())
p
.
SetVersion
(
c
.
Get
(
2
)
.
Str
())
}
}
p
.
ethereum
.
PushPeer
(
p
)
p
.
ethereum
.
reactor
.
Post
(
"peerList"
,
p
.
ethereum
.
Peers
())
ethutil
.
Config
.
Log
.
Infof
(
"[SERV] Added peer (%s) %d / %d
\n
"
,
p
.
conn
.
RemoteAddr
(),
p
.
ethereum
.
Peers
()
.
Len
(),
p
.
ethereum
.
MaxPeers
)
// Catch up with the connected peer
// Catch up with the connected peer
if
!
p
.
ethereum
.
IsUpToDate
()
{
if
!
p
.
ethereum
.
IsUpToDate
()
{
ethutil
.
Config
.
Log
.
Debugln
(
"Already syncing up with a peer; sleeping"
)
ethutil
.
Config
.
Log
.
Debugln
(
"Already syncing up with a peer; sleeping"
)
...
...
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