5
5
"math/big"
6
6
7
7
"github.com/ethereum/go-ethereum/core/types"
8
+ "github.com/ethereum/go-ethereum/crypto"
9
+ "github.com/ethereum/go-ethereum/ethutil"
8
10
"github.com/ethereum/go-ethereum/state"
9
11
"github.com/ethereum/go-ethereum/vm"
10
12
)
@@ -27,18 +29,50 @@ import (
27
29
*/
28
30
type StateTransition struct {
29
31
coinbase , receiver []byte
30
- tx * types. Transaction
32
+ msg Message
31
33
gas , gasPrice * big.Int
32
34
value * big.Int
33
35
data []byte
34
36
state * state.StateDB
35
37
block * types.Block
36
38
37
39
cb , rec , sen * state.StateObject
40
+
41
+ Env vm.Environment
42
+ }
43
+
44
+ type Message interface {
45
+ Hash () []byte
46
+
47
+ CreatesContract () bool
48
+
49
+ From () []byte
50
+ To () []byte
51
+
52
+ GasValue () * big.Int
53
+ GasPrice () * big.Int
54
+ Gas () * big.Int
55
+ Value () * big.Int
56
+
57
+ Nonce () uint64
58
+ Data () []byte
38
59
}
39
60
40
- func NewStateTransition (coinbase * state.StateObject , tx * types.Transaction , state * state.StateDB , block * types.Block ) * StateTransition {
41
- 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 }
61
+ func AddressFromMessage (msg Message ) []byte {
62
+ // Generate a new address
63
+ return crypto .Sha3 (ethutil .NewValue ([]interface {}{msg .From (), msg .Nonce ()}).Encode ())[12 :]
64
+ }
65
+
66
+ func NewStateTransition (coinbase * state.StateObject , msg Message , state * state.StateDB , block * types.Block ) * StateTransition {
67
+ return & StateTransition {coinbase .Address (), msg .To (), msg , new (big.Int ), new (big.Int ).Set (msg .GasPrice ()), msg .Value (), msg .Data (), state , block , coinbase , nil , nil , nil }
68
+ }
69
+
70
+ func (self * StateTransition ) VmEnv () vm.Environment {
71
+ if self .Env == nil {
72
+ self .Env = NewEnv (self .state , self .msg , self .block )
73
+ }
74
+
75
+ return self .Env
42
76
}
43
77
44
78
func (self * StateTransition ) Coinbase () * state.StateObject {
@@ -49,25 +83,25 @@ func (self *StateTransition) Coinbase() *state.StateObject {
49
83
self .cb = self .state .GetOrNewStateObject (self .coinbase )
50
84
return self .cb
51
85
}
52
- func (self * StateTransition ) Sender () * state.StateObject {
86
+ func (self * StateTransition ) From () * state.StateObject {
53
87
if self .sen != nil {
54
88
return self .sen
55
89
}
56
90
57
- self .sen = self .state .GetOrNewStateObject (self .tx . Sender ())
91
+ self .sen = self .state .GetOrNewStateObject (self .msg . From ())
58
92
59
93
return self .sen
60
94
}
61
- func (self * StateTransition ) Receiver () * state.StateObject {
62
- if self .tx != nil && self .tx .CreatesContract () {
95
+ func (self * StateTransition ) To () * state.StateObject {
96
+ if self .msg != nil && self .msg .CreatesContract () {
63
97
return nil
64
98
}
65
99
66
100
if self .rec != nil {
67
101
return self .rec
68
102
}
69
103
70
- self .rec = self .state .GetOrNewStateObject (self .tx . Recipient )
104
+ self .rec = self .state .GetOrNewStateObject (self .msg . To () )
71
105
return self .rec
72
106
}
73
107
@@ -87,41 +121,41 @@ func (self *StateTransition) AddGas(amount *big.Int) {
87
121
func (self * StateTransition ) BuyGas () error {
88
122
var err error
89
123
90
- sender := self .Sender ()
91
- if sender .Balance ().Cmp (self .tx .GasValue ()) < 0 {
92
- return fmt .Errorf ("Insufficient funds to pre-pay gas. Req %v, has %v" , self .tx .GasValue (), sender .Balance ())
124
+ sender := self .From ()
125
+ if sender .Balance ().Cmp (self .msg .GasValue ()) < 0 {
126
+ return fmt .Errorf ("Insufficient funds to pre-pay gas. Req %v, has %v" , self .msg .GasValue (), sender .Balance ())
93
127
}
94
128
95
129
coinbase := self .Coinbase ()
96
- err = coinbase .BuyGas (self .tx .Gas , self .tx .GasPrice )
130
+ err = coinbase .BuyGas (self .msg .Gas () , self .msg .GasPrice () )
97
131
if err != nil {
98
132
return err
99
133
}
100
134
101
- self .AddGas (self .tx .Gas )
102
- sender .SubAmount (self .tx .GasValue ())
135
+ self .AddGas (self .msg .Gas () )
136
+ sender .SubAmount (self .msg .GasValue ())
103
137
104
138
return nil
105
139
}
106
140
107
141
func (self * StateTransition ) RefundGas () {
108
- coinbase , sender := self .Coinbase (), self .Sender ()
109
- coinbase .RefundGas (self .gas , self .tx .GasPrice )
142
+ coinbase , sender := self .Coinbase (), self .From ()
143
+ coinbase .RefundGas (self .gas , self .msg .GasPrice () )
110
144
111
145
// Return remaining gas
112
- remaining := new (big.Int ).Mul (self .gas , self .tx .GasPrice )
146
+ remaining := new (big.Int ).Mul (self .gas , self .msg .GasPrice () )
113
147
sender .AddAmount (remaining )
114
148
}
115
149
116
150
func (self * StateTransition ) preCheck () (err error ) {
117
151
var (
118
- tx = self .tx
119
- sender = self .Sender ()
152
+ msg = self .msg
153
+ sender = self .From ()
120
154
)
121
155
122
156
// Make sure this transaction's nonce is correct
123
- if sender .Nonce != tx .Nonce {
124
- return NonceError (tx .Nonce , sender .Nonce )
157
+ if sender .Nonce != msg .Nonce () {
158
+ return NonceError (msg .Nonce () , sender .Nonce )
125
159
}
126
160
127
161
// Pre-pay gas / Buy gas of the coinbase account
@@ -133,16 +167,16 @@ func (self *StateTransition) preCheck() (err error) {
133
167
}
134
168
135
169
func (self * StateTransition ) TransitionState () (err error ) {
136
- statelogger .Debugf ("(~) %x\n " , self .tx .Hash ())
170
+ statelogger .Debugf ("(~) %x\n " , self .msg .Hash ())
137
171
138
172
// XXX Transactions after this point are considered valid.
139
173
if err = self .preCheck (); err != nil {
140
174
return
141
175
}
142
176
143
177
var (
144
- tx = self .tx
145
- sender = self .Sender ()
178
+ msg = self .msg
179
+ sender = self .From ()
146
180
)
147
181
148
182
defer self .RefundGas ()
@@ -169,15 +203,15 @@ func (self *StateTransition) TransitionState() (err error) {
169
203
}
170
204
171
205
var ret []byte
172
- vmenv := NewEnv ( self .state , self . tx , self . block )
206
+ vmenv := self .VmEnv ( )
173
207
var ref vm.ClosureRef
174
- if tx .CreatesContract () {
175
- self .rec = MakeContract (tx , self .state )
208
+ if msg .CreatesContract () {
209
+ self .rec = MakeContract (msg , self .state )
176
210
177
- ret , err , ref = vmenv .Create (sender , self .rec .Address (), self .tx .Data , self .gas , self .gasPrice , self .value )
211
+ ret , err , ref = vmenv .Create (sender , self .rec .Address (), self .msg .Data () , self .gas , self .gasPrice , self .value )
178
212
ref .SetCode (ret )
179
213
} else {
180
- ret , err = vmenv .Call (self .Sender (), self .Receiver ().Address (), self .tx .Data , self .gas , self .gasPrice , self .value )
214
+ ret , err = vmenv .Call (self .From (), self .To ().Address (), self .msg .Data () , self .gas , self .gasPrice , self .value )
181
215
}
182
216
if err != nil {
183
217
statelogger .Debugln (err )
@@ -187,11 +221,11 @@ func (self *StateTransition) TransitionState() (err error) {
187
221
}
188
222
189
223
// Converts an transaction in to a state object
190
- func MakeContract (tx * types. Transaction , state * state.StateDB ) * state.StateObject {
191
- addr := tx . CreationAddress ( state )
224
+ func MakeContract (msg Message , state * state.StateDB ) * state.StateObject {
225
+ addr := AddressFromMessage ( msg )
192
226
193
227
contract := state .GetOrNewStateObject (addr )
194
- contract .InitCode = tx .Data
228
+ contract .InitCode = msg .Data ()
195
229
196
230
return contract
197
231
}
0 commit comments