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
2cea4106
Commit
2cea4106
authored
Jun 18, 2015
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1282 from obscuren/state-cleanup
core/state: cleanup & optimisations
parents
53a6145a
430bcdb2
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
176 additions
and
197 deletions
+176
-197
types.go
common/types.go
+4
-0
block_processor.go
core/block_processor.go
+65
-74
block_processor_test.go
core/block_processor_test.go
+5
-3
dump.go
core/state/dump.go
+3
-3
state_object.go
core/state/state_object.go
+35
-43
state_test.go
core/state/state_test.go
+10
-13
statedb.go
core/state/statedb.go
+16
-30
state_transition.go
core/state_transition.go
+3
-5
transaction_pool.go
core/transaction_pool.go
+13
-9
vm.go
core/vm/vm.go
+11
-6
block_test_util.go
tests/block_test_util.go
+1
-1
gh_test.go
tests/vm/gh_test.go
+5
-5
types.go
xeth/types.go
+4
-4
xeth.go
xeth/xeth.go
+1
-1
No files found.
common/types.go
View file @
2cea4106
...
...
@@ -62,6 +62,10 @@ func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
return
reflect
.
ValueOf
(
h
)
}
func
EmptyHash
(
h
Hash
)
bool
{
return
h
==
Hash
{}
}
/////////// Address
func
BytesToAddress
(
b
[]
byte
)
Address
{
var
a
Address
...
...
core/block_processor.go
View file @
2cea4106
...
...
@@ -185,7 +185,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
state
:=
state
.
New
(
parent
.
Root
(),
sm
.
db
)
// Block validation
if
err
=
sm
.
ValidateHeader
(
block
.
Header
(),
parent
.
Header
(),
false
);
err
!=
nil
{
if
err
=
ValidateHeader
(
sm
.
Pow
,
block
.
Header
(),
parent
.
Header
(),
false
);
err
!=
nil
{
return
}
...
...
@@ -246,12 +246,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return
}
// store the receipts
err
=
putReceipts
(
sm
.
extraDb
,
block
.
Hash
(),
receipts
)
if
err
!=
nil
{
return
nil
,
err
}
// Sync the current block's state to the database
state
.
Sync
()
...
...
@@ -260,76 +254,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
putTx
(
sm
.
extraDb
,
tx
,
block
,
uint64
(
i
))
}
receiptsRlp
:=
receipts
.
RlpEncode
()
/*if len(receipts) > 0 {
glog.V(logger.Info).Infof("Saving %v receipts, rlp len is %v\n", len(receipts), len(receiptsRlp))
}*/
sm
.
extraDb
.
Put
(
append
(
receiptsPre
,
block
.
Hash
()
.
Bytes
()
...
),
receiptsRlp
)
// store the receipts
putReceipts
(
sm
.
extraDb
,
block
.
Hash
(),
receipts
)
return
state
.
Logs
(),
nil
}
// See YP section 4.3.4. "Block Header Validity"
// Validates a block. Returns an error if the block is invalid.
func
(
sm
*
BlockProcessor
)
ValidateHeader
(
block
,
parent
*
types
.
Header
,
checkPow
bool
)
error
{
if
big
.
NewInt
(
int64
(
len
(
block
.
Extra
)))
.
Cmp
(
params
.
MaximumExtraDataSize
)
==
1
{
return
fmt
.
Errorf
(
"Block extra data too long (%d)"
,
len
(
block
.
Extra
))
}
expd
:=
CalcDifficulty
(
block
,
parent
)
if
expd
.
Cmp
(
block
.
Difficulty
)
!=
0
{
return
fmt
.
Errorf
(
"Difficulty check failed for block %v, %v"
,
block
.
Difficulty
,
expd
)
}
a
:=
new
(
big
.
Int
)
.
Sub
(
block
.
GasLimit
,
parent
.
GasLimit
)
a
.
Abs
(
a
)
b
:=
new
(
big
.
Int
)
.
Div
(
parent
.
GasLimit
,
params
.
GasLimitBoundDivisor
)
if
!
(
a
.
Cmp
(
b
)
<
0
)
||
(
block
.
GasLimit
.
Cmp
(
params
.
MinGasLimit
)
==
-
1
)
{
return
fmt
.
Errorf
(
"GasLimit check failed for block %v (%v > %v)"
,
block
.
GasLimit
,
a
,
b
)
}
if
int64
(
block
.
Time
)
>
time
.
Now
()
.
Unix
()
{
return
BlockFutureErr
}
if
new
(
big
.
Int
)
.
Sub
(
block
.
Number
,
parent
.
Number
)
.
Cmp
(
big
.
NewInt
(
1
))
!=
0
{
return
BlockNumberErr
}
if
block
.
Time
<=
parent
.
Time
{
return
BlockEqualTSErr
//ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
}
if
checkPow
{
// Verify the nonce of the block. Return an error if it's not valid
if
!
sm
.
Pow
.
Verify
(
types
.
NewBlockWithHeader
(
block
))
{
return
ValidationError
(
"Block's nonce is invalid (= %x)"
,
block
.
Nonce
)
}
}
return
nil
}
func
AccumulateRewards
(
statedb
*
state
.
StateDB
,
block
*
types
.
Block
)
{
reward
:=
new
(
big
.
Int
)
.
Set
(
BlockReward
)
for
_
,
uncle
:=
range
block
.
Uncles
()
{
num
:=
new
(
big
.
Int
)
.
Add
(
big
.
NewInt
(
8
),
uncle
.
Number
)
num
.
Sub
(
num
,
block
.
Number
())
r
:=
new
(
big
.
Int
)
r
.
Mul
(
BlockReward
,
num
)
r
.
Div
(
r
,
big
.
NewInt
(
8
))
statedb
.
AddBalance
(
uncle
.
Coinbase
,
r
)
reward
.
Add
(
reward
,
new
(
big
.
Int
)
.
Div
(
BlockReward
,
big
.
NewInt
(
32
)))
}
// Get the account associated with the coinbase
statedb
.
AddBalance
(
block
.
Header
()
.
Coinbase
,
reward
)
}
func
(
sm
*
BlockProcessor
)
VerifyUncles
(
statedb
*
state
.
StateDB
,
block
,
parent
*
types
.
Block
)
error
{
ancestors
:=
set
.
New
()
uncles
:=
set
.
New
()
...
...
@@ -367,7 +297,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
return
UncleError
(
"uncle[%d](%x)'s parent is not ancestor (%x)"
,
i
,
hash
[
:
4
],
uncle
.
ParentHash
[
0
:
4
])
}
if
err
:=
sm
.
ValidateHeader
(
uncle
,
ancestorHeaders
[
uncle
.
ParentHash
],
true
);
err
!=
nil
{
if
err
:=
ValidateHeader
(
sm
.
Pow
,
uncle
,
ancestorHeaders
[
uncle
.
ParentHash
],
true
);
err
!=
nil
{
return
ValidationError
(
fmt
.
Sprintf
(
"uncle[%d](%x) header invalid: %v"
,
i
,
hash
[
:
4
],
err
))
}
}
...
...
@@ -404,6 +334,67 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
return
state
.
Logs
(),
nil
}
// See YP section 4.3.4. "Block Header Validity"
// Validates a block. Returns an error if the block is invalid.
func
ValidateHeader
(
pow
pow
.
PoW
,
block
,
parent
*
types
.
Header
,
checkPow
bool
)
error
{
if
big
.
NewInt
(
int64
(
len
(
block
.
Extra
)))
.
Cmp
(
params
.
MaximumExtraDataSize
)
==
1
{
return
fmt
.
Errorf
(
"Block extra data too long (%d)"
,
len
(
block
.
Extra
))
}
expd
:=
CalcDifficulty
(
block
,
parent
)
if
expd
.
Cmp
(
block
.
Difficulty
)
!=
0
{
return
fmt
.
Errorf
(
"Difficulty check failed for block %v, %v"
,
block
.
Difficulty
,
expd
)
}
a
:=
new
(
big
.
Int
)
.
Sub
(
block
.
GasLimit
,
parent
.
GasLimit
)
a
.
Abs
(
a
)
b
:=
new
(
big
.
Int
)
.
Div
(
parent
.
GasLimit
,
params
.
GasLimitBoundDivisor
)
if
!
(
a
.
Cmp
(
b
)
<
0
)
||
(
block
.
GasLimit
.
Cmp
(
params
.
MinGasLimit
)
==
-
1
)
{
return
fmt
.
Errorf
(
"GasLimit check failed for block %v (%v > %v)"
,
block
.
GasLimit
,
a
,
b
)
}
if
int64
(
block
.
Time
)
>
time
.
Now
()
.
Unix
()
{
return
BlockFutureErr
}
if
new
(
big
.
Int
)
.
Sub
(
block
.
Number
,
parent
.
Number
)
.
Cmp
(
big
.
NewInt
(
1
))
!=
0
{
return
BlockNumberErr
}
if
block
.
Time
<=
parent
.
Time
{
return
BlockEqualTSErr
//ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
}
if
checkPow
{
// Verify the nonce of the block. Return an error if it's not valid
if
!
pow
.
Verify
(
types
.
NewBlockWithHeader
(
block
))
{
return
ValidationError
(
"Block's nonce is invalid (= %x)"
,
block
.
Nonce
)
}
}
return
nil
}
func
AccumulateRewards
(
statedb
*
state
.
StateDB
,
block
*
types
.
Block
)
{
reward
:=
new
(
big
.
Int
)
.
Set
(
BlockReward
)
for
_
,
uncle
:=
range
block
.
Uncles
()
{
num
:=
new
(
big
.
Int
)
.
Add
(
big
.
NewInt
(
8
),
uncle
.
Number
)
num
.
Sub
(
num
,
block
.
Number
())
r
:=
new
(
big
.
Int
)
r
.
Mul
(
BlockReward
,
num
)
r
.
Div
(
r
,
big
.
NewInt
(
8
))
statedb
.
AddBalance
(
uncle
.
Coinbase
,
r
)
reward
.
Add
(
reward
,
new
(
big
.
Int
)
.
Div
(
BlockReward
,
big
.
NewInt
(
32
)))
}
// Get the account associated with the coinbase
statedb
.
AddBalance
(
block
.
Header
()
.
Coinbase
,
reward
)
}
func
getBlockReceipts
(
db
common
.
Database
,
bhash
common
.
Hash
)
(
receipts
types
.
Receipts
,
err
error
)
{
var
rdata
[]
byte
rdata
,
err
=
db
.
Get
(
append
(
receiptsPre
,
bhash
[
:
]
...
))
...
...
core/block_processor_test.go
View file @
2cea4106
...
...
@@ -26,18 +26,20 @@ func proc() (*BlockProcessor, *ChainManager) {
}
func
TestNumber
(
t
*
testing
.
T
)
{
bp
,
chain
:=
proc
()
_
,
chain
:=
proc
()
block1
:=
chain
.
NewBlock
(
common
.
Address
{})
block1
.
Header
()
.
Number
=
big
.
NewInt
(
3
)
block1
.
Header
()
.
Time
--
err
:=
bp
.
ValidateHeader
(
block1
.
Header
(),
chain
.
Genesis
()
.
Header
(),
false
)
pow
:=
ezp
.
New
()
err
:=
ValidateHeader
(
pow
,
block1
.
Header
(),
chain
.
Genesis
()
.
Header
(),
false
)
if
err
!=
BlockNumberErr
{
t
.
Errorf
(
"expected block number error %v"
,
err
)
}
block1
=
chain
.
NewBlock
(
common
.
Address
{})
err
=
bp
.
ValidateHeader
(
block1
.
Header
(),
chain
.
Genesis
()
.
Header
(),
false
)
err
=
ValidateHeader
(
pow
,
block1
.
Header
(),
chain
.
Genesis
()
.
Header
(),
false
)
if
err
==
BlockNumberErr
{
t
.
Errorf
(
"didn't expect block number error"
)
}
...
...
core/state/dump.go
View file @
2cea4106
...
...
@@ -34,7 +34,7 @@ func (self *StateDB) RawDump() World {
account
:=
Account
{
Balance
:
stateObject
.
balance
.
String
(),
Nonce
:
stateObject
.
nonce
,
Root
:
common
.
Bytes2Hex
(
stateObject
.
Root
()),
CodeHash
:
common
.
Bytes2Hex
(
stateObject
.
codeHash
)}
account
.
Storage
=
make
(
map
[
string
]
string
)
storageIt
:=
stateObject
.
State
.
trie
.
Iterator
()
storageIt
:=
stateObject
.
trie
.
Iterator
()
for
storageIt
.
Next
()
{
account
.
Storage
[
common
.
Bytes2Hex
(
self
.
trie
.
GetKey
(
storageIt
.
Key
))]
=
common
.
Bytes2Hex
(
storageIt
.
Value
)
}
...
...
@@ -54,8 +54,8 @@ func (self *StateDB) Dump() []byte {
// Debug stuff
func
(
self
*
StateObject
)
CreateOutputForDiff
()
{
fmt
.
Printf
(
"%x %x %x %x
\n
"
,
self
.
Address
(),
self
.
State
.
Root
(),
self
.
balance
.
Bytes
(),
self
.
nonce
)
it
:=
self
.
State
.
trie
.
Iterator
()
fmt
.
Printf
(
"%x %x %x %x
\n
"
,
self
.
Address
(),
self
.
Root
(),
self
.
balance
.
Bytes
(),
self
.
nonce
)
it
:=
self
.
trie
.
Iterator
()
for
it
.
Next
()
{
fmt
.
Printf
(
"%x %x
\n
"
,
it
.
Key
,
it
.
Value
)
}
...
...
core/state/state_object.go
View file @
2cea4106
...
...
@@ -19,11 +19,11 @@ func (self Code) String() string {
return
string
(
self
)
//strings.Join(Disassemble(self), " ")
}
type
Storage
map
[
string
]
*
common
.
Value
type
Storage
map
[
string
]
common
.
Hash
func
(
self
Storage
)
String
()
(
str
string
)
{
for
key
,
value
:=
range
self
{
str
+=
fmt
.
Sprintf
(
"%X : %X
\n
"
,
key
,
value
.
Bytes
()
)
str
+=
fmt
.
Sprintf
(
"%X : %X
\n
"
,
key
,
value
)
}
return
...
...
@@ -32,7 +32,6 @@ func (self Storage) String() (str string) {
func
(
self
Storage
)
Copy
()
Storage
{
cpy
:=
make
(
Storage
)
for
key
,
value
:=
range
self
{
// XXX Do we need a 'value' copy or is this sufficient?
cpy
[
key
]
=
value
}
...
...
@@ -41,9 +40,8 @@ func (self Storage) Copy() Storage {
type
StateObject
struct
{
// State database for storing state changes
db
common
.
Database
// The state object
State
*
StateDB
db
common
.
Database
trie
*
trie
.
SecureTrie
// Address belonging to this account
address
common
.
Address
...
...
@@ -76,7 +74,6 @@ type StateObject struct {
func
(
self
*
StateObject
)
Reset
()
{
self
.
storage
=
make
(
Storage
)
self
.
State
.
Reset
()
}
func
NewStateObject
(
address
common
.
Address
,
db
common
.
Database
)
*
StateObject
{
...
...
@@ -84,7 +81,7 @@ func NewStateObject(address common.Address, db common.Database) *StateObject {
//address := common.ToAddress(addr)
object
:=
&
StateObject
{
db
:
db
,
address
:
address
,
balance
:
new
(
big
.
Int
),
gasPool
:
new
(
big
.
Int
),
dirty
:
true
}
object
.
State
=
New
(
common
.
Hash
{},
db
)
//New(trie.New(common.Config.Db, "")
)
object
.
trie
=
trie
.
NewSecure
((
common
.
Hash
{})
.
Bytes
(),
db
)
object
.
storage
=
make
(
Storage
)
object
.
gasPool
=
new
(
big
.
Int
)
object
.
prepaid
=
new
(
big
.
Int
)
...
...
@@ -111,8 +108,8 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data
object
.
nonce
=
extobject
.
Nonce
object
.
balance
=
extobject
.
Balance
object
.
codeHash
=
extobject
.
CodeHash
object
.
State
=
New
(
extobject
.
Root
,
db
)
object
.
storage
=
make
(
map
[
string
]
*
common
.
Value
)
object
.
trie
=
trie
.
NewSecure
(
extobject
.
Root
[
:
]
,
db
)
object
.
storage
=
make
(
map
[
string
]
common
.
Hash
)
object
.
gasPool
=
new
(
big
.
Int
)
object
.
prepaid
=
new
(
big
.
Int
)
object
.
code
,
_
=
db
.
Get
(
extobject
.
CodeHash
)
...
...
@@ -129,35 +126,31 @@ func (self *StateObject) MarkForDeletion() {
}
}
func
(
c
*
StateObject
)
getAddr
(
addr
common
.
Hash
)
*
common
.
Value
{
return
common
.
NewValueFromBytes
([]
byte
(
c
.
State
.
trie
.
Get
(
addr
[
:
])))
func
(
c
*
StateObject
)
getAddr
(
addr
common
.
Hash
)
common
.
Hash
{
var
ret
[]
byte
rlp
.
DecodeBytes
(
c
.
trie
.
Get
(
addr
[
:
]),
&
ret
)
return
common
.
BytesToHash
(
ret
)
}
func
(
c
*
StateObject
)
setAddr
(
addr
[]
byte
,
value
interface
{})
{
c
.
State
.
trie
.
Update
(
addr
,
common
.
Encode
(
value
))
}
func
(
self
*
StateObject
)
GetStorage
(
key
*
big
.
Int
)
*
common
.
Value
{
fmt
.
Printf
(
"%v: get %v %v"
,
self
.
address
.
Hex
(),
key
)
return
self
.
GetState
(
common
.
BytesToHash
(
key
.
Bytes
()))
}
func
(
self
*
StateObject
)
SetStorage
(
key
*
big
.
Int
,
value
*
common
.
Value
)
{
fmt
.
Printf
(
"%v: set %v -> %v"
,
self
.
address
.
Hex
(),
key
,
value
)
self
.
SetState
(
common
.
BytesToHash
(
key
.
Bytes
()),
value
)
func
(
c
*
StateObject
)
setAddr
(
addr
[]
byte
,
value
common
.
Hash
)
{
v
,
err
:=
rlp
.
EncodeToBytes
(
bytes
.
TrimLeft
(
value
[
:
],
"
\x00
"
))
if
err
!=
nil
{
// if RLPing failed we better panic and not fail silently. This would be considered a consensus issue
panic
(
err
)
}
c
.
trie
.
Update
(
addr
,
v
)
}
func
(
self
*
StateObject
)
Storage
()
Storage
{
return
self
.
storage
}
func
(
self
*
StateObject
)
GetState
(
key
common
.
Hash
)
*
common
.
Value
{
func
(
self
*
StateObject
)
GetState
(
key
common
.
Hash
)
common
.
Hash
{
strkey
:=
key
.
Str
()
value
:=
self
.
storage
[
strkey
]
if
value
==
nil
{
value
,
exists
:=
self
.
storage
[
strkey
]
if
!
exists
{
value
=
self
.
getAddr
(
key
)
if
!
value
.
IsNil
()
{
if
(
value
!=
common
.
Hash
{})
{
self
.
storage
[
strkey
]
=
value
}
}
...
...
@@ -165,15 +158,16 @@ func (self *StateObject) GetState(key common.Hash) *common.Value {
return
value
}
func
(
self
*
StateObject
)
SetState
(
k
common
.
Hash
,
value
*
common
.
Value
)
{
self
.
storage
[
k
.
Str
()]
=
value
.
Copy
()
func
(
self
*
StateObject
)
SetState
(
k
,
value
common
.
Hash
)
{
self
.
storage
[
k
.
Str
()]
=
value
self
.
dirty
=
true
}
func
(
self
*
StateObject
)
Sync
()
{
// Update updates the current cached storage to the trie
func
(
self
*
StateObject
)
Update
()
{
for
key
,
value
:=
range
self
.
storage
{
if
value
.
Len
()
==
0
{
self
.
State
.
trie
.
Delete
([]
byte
(
key
))
if
(
value
==
common
.
Hash
{})
{
self
.
trie
.
Delete
([]
byte
(
key
))
continue
}
...
...
@@ -266,9 +260,7 @@ func (self *StateObject) Copy() *StateObject {
stateObject
.
balance
.
Set
(
self
.
balance
)
stateObject
.
codeHash
=
common
.
CopyBytes
(
self
.
codeHash
)
stateObject
.
nonce
=
self
.
nonce
if
self
.
State
!=
nil
{
stateObject
.
State
=
self
.
State
.
Copy
()
}
stateObject
.
trie
=
self
.
trie
stateObject
.
code
=
common
.
CopyBytes
(
self
.
code
)
stateObject
.
initCode
=
common
.
CopyBytes
(
self
.
initCode
)
stateObject
.
storage
=
self
.
storage
.
Copy
()
...
...
@@ -306,11 +298,11 @@ func (c *StateObject) Init() Code {
}
func
(
self
*
StateObject
)
Trie
()
*
trie
.
SecureTrie
{
return
self
.
State
.
trie
return
self
.
trie
}
func
(
self
*
StateObject
)
Root
()
[]
byte
{
return
self
.
Trie
()
.
Root
()
return
self
.
trie
.
Root
()
}
func
(
self
*
StateObject
)
Code
()
[]
byte
{
...
...
@@ -342,10 +334,10 @@ func (self *StateObject) EachStorage(cb func(key, value []byte)) {
cb
([]
byte
(
h
),
v
.
Bytes
())
}
it
:=
self
.
State
.
trie
.
Iterator
()
it
:=
self
.
trie
.
Iterator
()
for
it
.
Next
()
{
// ignore cached values
key
:=
self
.
State
.
trie
.
GetKey
(
it
.
Key
)
key
:=
self
.
trie
.
GetKey
(
it
.
Key
)
if
_
,
ok
:=
self
.
storage
[
string
(
key
)];
!
ok
{
cb
(
key
,
it
.
Value
)
}
...
...
@@ -369,8 +361,8 @@ func (c *StateObject) RlpDecode(data []byte) {
decoder
:=
common
.
NewValueFromBytes
(
data
)
c
.
nonce
=
decoder
.
Get
(
0
)
.
Uint
()
c
.
balance
=
decoder
.
Get
(
1
)
.
BigInt
()
c
.
State
=
New
(
common
.
BytesToHash
(
decoder
.
Get
(
2
)
.
Bytes
()),
c
.
db
)
//New(trie.New(common.Config.Db, decoder.Get(2).Interface())
)
c
.
storage
=
make
(
map
[
string
]
*
common
.
Value
)
c
.
trie
=
trie
.
NewSecure
(
decoder
.
Get
(
2
)
.
Bytes
(),
c
.
db
)
c
.
storage
=
make
(
map
[
string
]
common
.
Hash
)
c
.
gasPool
=
new
(
big
.
Int
)
c
.
codeHash
=
decoder
.
Get
(
3
)
.
Bytes
()
...
...
core/state/state_test.go
View file @
2cea4106
...
...
@@ -70,37 +70,34 @@ func TestNull(t *testing.T) {
address
:=
common
.
HexToAddress
(
"0x823140710bf13990e4500136726d8b55"
)
state
.
CreateAccount
(
address
)
//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
va
lue
:=
make
([]
byte
,
16
)
va
r
value
common
.
Hash
state
.
SetState
(
address
,
common
.
Hash
{},
value
)
state
.
Update
()
state
.
Sync
()
value
=
state
.
GetState
(
address
,
common
.
Hash
{})
if
!
common
.
EmptyHash
(
value
)
{
t
.
Errorf
(
"expected empty hash. got %x"
,
value
)
}
}
func
(
s
*
StateSuite
)
TestSnapshot
(
c
*
checker
.
C
)
{
stateobjaddr
:=
toAddr
([]
byte
(
"aa"
))
storageaddr
:=
common
.
Big
(
"0"
)
data1
:=
common
.
NewValue
(
42
)
data2
:=
common
.
NewValue
(
43
)
var
storageaddr
common
.
Hash
data1
:=
common
.
BytesToHash
([]
byte
{
42
}
)
data2
:=
common
.
BytesToHash
([]
byte
{
43
}
)
// get state object
stateObject
:=
s
.
state
.
GetOrNewStateObject
(
stateobjaddr
)
// set inital state object value
s
tateObject
.
SetStorage
(
storageaddr
,
data1
)
s
.
state
.
SetState
(
stateobjaddr
,
storageaddr
,
data1
)
// get snapshot of current state
snapshot
:=
s
.
state
.
Copy
()
// get state object. is this strictly necessary?
stateObject
=
s
.
state
.
GetStateObject
(
stateobjaddr
)
// set new state object value
s
tateObject
.
SetStorage
(
storageaddr
,
data2
)
s
.
state
.
SetState
(
stateobjaddr
,
storageaddr
,
data2
)
// restore snapshot
s
.
state
.
Set
(
snapshot
)
// get state object
stateObject
=
s
.
state
.
GetStateObject
(
stateobjaddr
)
// get state storage value
res
:=
s
tateObject
.
GetStorage
(
storageaddr
)
res
:=
s
.
state
.
GetState
(
stateobjaddr
,
storageaddr
)
c
.
Assert
(
data1
,
checker
.
DeepEquals
,
res
)
}
core/state/statedb.go
View file @
2cea4106
...
...
@@ -21,7 +21,7 @@ type StateDB struct {
stateObjects
map
[
string
]
*
StateObject
refund
map
[
string
]
*
big
.
Int
refund
*
big
.
Int
thash
,
bhash
common
.
Hash
txIndex
int
...
...
@@ -31,7 +31,7 @@ type StateDB struct {
// Create a new state from a given trie
func
New
(
root
common
.
Hash
,
db
common
.
Database
)
*
StateDB
{
trie
:=
trie
.
NewSecure
(
root
[
:
],
db
)
return
&
StateDB
{
db
:
db
,
trie
:
trie
,
stateObjects
:
make
(
map
[
string
]
*
StateObject
),
refund
:
make
(
map
[
string
]
*
big
.
Int
),
logs
:
make
(
map
[
common
.
Hash
]
Logs
)}
return
&
StateDB
{
db
:
db
,
trie
:
trie
,
stateObjects
:
make
(
map
[
string
]
*
StateObject
),
refund
:
new
(
big
.
Int
),
logs
:
make
(
map
[
common
.
Hash
]
Logs
)}
}
func
(
self
*
StateDB
)
PrintRoot
()
{
...
...
@@ -63,12 +63,8 @@ func (self *StateDB) Logs() Logs {
return
logs
}
func
(
self
*
StateDB
)
Refund
(
address
common
.
Address
,
gas
*
big
.
Int
)
{
addr
:=
address
.
Str
()
if
self
.
refund
[
addr
]
==
nil
{
self
.
refund
[
addr
]
=
new
(
big
.
Int
)
}
self
.
refund
[
addr
]
.
Add
(
self
.
refund
[
addr
],
gas
)
func
(
self
*
StateDB
)
Refund
(
gas
*
big
.
Int
)
{
self
.
refund
.
Add
(
self
.
refund
,
gas
)
}
/*
...
...
@@ -107,13 +103,13 @@ func (self *StateDB) GetCode(addr common.Address) []byte {
return
nil
}
func
(
self
*
StateDB
)
GetState
(
a
common
.
Address
,
b
common
.
Hash
)
[]
byte
{
func
(
self
*
StateDB
)
GetState
(
a
common
.
Address
,
b
common
.
Hash
)
common
.
Hash
{
stateObject
:=
self
.
GetStateObject
(
a
)
if
stateObject
!=
nil
{
return
stateObject
.
GetState
(
b
)
.
Bytes
()
return
stateObject
.
GetState
(
b
)
}
return
nil
return
common
.
Hash
{}
}
func
(
self
*
StateDB
)
IsDeleted
(
addr
common
.
Address
)
bool
{
...
...
@@ -149,10 +145,10 @@ func (self *StateDB) SetCode(addr common.Address, code []byte) {
}
}
func
(
self
*
StateDB
)
SetState
(
addr
common
.
Address
,
key
common
.
Hash
,
value
interface
{}
)
{
func
(
self
*
StateDB
)
SetState
(
addr
common
.
Address
,
key
common
.
Hash
,
value
common
.
Hash
)
{
stateObject
:=
self
.
GetOrNewStateObject
(
addr
)
if
stateObject
!=
nil
{
stateObject
.
SetState
(
key
,
common
.
NewValue
(
value
)
)
stateObject
.
SetState
(
key
,
value
)
}
}
...
...
@@ -263,14 +259,12 @@ func (s *StateDB) Cmp(other *StateDB) bool {
func
(
self
*
StateDB
)
Copy
()
*
StateDB
{
state
:=
New
(
common
.
Hash
{},
self
.
db
)
state
.
trie
=
self
.
trie
.
Copy
()
state
.
trie
=
self
.
trie
for
k
,
stateObject
:=
range
self
.
stateObjects
{
state
.
stateObjects
[
k
]
=
stateObject
.
Copy
()
}
for
addr
,
refund
:=
range
self
.
refund
{
state
.
refund
[
addr
]
=
new
(
big
.
Int
)
.
Set
(
refund
)
}
state
.
refund
.
Set
(
self
.
refund
)
for
hash
,
logs
:=
range
self
.
logs
{
state
.
logs
[
hash
]
=
make
(
Logs
,
len
(
logs
))
...
...
@@ -302,10 +296,6 @@ func (s *StateDB) Reset() {
// Reset all nested states
for
_
,
stateObject
:=
range
s
.
stateObjects
{
if
stateObject
.
State
==
nil
{
continue
}
stateObject
.
Reset
()
}
...
...
@@ -316,11 +306,7 @@ func (s *StateDB) Reset() {
func
(
s
*
StateDB
)
Sync
()
{
// Sync all nested states
for
_
,
stateObject
:=
range
s
.
stateObjects
{
if
stateObject
.
State
==
nil
{
continue
}
stateObject
.
State
.
Sync
()
stateObject
.
trie
.
Commit
()
}
s
.
trie
.
Commit
()
...
...
@@ -330,22 +316,22 @@ func (s *StateDB) Sync() {
func
(
self
*
StateDB
)
Empty
()
{
self
.
stateObjects
=
make
(
map
[
string
]
*
StateObject
)
self
.
refund
=
make
(
map
[
string
]
*
big
.
Int
)
self
.
refund
=
new
(
big
.
Int
)
}
func
(
self
*
StateDB
)
Refunds
()
map
[
string
]
*
big
.
Int
{
func
(
self
*
StateDB
)
Refunds
()
*
big
.
Int
{
return
self
.
refund
}
func
(
self
*
StateDB
)
Update
()
{
self
.
refund
=
make
(
map
[
string
]
*
big
.
Int
)
self
.
refund
=
new
(
big
.
Int
)
for
_
,
stateObject
:=
range
self
.
stateObjects
{
if
stateObject
.
dirty
{
if
stateObject
.
remove
{
self
.
DeleteStateObject
(
stateObject
)
}
else
{
stateObject
.
Sync
()
stateObject
.
Update
()
self
.
UpdateStateObject
(
stateObject
)
}
...
...
core/state_transition.go
View file @
2cea4106
...
...
@@ -241,11 +241,9 @@ func (self *StateTransition) refundGas() {
sender
.
AddBalance
(
remaining
)
uhalf
:=
new
(
big
.
Int
)
.
Div
(
self
.
gasUsed
(),
common
.
Big2
)
for
addr
,
ref
:=
range
self
.
state
.
Refunds
()
{
refund
:=
common
.
BigMin
(
uhalf
,
ref
)
self
.
gas
.
Add
(
self
.
gas
,
refund
)
self
.
state
.
AddBalance
(
common
.
StringToAddress
(
addr
),
refund
.
Mul
(
refund
,
self
.
msg
.
GasPrice
()))
}
refund
:=
common
.
BigMin
(
uhalf
,
self
.
state
.
Refunds
())
self
.
gas
.
Add
(
self
.
gas
,
refund
)
self
.
state
.
AddBalance
(
sender
.
Address
(),
refund
.
Mul
(
refund
,
self
.
msg
.
GasPrice
()))
coinbase
.
RefundGas
(
self
.
gas
,
self
.
msg
.
GasPrice
())
}
...
...
core/transaction_pool.go
View file @
2cea4106
...
...
@@ -105,7 +105,9 @@ func (pool *TxPool) resetState() {
if
addr
,
err
:=
tx
.
From
();
err
==
nil
{
// Set the nonce. Transaction nonce can never be lower
// than the state nonce; validatePool took care of that.
pool
.
pendingState
.
SetNonce
(
addr
,
tx
.
Nonce
())
if
pool
.
pendingState
.
GetNonce
(
addr
)
<
tx
.
Nonce
()
{
pool
.
pendingState
.
SetNonce
(
addr
,
tx
.
Nonce
())
}
}
}
...
...
@@ -153,6 +155,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
return
ErrNonExistentAccount
}
// Last but not least check for nonce errors
if
pool
.
currentState
()
.
GetNonce
(
from
)
>
tx
.
Nonce
()
{
return
ErrNonce
}
// Check the transaction doesn't exceed the current
// block limit gas.
if
pool
.
gasLimit
()
.
Cmp
(
tx
.
GasLimit
)
<
0
{
...
...
@@ -179,12 +186,6 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
return
ErrIntrinsicGas
}
// Last but not least check for nonce errors (intensive
// operation, saved for last)
if
pool
.
currentState
()
.
GetNonce
(
from
)
>
tx
.
Nonce
()
{
return
ErrNonce
}
return
nil
}
...
...
@@ -394,10 +395,13 @@ func (pool *TxPool) removeTx(hash common.Hash) {
// validatePool removes invalid and processed transactions from the main pool.
func
(
pool
*
TxPool
)
validatePool
()
{
state
:=
pool
.
currentState
()
for
hash
,
tx
:=
range
pool
.
pending
{
if
err
:=
pool
.
validateTx
(
tx
);
err
!=
nil
{
from
,
_
:=
tx
.
From
()
// err already checked
// perform light nonce validation
if
state
.
GetNonce
(
from
)
>
tx
.
Nonce
()
{
if
glog
.
V
(
logger
.
Core
)
{
glog
.
Infof
(
"removed tx (%x) from pool:
%v
\n
"
,
hash
[
:
4
],
err
)
glog
.
Infof
(
"removed tx (%x) from pool:
low tx nonce
\n
"
,
hash
[
:
4
]
)
}
delete
(
pool
.
pending
,
hash
)
}
...
...
core/vm/vm.go
View file @
2cea4106
...
...
@@ -506,14 +506,14 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
case
SLOAD
:
loc
:=
common
.
BigToHash
(
stack
.
pop
())
val
:=
common
.
Bytes2Big
(
statedb
.
GetState
(
context
.
Address
(),
loc
)
)
val
:=
statedb
.
GetState
(
context
.
Address
(),
loc
)
.
Big
(
)
stack
.
push
(
val
)
case
SSTORE
:
loc
:=
common
.
BigToHash
(
stack
.
pop
())
val
:=
stack
.
pop
()
statedb
.
SetState
(
context
.
Address
(),
loc
,
val
)
statedb
.
SetState
(
context
.
Address
(),
loc
,
common
.
BigToHash
(
val
)
)
case
JUMP
:
if
err
:=
jump
(
pc
,
stack
.
pop
());
err
!=
nil
{
...
...
@@ -686,11 +686,16 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
var
g
*
big
.
Int
y
,
x
:=
stack
.
data
[
stack
.
len
()
-
2
],
stack
.
data
[
stack
.
len
()
-
1
]
val
:=
statedb
.
GetState
(
context
.
Address
(),
common
.
BigToHash
(
x
))
if
len
(
val
)
==
0
&&
len
(
y
.
Bytes
())
>
0
{
// This checks for 3 scenario's and calculates gas accordingly
// 1. From a zero-value address to a non-zero value (NEW VALUE)
// 2. From a non-zero value address to a zero-value address (DELETE)
// 3. From a nen-zero to a non-zero (CHANGE)
if
common
.
EmptyHash
(
val
)
&&
!
common
.
EmptyHash
(
common
.
BigToHash
(
y
))
{
// 0 => non 0
g
=
params
.
SstoreSetGas
}
else
if
len
(
val
)
>
0
&&
len
(
y
.
Bytes
())
==
0
{
statedb
.
Refund
(
self
.
env
.
Origin
(),
params
.
SstoreRefundGas
)
}
else
if
!
common
.
EmptyHash
(
val
)
&&
common
.
EmptyHash
(
common
.
BigToHash
(
y
))
{
statedb
.
Refund
(
params
.
SstoreRefundGas
)
g
=
params
.
SstoreClearGas
}
else
{
...
...
@@ -700,7 +705,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
gas
.
Set
(
g
)
case
SUICIDE
:
if
!
statedb
.
IsDeleted
(
context
.
Address
())
{
statedb
.
Refund
(
self
.
env
.
Origin
(),
params
.
SuicideRefundGas
)
statedb
.
Refund
(
params
.
SuicideRefundGas
)
}
case
MLOAD
:
newMemSize
=
calcMemSize
(
stack
.
peek
(),
u256
(
32
))
...
...
tests/block_test_util.go
View file @
2cea4106
...
...
@@ -124,7 +124,7 @@ func (t *BlockTest) InsertPreState(ethereum *eth.Ethereum) (*state.StateDB, erro
obj
.
SetBalance
(
balance
)
obj
.
SetNonce
(
nonce
)
for
k
,
v
:=
range
acct
.
Storage
{
statedb
.
SetState
(
common
.
HexToAddress
(
addrString
),
common
.
HexToHash
(
k
),
common
.
FromHex
(
v
))
statedb
.
SetState
(
common
.
HexToAddress
(
addrString
),
common
.
HexToHash
(
k
),
common
.
HexToHash
(
v
))
}
}
// sync objects to trie
...
...
tests/vm/gh_test.go
View file @
2cea4106
...
...
@@ -97,7 +97,7 @@ func RunVmTest(p string, t *testing.T) {
obj
:=
StateObjectFromAccount
(
db
,
addr
,
account
)
statedb
.
SetStateObject
(
obj
)
for
a
,
v
:=
range
account
.
Storage
{
obj
.
SetState
(
common
.
HexToHash
(
a
),
common
.
NewValue
(
helper
.
FromHex
(
v
)
))
obj
.
SetState
(
common
.
HexToHash
(
a
),
common
.
HexToHash
(
v
))
}
}
...
...
@@ -168,11 +168,11 @@ func RunVmTest(p string, t *testing.T) {
}
for
addr
,
value
:=
range
account
.
Storage
{
v
:=
obj
.
GetState
(
common
.
HexToHash
(
addr
))
.
Bytes
()
vexp
:=
helper
.
FromHex
(
value
)
v
:=
obj
.
GetState
(
common
.
HexToHash
(
addr
))
vexp
:=
common
.
HexToHash
(
value
)
if
bytes
.
Compare
(
v
,
vexp
)
!=
0
{
t
.
Errorf
(
"%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)
\n
"
,
name
,
obj
.
Address
()
.
Bytes
()[
0
:
4
],
addr
,
vexp
,
v
,
common
.
BigD
(
vexp
),
common
.
BigD
(
v
))
if
v
!=
vexp
{
t
.
Errorf
(
"%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)
\n
"
,
name
,
obj
.
Address
()
.
Bytes
()[
0
:
4
],
addr
,
vexp
,
v
,
vexp
.
Big
(),
v
.
Big
(
))
}
}
}
...
...
xeth/types.go
View file @
2cea4106
...
...
@@ -22,7 +22,7 @@ func NewObject(state *state.StateObject) *Object {
return
&
Object
{
state
}
}
func
(
self
*
Object
)
StorageString
(
str
string
)
*
common
.
Valu
e
{
func
(
self
*
Object
)
StorageString
(
str
string
)
[]
byt
e
{
if
common
.
IsHex
(
str
)
{
return
self
.
storage
(
common
.
Hex2Bytes
(
str
[
2
:
]))
}
else
{
...
...
@@ -30,12 +30,12 @@ func (self *Object) StorageString(str string) *common.Value {
}
}
func
(
self
*
Object
)
StorageValue
(
addr
*
common
.
Value
)
*
common
.
Valu
e
{
func
(
self
*
Object
)
StorageValue
(
addr
*
common
.
Value
)
[]
byt
e
{
return
self
.
storage
(
addr
.
Bytes
())
}
func
(
self
*
Object
)
storage
(
addr
[]
byte
)
*
common
.
Valu
e
{
return
self
.
StateObject
.
GetSt
orage
(
common
.
BigD
(
addr
)
)
func
(
self
*
Object
)
storage
(
addr
[]
byte
)
[]
byt
e
{
return
self
.
StateObject
.
GetSt
ate
(
common
.
BytesToHash
(
addr
))
.
Bytes
(
)
}
func
(
self
*
Object
)
Storage
()
(
storage
map
[
string
]
string
)
{
...
...
xeth/xeth.go
View file @
2cea4106
...
...
@@ -488,7 +488,7 @@ func (self *XEth) NumberToHuman(balance string) string {
}
func
(
self
*
XEth
)
StorageAt
(
addr
,
storageAddr
string
)
string
{
return
common
.
ToHex
(
self
.
State
()
.
state
.
GetState
(
common
.
HexToAddress
(
addr
),
common
.
HexToHash
(
storageAddr
))
)
return
self
.
State
()
.
state
.
GetState
(
common
.
HexToAddress
(
addr
),
common
.
HexToHash
(
storageAddr
))
.
Hex
(
)
}
func
(
self
*
XEth
)
BalanceAt
(
addr
string
)
string
{
...
...
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