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
Hide 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
Ethereum Go Development package (C) Jeffrey Wilcke
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
individual package for more information.
...
...
ethchain/asm.go
View file @
3f1f8438
...
...
@@ -28,7 +28,7 @@ func Disassemble(script []byte) (asm []string) {
if
len
(
data
)
==
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
))
}
...
...
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
import
(
"fmt"
_
"github.com/ethereum/eth-go/ethutil
"
"math
"
"math/big"
)
...
...
@@ -118,7 +118,13 @@ func (m *Memory) Resize(size uint64) {
}
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
{
...
...
ethchain/state.go
View file @
3f1f8438
...
...
@@ -13,8 +13,6 @@ import (
type
State
struct
{
// The trie for this structure
trie
*
ethutil
.
Trie
// Nested states
states
map
[
string
]
*
State
stateObjects
map
[
string
]
*
StateObject
...
...
@@ -23,7 +21,7 @@ type State struct {
// Create a new state from a given trie
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
...
...
@@ -38,12 +36,16 @@ func (s *State) Reset() {
stateObject
.
state
.
Reset
()
}
s
.
Empty
()
}
// Syncs the trie and all siblings
func
(
s
*
State
)
Sync
()
{
// Sync all nested states
for
_
,
stateObject
:=
range
s
.
stateObjects
{
s
.
UpdateStateObject
(
stateObject
)
if
stateObject
.
state
==
nil
{
continue
}
...
...
@@ -52,6 +54,18 @@ func (s *State) 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.
...
...
@@ -64,6 +78,12 @@ func (s *State) EachStorage(cb ethutil.EachCallback) {
it
.
Each
(
cb
)
}
func
(
self
*
State
)
ResetStateObject
(
stateObject
*
StateObject
)
{
delete
(
self
.
stateObjects
,
string
(
stateObject
.
Address
()))
stateObject
.
state
.
Reset
()
}
func
(
self
*
State
)
UpdateStateObject
(
stateObject
*
StateObject
)
{
addr
:=
stateObject
.
Address
()
...
...
@@ -98,13 +118,21 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
func
(
self
*
State
)
GetOrNewStateObject
(
addr
[]
byte
)
*
StateObject
{
stateObject
:=
self
.
GetStateObject
(
addr
)
if
stateObject
==
nil
{
stateObject
=
NewStateObject
(
addr
)
self
.
stateObjects
[
string
(
addr
)]
=
stateObject
stateObject
=
self
.
NewStateObject
(
addr
)
}
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
{
return
self
.
GetOrNewStateObject
(
addr
)
}
...
...
@@ -126,13 +154,10 @@ func (self *State) Copy() *State {
return
nil
}
func
(
s
*
State
)
Snapshot
()
*
State
{
return
s
.
Copy
()
}
func
(
s
*
State
)
Revert
(
snapshot
*
State
)
{
s
.
trie
=
snapshot
.
trie
s
.
states
=
snapshot
.
states
func
(
self
*
State
)
Set
(
state
*
State
)
{
//s.trie = snapshot.trie
//s.stateObjects = snapshot.stateObjects
self
=
state
}
func
(
s
*
State
)
Put
(
key
,
object
[]
byte
)
{
...
...
ethchain/state_manager.go
View file @
3f1f8438
...
...
@@ -127,6 +127,9 @@ done:
// Notify all subscribers
self
.
Ethereum
.
Reactor
()
.
Post
(
"newTx:post"
,
tx
)
// Update the state with pending changes
state
.
Update
()
txGas
.
Sub
(
txGas
,
st
.
gas
)
accumelative
:=
new
(
big
.
Int
)
.
Set
(
totalUsedGas
.
Add
(
totalUsedGas
,
txGas
))
receipt
:=
&
Receipt
{
tx
,
ethutil
.
CopyBytes
(
state
.
Root
()
.
([]
byte
)),
accumelative
}
...
...
@@ -135,8 +138,6 @@ done:
handled
=
append
(
handled
,
tx
)
}
fmt
.
Println
(
"################# MADE
\n
"
,
receipts
,
"
\n
############################"
)
parent
.
GasUsed
=
totalUsedGas
return
receipts
,
handled
,
unhandled
,
err
...
...
@@ -154,7 +155,7 @@ func (sm *StateManager) Process(block *Block, dontReact bool) error {
}
// 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
sm
.
mutex
.
Lock
()
defer
sm
.
mutex
.
Unlock
()
...
...
@@ -175,30 +176,40 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
if
!
sm
.
bc
.
HasBlock
(
block
.
PrevHash
)
&&
sm
.
bc
.
CurrentBlock
!=
nil
{
return
ParentError
(
block
.
PrevHash
)
}
fmt
.
Println
(
block
.
Receipts
())
coinbase
:=
state
.
GetOrNewStateObject
(
block
.
Coinbase
)
coinbase
.
SetGasPool
(
block
.
CalcGasLimit
(
parent
))
// Process the transactions on to current block
//sm.ApplyTransactions(block.Coinbase, state, parent, block.Transactions())
sm
.
ProcessTransactions
(
coinbase
,
state
,
block
,
parent
,
block
.
Transactions
())
receipts
,
_
,
_
,
_
:=
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
if
err
:
=
sm
.
ValidateBlock
(
block
);
err
!=
nil
{
if
err
=
sm
.
ValidateBlock
(
block
);
err
!=
nil
{
fmt
.
Println
(
"[SM] Error validating block:"
,
err
)
return
err
}
// I'm not sure, but I don't know if there should be thrown
// 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
)
return
err
}
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
...
...
@@ -270,10 +281,12 @@ func (sm *StateManager) ValidateBlock(block *Block) error {
return
ValidationError
(
"Block timestamp less then prev block %v"
,
diff
)
}
/* XXX
// New blocks must be within the 15 minute range of the last block.
if diff > int64(15*time.Minute) {
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
if
!
sm
.
Pow
.
Verify
(
block
.
HashNoNonce
(),
block
.
Difficulty
,
block
.
Nonce
)
{
...
...
ethchain/state_object.go
View file @
3f1f8438
...
...
@@ -4,8 +4,15 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"strings"
)
type
Code
[]
byte
func
(
self
Code
)
String
()
string
{
return
strings
.
Join
(
Disassemble
(
self
),
" "
)
}
type
StateObject
struct
{
// Address of the object
address
[]
byte
...
...
@@ -15,8 +22,8 @@ type StateObject struct {
Nonce
uint64
// Contract related attributes
state
*
State
script
[]
byt
e
initScript
[]
byt
e
script
Cod
e
initScript
Cod
e
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
...
...
@@ -30,12 +37,9 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
if
tx
.
IsContract
()
{
addr
:=
tx
.
CreationAddress
()
value
:=
tx
.
Value
contract
:=
NewContract
(
addr
,
value
,
ZeroHash256
)
contract
:=
state
.
NewStateObject
(
addr
)
contract
.
initScript
=
tx
.
Data
state
.
UpdateStateObject
(
contract
)
contract
.
state
=
NewState
(
ethutil
.
NewTrie
(
ethutil
.
Config
.
Db
,
""
))
return
contract
}
...
...
@@ -44,7 +48,7 @@ func MakeContract(tx *Transaction, state *State) *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
{
...
...
@@ -120,13 +124,13 @@ func (c *StateObject) ReturnGas(gas, price *big.Int, state *State) {
func
(
c
*
StateObject
)
AddAmount
(
amount
*
big
.
Int
)
{
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
)
{
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
)
{
...
...
@@ -172,6 +176,26 @@ func (self *StateObject) RefundGas(gas, price *big.Int) {
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 {
stCopy := &StateObject{}
stCopy.address = make([]byte, len(self.address))
...
...
@@ -190,6 +214,7 @@ func (self *StateObject) Copy() *StateObject {
return stCopy
}
*/
// Returns the address of the contract/account
func
(
c
*
StateObject
)
Address
()
[]
byte
{
...
...
@@ -197,12 +222,12 @@ func (c *StateObject) Address() []byte {
}
// Returns the main script body
func
(
c
*
StateObject
)
Script
()
[]
byt
e
{
func
(
c
*
StateObject
)
Script
()
Cod
e
{
return
c
.
script
}
// Returns the initialization script
func
(
c
*
StateObject
)
Init
()
[]
byt
e
{
func
(
c
*
StateObject
)
Init
()
Cod
e
{
return
c
.
initScript
}
...
...
ethchain/state_transition.go
View file @
3f1f8438
...
...
@@ -23,17 +23,19 @@ import (
* 6) Derive new state root
*/
type
StateTransition
struct
{
coinbase
[]
byte
tx
*
Transaction
gas
*
big
.
Int
state
*
State
block
*
Block
coinbase
,
receiver
[]
byte
tx
*
Transaction
gas
,
gasPrice
*
big
.
Int
value
*
big
.
Int
data
[]
byte
state
*
State
block
*
Block
cb
,
rec
,
sen
*
StateObject
}
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
{
...
...
@@ -53,7 +55,7 @@ func (self *StateTransition) Sender() *StateObject {
return
self
.
sen
}
func
(
self
*
StateTransition
)
Receiver
()
*
StateObject
{
if
self
.
tx
.
CreatesContract
()
{
if
self
.
tx
!=
nil
&&
self
.
tx
.
CreatesContract
()
{
return
nil
}
...
...
@@ -67,13 +69,8 @@ func (self *StateTransition) Receiver() *StateObject {
func
(
self
*
StateTransition
)
MakeStateObject
(
state
*
State
,
tx
*
Transaction
)
*
StateObject
{
contract
:=
MakeContract
(
tx
,
state
)
if
contract
!=
nil
{
state
.
states
[
string
(
tx
.
CreationAddress
())]
=
contract
.
state
return
contract
}
return
nil
return
contract
}
func
(
self
*
StateTransition
)
UseGas
(
amount
*
big
.
Int
)
error
{
...
...
@@ -94,7 +91,7 @@ func (self *StateTransition) BuyGas() error {
sender
:=
self
.
Sender
()
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
()
...
...
@@ -102,7 +99,6 @@ func (self *StateTransition) BuyGas() error {
if
err
!=
nil
{
return
err
}
//self.state.UpdateStateObject(coinbase)
self
.
AddGas
(
self
.
tx
.
Gas
)
sender
.
SubAmount
(
self
.
tx
.
GasValue
())
...
...
@@ -119,22 +115,10 @@ func (self *StateTransition) RefundGas() {
sender
.
AddAmount
(
remaining
)
}
func
(
self
*
StateTransition
)
TransitionState
()
(
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)
}
}()
*/
func
(
self
*
StateTransition
)
preCheck
()
(
err
error
)
{
var
(
tx
=
self
.
tx
sender
=
self
.
Sender
()
receiver
*
StateObject
tx
=
self
.
tx
sender
=
self
.
Sender
()
)
// Make sure this transaction's nonce is correct
...
...
@@ -147,38 +131,49 @@ func (self *StateTransition) TransitionState() (err error) {
return
err
}
// XXX Transactions after this point are considered valid.
return
nil
}
defer
func
(
)
{
self
.
RefundGas
(
)
func
(
self
*
StateTransition
)
TransitionState
()
(
err
error
)
{
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
{
self
.
state
.
UpdateStateObject
(
receiver
)
}
// XXX Transactions after this point are considered valid.
if
err
=
self
.
preCheck
();
err
!=
nil
{
return
}
var
(
tx
=
self
.
tx
sender
=
self
.
Sender
()
receiver
*
StateObject
)
self
.
state
.
UpdateStateObject
(
self
.
Coinbase
())
}()
defer
self
.
RefundGas
()
// Increment the nonce for the next transaction
sender
.
Nonce
+=
1
// Get the receiver (TODO fix this, if coinbase is the receiver we need to save/retrieve)
receiver
=
self
.
Receiver
()
// Transaction gas
if
err
=
self
.
UseGas
(
GasTx
);
err
!=
nil
{
return
err
return
}
// Pay data gas
dataPrice
:=
big
.
NewInt
(
int64
(
len
(
tx
.
D
ata
)))
dataPrice
:=
big
.
NewInt
(
int64
(
len
(
self
.
d
ata
)))
dataPrice
.
Mul
(
dataPrice
,
GasData
)
if
err
=
self
.
UseGas
(
dataPrice
);
err
!=
nil
{
return
err
return
}
// If the receiver is nil it's a contract (\0*32).
...
...
@@ -186,75 +181,83 @@ func (self *StateTransition) TransitionState() (err error) {
// Create a new state object for the contract
receiver
=
self
.
MakeStateObject
(
self
.
state
,
tx
)
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
if
err
=
self
.
transferValue
(
sender
,
receiver
);
err
!=
nil
{
return
err
return
}
// Process the init code and create 'valid' contract
if
tx
.
CreatesContract
(
)
{
if
IsContractAddr
(
self
.
receiver
)
{
// Evaluate the initialization script
// and use the return value as the
// script section for the state object.
//script, gas, err = sm.Eval(state, contract.Init(), contract, tx, block)
code
,
err
:=
self
.
Eval
(
receiver
.
Init
(),
receiver
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error during init script run %v"
,
err
)
self
.
data
=
nil
code
,
err
,
deepErr
:=
self
.
Eval
(
receiver
.
Init
(),
receiver
)
if
err
!=
nil
||
deepErr
{
self
.
state
.
ResetStateObject
(
receiver
)
return
fmt
.
Errorf
(
"Error during init script run %v (deepErr = %v)"
,
err
,
deepErr
)
}
receiver
.
script
=
code
}
else
{
if
len
(
receiver
.
Script
())
>
0
{
_
,
err
:=
self
.
Eval
(
receiver
.
Script
(),
receiver
)
var
deepErr
bool
_
,
err
,
deepErr
=
self
.
Eval
(
receiver
.
Script
(),
receiver
)
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
{
if
sender
.
Amount
.
Cmp
(
self
.
tx
.
V
alue
)
<
0
{
return
fmt
.
Errorf
(
"Insufficient funds to transfer value. Req %v, has %v"
,
self
.
tx
.
V
alue
,
sender
.
Amount
)
if
sender
.
Amount
.
Cmp
(
self
.
v
alue
)
<
0
{
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
{
// Subtract the amount from the senders account
sender
.
SubAmount
(
self
.
tx
.
V
alue
)
// Add the amount to receivers account which should conclude this transaction
receiver
.
AddAmount
(
self
.
tx
.
V
alue
)
//if self.v
alue.Cmp(ethutil.Big0) > 0 {
// Subtract the amount from the senders account
sender
.
SubAmount
(
self
.
v
alue
)
// Add the amount to receivers account which should conclude this transaction
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
}
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
(
tx
=
self
.
tx
block
=
self
.
block
initiator
=
self
.
Sender
()
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
{
Origin
:
initiator
.
Address
(),
BlockNumber
:
block
.
BlockInfo
()
.
Number
,
Block
:
block
,
BlockNumber
:
block
.
Number
,
PrevHash
:
block
.
PrevHash
,
Coinbase
:
block
.
Coinbase
,
Time
:
block
.
Time
,
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
}
ethchain/transaction.go
View file @
3f1f8438
...
...
@@ -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
}
func
IsContractAddr
(
addr
[]
byte
)
bool
{
return
bytes
.
Compare
(
addr
,
ContractAddr
)
==
0
}
type
Transaction
struct
{
Nonce
uint64
Recipient
[]
byte
...
...
@@ -65,7 +69,7 @@ func (tx *Transaction) CreatesContract() bool {
return
tx
.
contractCreation
}
/* Depr
i
cated */
/* Depr
e
cated */
func
(
tx
*
Transaction
)
IsContract
()
bool
{
return
tx
.
CreatesContract
()
}
...
...
@@ -149,7 +153,7 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx
.
r
=
decoder
.
Get
(
7
)
.
Bytes
()
tx
.
s
=
decoder
.
Get
(
8
)
.
Bytes
()
if
bytes
.
Compare
(
tx
.
Recipient
,
ContractAddr
)
==
0
{
if
IsContractAddr
(
tx
.
Recipient
)
{
tx
.
contractCreation
=
true
}
}
...
...
ethchain/types.go
View file @
3f1f8438
...
...
@@ -166,6 +166,7 @@ var opCodeToString = map[OpCode]string{
GASLIMIT
:
"GASLIMIT"
,
// 0x50 range - 'storage' and execution
POP
:
"POP"
,
DUP
:
"DUP"
,
SWAP
:
"SWAP"
,
MLOAD
:
"MLOAD"
,
...
...
@@ -226,7 +227,7 @@ var opCodeToString = map[OpCode]string{
func
(
o
OpCode
)
String
()
string
{
str
:=
opCodeToString
[
o
]
if
len
(
str
)
==
0
{
return
fmt
.
Sprintf
(
"Missing opcode
%#
x"
,
int
(
o
))
return
fmt
.
Sprintf
(
"Missing opcode
0x%
x"
,
int
(
o
))
}
return
str
...
...
ethchain/vm.go
View file @
3f1f8438
package
ethchain
import
(
_
"bytes"
"fmt"
"github.com/ethereum/eth-go/ethutil"
_
"github.com/obscuren/secp256k1-go"
"math"
_
"math"
"math/big"
)
...
...
@@ -45,11 +42,18 @@ type Vm struct {
state
*
State
stateManager
*
StateManager
Verbose
bool
logStr
string
err
error
}
type
RuntimeVars
struct
{
Origin
[]
byte
BlockNumber
uint64
Block
*
Block
BlockNumber
*
big
.
Int
PrevHash
[]
byte
Coinbase
[]
byte
Time
int64
...
...
@@ -58,6 +62,23 @@ type RuntimeVars struct {
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
{
return
&
Vm
{
vars
:
vars
,
state
:
state
,
stateManager
:
stateManager
}
}
...
...
@@ -69,14 +90,14 @@ var isRequireError = false
func
(
vm
*
Vm
)
RunClosure
(
closure
*
Closure
,
hook
DebugHook
)
(
ret
[]
byte
,
err
error
)
{
// Recover from any require exception
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
/*&& isRequireError*/
{
if
r
:=
recover
();
r
!=
nil
{
ret
=
closure
.
Return
(
nil
)
err
=
fmt
.
Errorf
(
"%v"
,
r
)
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
mem
:=
&
Memory
{}
...
...
@@ -95,10 +116,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
step
:=
0
prevStep
:=
0
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
}
for
{
prevStep
=
step
// The base for all big integer arithmetic
...
...
@@ -109,13 +126,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
val
:=
closure
.
Get
(
pc
)
// Get the opcode (it must be an opcode!)
op
:=
OpCode
(
val
.
Uint
())
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"%-3d %-4s"
,
pc
,
op
.
String
())
}
gas
:=
new
(
big
.
Int
)
addStepGasUsage
:=
func
(
amount
*
big
.
Int
)
{
gas
.
Add
(
gas
,
amount
)
if
amount
.
Cmp
(
ethutil
.
Big0
)
>=
0
{
gas
.
Add
(
gas
,
amount
)
}
}
addStepGasUsage
(
GasStep
)
...
...
@@ -123,7 +139,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
var
newMemSize
uint64
=
0
switch
op
{
case
STOP
:
gas
.
Set
(
ethutil
.
Big0
)
case
SUICIDE
:
gas
.
Set
(
ethutil
.
Big0
)
case
SLOAD
:
gas
.
Set
(
GasSLoad
)
case
SSTORE
:
...
...
@@ -169,7 +187,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
CALL
:
require
(
7
)
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
()
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
}
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
)
switch
op
{
...
...
@@ -204,29 +227,41 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
ADD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
vm
.
Printf
(
" %v + %v"
,
y
,
x
)
base
.
Add
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
SUB
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
vm
.
Printf
(
" %v - %v"
,
y
,
x
)
base
.
Sub
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
MUL
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
vm
.
Printf
(
" %v * %v"
,
y
,
x
)
base
.
Mul
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
DIV
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// floor(x / y)
base
.
Div
(
x
,
y
)
vm
.
Printf
(
" %v / %v"
,
y
,
x
)
base
.
Div
(
y
,
x
)
vm
.
Printf
(
" = %v"
,
base
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
SDIV
:
...
...
@@ -249,7 +284,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
MOD
:
require
(
2
)
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
)
case
SMOD
:
require
(
2
)
...
...
@@ -271,7 +311,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
EXP
:
require
(
2
)
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
)
case
NEG
:
...
...
@@ -280,7 +325,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack
.
Push
(
base
)
case
LT
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
y
,
x
:=
stack
.
Popn
()
vm
.
Printf
(
" %v < %v"
,
x
,
y
)
// x < y
if
x
.
Cmp
(
y
)
<
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
...
...
@@ -289,7 +335,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
case
GT
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
y
,
x
:=
stack
.
Popn
()
vm
.
Printf
(
" %v > %v"
,
x
,
y
)
// x > y
if
x
.
Cmp
(
y
)
>
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
...
...
@@ -299,6 +347,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
EQ
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
vm
.
Printf
(
" %v == %v"
,
y
,
x
)
// x == y
if
x
.
Cmp
(
y
)
==
0
{
stack
.
Push
(
ethutil
.
BigTrue
)
...
...
@@ -318,24 +368,21 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
AND
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
&&
(
y
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
{
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
vm
.
Printf
(
" %v & %v"
,
y
,
x
)
stack
.
Push
(
base
.
And
(
y
,
x
))
case
OR
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
||
(
y
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
{
stack
.
Push
(
ethutil
.
BigTrue
)
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
vm
.
Printf
(
" %v | %v"
,
y
,
x
)
stack
.
Push
(
base
.
Or
(
y
,
x
))
case
XOR
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
stack
.
Push
(
base
.
Xor
(
x
,
y
))
vm
.
Printf
(
" %v ^ %v"
,
y
,
x
)
stack
.
Push
(
base
.
Xor
(
y
,
x
))
case
BYTE
:
require
(
2
)
val
,
th
:=
stack
.
Popn
()
...
...
@@ -360,25 +407,35 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
ORIGIN
:
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
Origin
))
case
CALLER
:
stack
.
Push
(
ethutil
.
BigD
(
closure
.
caller
.
Address
()))
caller
:=
closure
.
caller
.
Address
()
stack
.
Push
(
ethutil
.
BigD
(
caller
))
vm
.
Printf
(
" => %x"
,
caller
)
case
CALLVALUE
:
stack
.
Push
(
vm
.
vars
.
Value
)
case
CALLDATALOAD
:
require
(
1
)
offset
:=
stack
.
Pop
()
.
Int64
()
var
data
[]
byte
if
len
(
closure
.
Args
)
>=
int
(
offset
+
32
)
{
data
=
closure
.
Args
[
offset
:
offset
+
32
]
}
else
{
data
=
[]
byte
{
0
}
data
:=
make
([]
byte
,
32
)
if
len
(
closure
.
Args
)
>=
int
(
offset
)
{
l
:=
int64
(
math
.
Min
(
float64
(
offset
+
32
),
float64
(
len
(
closure
.
Args
))))
copy
(
data
,
closure
.
Args
[
offset
:
l
])
}
vm
.
Printf
(
" => 0x%x"
,
data
)
stack
.
Push
(
ethutil
.
BigD
(
data
))
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
:
panic
(
"not implemented"
)
case
CODESIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Script
))))
case
CODECOPY
:
var
(
size
=
int64
(
len
(
closure
.
Script
))
...
...
@@ -408,7 +465,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case
TIMESTAMP
:
stack
.
Push
(
big
.
NewInt
(
vm
.
vars
.
Time
))
case
NUMBER
:
stack
.
Push
(
big
.
NewInt
(
int64
(
vm
.
vars
.
BlockNumber
))
)
stack
.
Push
(
vm
.
vars
.
BlockNumber
)
case
DIFFICULTY
:
stack
.
Push
(
vm
.
vars
.
Diff
)
case
GASLIMIT
:
...
...
@@ -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
)))
step
+=
int
(
op
)
-
int
(
PUSH1
)
+
1
vm
.
Printf
(
" => 0x%x"
,
data
.
Bytes
())
case
POP
:
require
(
1
)
stack
.
Pop
()
case
DUP
:
require
(
1
)
stack
.
Push
(
stack
.
Peek
())
vm
.
Printf
(
" => 0x%x"
,
stack
.
Peek
()
.
Bytes
())
case
SWAP
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
...
...
@@ -446,38 +507,53 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Pop value of the stack
val
,
mStart
:=
stack
.
Popn
()
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
vm
.
Printf
(
" => 0x%x"
,
val
)
case
MSTORE8
:
require
(
2
)
val
,
mStart
:=
stack
.
Popn
()
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
vm
.
Printf
(
" => 0x%x"
,
val
)
case
SLOAD
:
require
(
1
)
loc
:=
stack
.
Pop
()
val
:=
closure
.
GetMem
(
loc
)
//fmt.Println("get", val.BigInt(), "@", loc)
stack
.
Push
(
val
.
BigInt
())
vm
.
Printf
(
" {} 0x%x"
,
val
)
case
SSTORE
:
require
(
2
)
val
,
loc
:=
stack
.
Popn
()
//fmt.Println("storing", val, "@", loc)
closure
.
SetStorage
(
loc
,
ethutil
.
NewValue
(
val
))
// FIXME This should be handled in the Trie it self
if
val
.
Cmp
(
big
.
NewInt
(
0
))
!=
0
{
closure
.
SetStorage
(
loc
,
ethutil
.
NewValue
(
val
))
}
// Add the change to manifest
vm
.
state
.
manifest
.
AddStorageChange
(
closure
.
Object
(),
loc
.
Bytes
(),
val
)
vm
.
Printf
(
" {0x%x} 0x%x"
,
loc
,
val
)
case
JUMP
:
require
(
1
)
pc
=
stack
.
Pop
()
// 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
case
JUMPI
:
require
(
2
)
cond
,
pos
:=
stack
.
Popn
()
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
=
=
0
{
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
>
=
0
{
pc
=
pos
//pc.Sub(pc, ethutil.Big1)
vm
.
Printf
(
" ~> %v (t)"
,
pc
)
.
Endl
()
continue
}
else
{
vm
.
Printf
(
" (f)"
)
}
case
PC
:
stack
.
Push
(
pc
)
...
...
@@ -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
// revert back to it later.
snapshot
:=
vm
.
state
.
Snapshot
()
snapshot
:=
vm
.
state
.
Copy
()
// Generate a new address
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
stack
.
Push
(
ethutil
.
BigFalse
)
// Revert the state as it was before.
vm
.
state
.
Rever
t
(
snapshot
)
vm
.
state
.
Se
t
(
snapshot
)
}
else
{
stack
.
Push
(
ethutil
.
BigD
(
addr
))
vm
.
state
.
UpdateStateObject
(
contract
)
}
case
CALL
:
// TODO RE-WRITE
require
(
7
)
// Closure addr
addr
:=
stack
.
Pop
()
vm
.
Endl
()
gas
:=
stack
.
Pop
()
// Pop gas and value of the stack.
gas
,
value
:=
stack
.
Popn
()
value
,
addr
:=
stack
.
Popn
()
// Pop input size and offset
inSize
,
inOffset
:=
stack
.
Popn
()
// Pop return size and offset
...
...
@@ -543,39 +618,34 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Get the arguments from the memory
args
:=
mem
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
snapshot
:=
vm
.
state
.
Snapshot
()
closure
.
object
.
Nonce
+=
1
if
closure
.
object
.
Amount
.
Cmp
(
value
)
<
0
{
ethutil
.
Config
.
Log
.
Debugf
(
"Insufficient funds to transfer value. Req %v, has %v"
,
value
,
closure
.
object
.
Amount
)
stack
.
Push
(
ethutil
.
BigFalse
)
}
else
{
// Fetch the contract which will serve as the closure body
contract
:=
vm
.
state
.
GetStateObject
(
addr
.
Bytes
())
if
contract
!=
nil
{
// Add the value to the state object
contract
.
AddAmount
(
value
)
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
contract
,
contract
.
script
,
vm
.
state
,
gas
,
closure
.
Price
)
// Executer the closure and get the return value (if any)
ret
,
_
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
if
err
!=
nil
{
stack
.
Push
(
ethutil
.
BigFalse
)
// Reset the changes applied this object
vm
.
state
.
Revert
(
snapshot
)
}
else
{
stack
.
Push
(
ethutil
.
BigTrue
)
vm
.
state
.
UpdateStateObject
(
contract
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
}
}
else
{
ethutil
.
Config
.
Log
.
Debugf
(
"Contract %x not found
\n
"
,
addr
.
Bytes
())
snapshot
:=
vm
.
state
.
Copy
()
stateObject
:=
vm
.
state
.
GetOrNewStateObject
(
addr
.
Bytes
())
closure
.
object
.
SubAmount
(
value
)
// Add the value to the state object
stateObject
.
AddAmount
(
value
)
// Create a new callable closure
closure
:=
NewClosure
(
closure
,
stateObject
,
stateObject
.
script
,
vm
.
state
,
gas
,
closure
.
Price
)
// Executer the closure and get the return value (if any)
ret
,
_
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
if
err
!=
nil
{
stack
.
Push
(
ethutil
.
BigFalse
)
ethutil
.
Config
.
Log
.
Debugf
(
"Closure execution failed. %v
\n
"
,
err
)
vm
.
err
=
err
vm
.
state
.
Set
(
snapshot
)
}
else
{
stack
.
Push
(
ethutil
.
BigTrue
)
mem
.
Set
(
retOffset
.
Int64
(),
retSize
.
Int64
(),
ret
)
}
}
case
RETURN
:
...
...
@@ -583,18 +653,24 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
size
,
offset
:=
stack
.
Popn
()
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
vm
.
Printf
(
" => (%d) 0x%x"
,
len
(
ret
),
ret
)
.
Endl
()
return
closure
.
Return
(
ret
),
nil
case
SUICIDE
:
require
(
1
)
receiver
:=
vm
.
state
.
GetAccount
(
stack
.
Pop
()
.
Bytes
())
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
case
STOP
:
// Stop the closure
vm
.
Printf
(
" (g) %v"
,
closure
.
Gas
)
.
Endl
()
return
closure
.
Return
(
nil
),
nil
default
:
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
pc
.
Add
(
pc
,
ethutil
.
Big1
)
vm
.
Endl
()
if
hook
!=
nil
{
if
!
hook
(
prevStep
,
op
,
mem
,
stack
,
closure
.
Object
())
{
return
nil
,
nil
...
...
ethereum.go
View file @
3f1f8438
...
...
@@ -149,7 +149,9 @@ func (s *Ethereum) IsUpToDate() bool {
})
return
upToDate
}
func
(
s
*
Ethereum
)
PushPeer
(
peer
*
Peer
)
{
s
.
peers
.
PushBack
(
peer
)
}
func
(
s
*
Ethereum
)
IsListening
()
bool
{
return
s
.
listening
}
...
...
@@ -159,14 +161,11 @@ func (s *Ethereum) AddPeer(conn net.Conn) {
if
peer
!=
nil
{
if
s
.
peers
.
Len
()
<
s
.
MaxPeers
{
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
}
else
{
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
)
{
...
...
@@ -233,12 +232,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error {
return
nil
}
peer
:=
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
)
NewOutboundPeer
(
addr
,
s
,
s
.
serverCaps
)
}
return
nil
...
...
ethminer/miner.go
View file @
3f1f8438
...
...
@@ -154,6 +154,8 @@ func (self *Miner) mineNewBlock() {
// Accumulate the rewards included for this 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"
)
// Find a valid nonce
...
...
ethpub/pub.go
View file @
3f1f8438
...
...
@@ -170,11 +170,6 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, sc
tx
=
ethchain
.
NewContractCreationTx
(
value
,
gas
,
gasPrice
,
script
)
}
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
)
{
slice
:=
strings
.
Split
(
s
,
"
\n
"
)
for
_
,
dataItem
:=
range
slice
{
...
...
ethpub/types.go
View file @
3f1f8438
...
...
@@ -104,16 +104,17 @@ type PTx struct {
func
NewPTx
(
tx
*
ethchain
.
Transaction
)
*
PTx
{
hash
:=
hex
.
EncodeToString
(
tx
.
Hash
())
receiver
:=
hex
.
EncodeToString
(
tx
.
Recipient
)
if
receiver
==
""
{
if
receiver
==
"0000000000000000000000000000000000000000"
{
receiver
=
hex
.
EncodeToString
(
tx
.
CreationAddress
())
}
sender
:=
hex
.
EncodeToString
(
tx
.
Sender
())
createsContract
:=
tx
.
CreatesContract
()
data
:=
string
(
tx
.
Data
)
var
data
string
if
tx
.
CreatesContract
()
{
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
)}
...
...
ethutil/bytes.go
View file @
3f1f8438
...
...
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"fmt"
"math/big"
"strings"
)
// Number to bytes
...
...
@@ -91,7 +92,7 @@ func IsHex(str string) bool {
}
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
:
])
}
else
{
ret
=
cb
(
str
)
...
...
ethutil/config.go
View file @
3f1f8438
...
...
@@ -75,7 +75,7 @@ func ReadConfig(base string, logTypes LoggerType, g *globalconf.GlobalConf, id s
if
Config
==
nil
{
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
.
Identifier
=
id
Config
.
Log
=
NewLogger
(
logTypes
,
LogLevelDebug
)
...
...
ethutil/trie_test.go
View file @
3f1f8438
...
...
@@ -173,12 +173,21 @@ func TestTriePurge(t *testing.T) {
func
TestTrieIt
(
t
*
testing
.
T
)
{
_
,
trie
:=
New
()
trie
.
Update
(
"c"
,
LONG_WORD
)
trie
.
Update
(
"ca"
,
LONG_WORD
)
trie
.
Update
(
"cat"
,
LONG_WORD
)
it
:=
trie
.
NewIterator
()
it
.
Each
(
func
(
key
string
,
node
*
Value
)
{
fmt
.
Println
(
key
,
":"
,
node
.
Str
())
})
data
:=
[][]
string
{
{
"do"
,
"verb"
},
{
"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 {
func
(
val
*
Value
)
Bytes
()
[]
byte
{
if
a
,
ok
:=
val
.
Val
.
([]
byte
);
ok
{
return
a
}
else
if
s
,
ok
:=
val
.
Val
.
(
byte
);
ok
{
return
[]
byte
{
s
}
}
return
[]
byte
{}
...
...
peer.go
View file @
3f1f8438
...
...
@@ -2,6 +2,7 @@ package eth
import
(
"bytes"
"container/list"
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
...
...
@@ -124,6 +125,7 @@ type Peer struct {
port
uint16
caps
Caps
// This peer's public key
pubkey
[]
byte
// Indicated whether the node is catching up or not
...
...
@@ -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
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
{
ethutil
.
Config
.
Log
.
Debugln
(
"Connection to peer failed"
,
err
)
...
...
@@ -614,6 +616,30 @@ func (p *Peer) pushPeers() {
func
(
p
*
Peer
)
handleHandshake
(
msg
*
ethwire
.
Msg
)
{
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
{
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid peer version. Require protocol: %d. Received: %d
\n
"
,
ProtocolVersion
,
c
.
Get
(
0
)
.
Uint
())
p
.
Stop
()
...
...
@@ -625,7 +651,6 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
// If this is an inbound connection send an ack back
if
p
.
inbound
{
p
.
pubkey
=
c
.
Get
(
5
)
.
Bytes
()
p
.
port
=
uint16
(
c
.
Get
(
4
)
.
Uint
())
// Self connect detection
...
...
@@ -647,6 +672,11 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
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
if
!
p
.
ethereum
.
IsUpToDate
()
{
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