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
731f55a0
Commit
731f55a0
authored
Jun 19, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reset state when a transition fails
parent
509389be
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
93 additions
and
46 deletions
+93
-46
state.go
ethchain/state.go
+6
-1
state_transition.go
ethchain/state_transition.go
+87
-45
No files found.
ethchain/state.go
View file @
731f55a0
...
...
@@ -78,11 +78,16 @@ func (s *State) EachStorage(cb ethutil.EachCallback) {
it
.
Each
(
cb
)
}
func
(
self
*
State
)
ResetStateObject
(
stateObject
*
StateObject
)
{
stateObject
.
state
.
Reset
()
delete
(
self
.
stateObjects
,
string
(
stateObject
.
Address
()))
}
func
(
self
*
State
)
UpdateStateObject
(
stateObject
*
StateObject
)
{
addr
:=
stateObject
.
Address
()
if
self
.
stateObjects
[
string
(
addr
)]
==
nil
{
panic
(
"?"
)
self
.
stateObjects
[
string
(
addr
)]
=
stateObject
}
...
...
ethchain/state_transition.go
View file @
731f55a0
...
...
@@ -23,17 +23,36 @@ 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
Transition
(
coinbase
,
sender
,
receiver
,
data
[]
byte
,
gas
,
gasPrice
,
value
*
big
.
Int
,
state
*
State
,
block
*
Block
)
(
ret
[]
byte
,
err
error
)
{
stateTransition
:=
&
StateTransition
{
coinbase
:
coinbase
,
receiver
:
receiver
,
cb
:
state
.
GetOrNewStateObject
(
coinbase
),
rec
:
state
.
GetOrNewStateObject
(
receiver
),
sen
:
state
.
GetOrNewStateObject
(
sender
),
gas
:
gas
,
gasPrice
:
gasPrice
,
value
:
value
,
state
:
state
,
block
:
block
,
}
return
stateTransition
.
Transition
()
}
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 +72,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
}
...
...
@@ -113,6 +132,25 @@ func (self *StateTransition) RefundGas() {
sender
.
AddAmount
(
remaining
)
}
func
(
self
*
StateTransition
)
preCheck
()
(
err
error
)
{
var
(
tx
=
self
.
tx
sender
=
self
.
Sender
()
)
// Make sure this transaction's nonce is correct
if
sender
.
Nonce
!=
tx
.
Nonce
{
return
NonceError
(
tx
.
Nonce
,
sender
.
Nonce
)
}
// Pre-pay gas / Buy gas of the coinbase account
if
err
=
self
.
BuyGas
();
err
!=
nil
{
return
err
}
return
nil
}
func
(
self
*
StateTransition
)
TransitionState
()
(
err
error
)
{
ethutil
.
Config
.
Log
.
Printf
(
ethutil
.
LogLevelInfo
,
"(~) %x
\n
"
,
self
.
tx
.
Hash
())
...
...
@@ -125,26 +163,25 @@ func (self *StateTransition) TransitionState() (err error) {
}()
*/
// XXX Transactions after this point are considered valid.
if
err
=
self
.
preCheck
();
err
!=
nil
{
return
}
defer
self
.
RefundGas
()
_
,
err
=
self
.
Transition
()
return
}
func
(
self
*
StateTransition
)
Transition
()
(
ret
[]
byte
,
err
error
)
{
var
(
tx
=
self
.
tx
sender
=
self
.
Sender
()
receiver
*
StateObject
)
// Make sure this transaction's nonce is correct
if
sender
.
Nonce
!=
tx
.
Nonce
{
return
NonceError
(
tx
.
Nonce
,
sender
.
Nonce
)
}
// Pre-pay gas / Buy gas of the coinbase account
if
err
=
self
.
BuyGas
();
err
!=
nil
{
return
err
}
// XXX Transactions after this point are considered valid.
defer
self
.
RefundGas
()
// Increment the nonce for the next transaction
sender
.
Nonce
+=
1
...
...
@@ -152,14 +189,14 @@ func (self *StateTransition) TransitionState() (err error) {
// 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).
...
...
@@ -167,25 +204,28 @@ 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
nil
,
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.
self
.
data
=
nil
ethutil
.
Config
.
Log
.
Println
(
ethutil
.
LogLevelSystem
,
receiver
.
Init
())
code
,
err
:=
self
.
Eval
(
receiver
.
Init
(),
receiver
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error during init script run %v"
,
err
)
self
.
state
.
ResetStateObject
(
receiver
)
return
nil
,
fmt
.
Errorf
(
"Error during init script run %v"
,
err
)
}
receiver
.
script
=
code
...
...
@@ -193,53 +233,55 @@ func (self *StateTransition) TransitionState() (err error) {
if
len
(
receiver
.
Script
())
>
0
{
ethutil
.
Config
.
Log
.
Println
(
ethutil
.
LogLevelSystem
,
receiver
.
Script
())
_
,
err
:
=
self
.
Eval
(
receiver
.
Script
(),
receiver
)
ret
,
err
=
self
.
Eval
(
receiver
.
Script
(),
receiver
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error during code execution %v"
,
err
)
self
.
state
.
ResetStateObject
(
receiver
)
return
nil
,
fmt
.
Errorf
(
"Error during code execution %v"
,
err
)
}
}
}
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
)
{
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
,
})
vm
.
Verbose
=
true
ret
,
_
,
err
=
closure
.
Call
(
vm
,
tx
.
D
ata
,
nil
)
ret
,
_
,
err
=
closure
.
Call
(
vm
,
self
.
d
ata
,
nil
)
return
}
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