state_transition.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package ethchain
  2. import (
  3. "fmt"
  4. "math/big"
  5. "github.com/ethereum/eth-go/ethstate"
  6. "github.com/ethereum/eth-go/ethtrie"
  7. "github.com/ethereum/eth-go/ethutil"
  8. "github.com/ethereum/eth-go/ethvm"
  9. )
  10. /*
  11. * The State transitioning model
  12. *
  13. * A state transition is a change made when a transaction is applied to the current world state
  14. * The state transitioning model does all all the necessary work to work out a valid new state root.
  15. * 1) Nonce handling
  16. * 2) Pre pay / buy gas of the coinbase (miner)
  17. * 3) Create a new state object if the recipient is \0*32
  18. * 4) Value transfer
  19. * == If contract creation ==
  20. * 4a) Attempt to run transaction data
  21. * 4b) If valid, use result as code for the new state object
  22. * == end ==
  23. * 5) Run Script section
  24. * 6) Derive new state root
  25. */
  26. type StateTransition struct {
  27. coinbase, receiver []byte
  28. tx *Transaction
  29. gas, gasPrice *big.Int
  30. value *big.Int
  31. data []byte
  32. state *ethstate.State
  33. block *Block
  34. cb, rec, sen *ethstate.StateObject
  35. }
  36. func NewStateTransition(coinbase *ethstate.StateObject, tx *Transaction, state *ethstate.State, block *Block) *StateTransition {
  37. 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}
  38. }
  39. func (self *StateTransition) Coinbase() *ethstate.StateObject {
  40. if self.cb != nil {
  41. return self.cb
  42. }
  43. self.cb = self.state.GetOrNewStateObject(self.coinbase)
  44. return self.cb
  45. }
  46. func (self *StateTransition) Sender() *ethstate.StateObject {
  47. if self.sen != nil {
  48. return self.sen
  49. }
  50. self.sen = self.state.GetOrNewStateObject(self.tx.Sender())
  51. return self.sen
  52. }
  53. func (self *StateTransition) Receiver() *ethstate.StateObject {
  54. if self.tx != nil && self.tx.CreatesContract() {
  55. return nil
  56. }
  57. if self.rec != nil {
  58. return self.rec
  59. }
  60. self.rec = self.state.GetOrNewStateObject(self.tx.Recipient)
  61. return self.rec
  62. }
  63. func (self *StateTransition) MakeStateObject(state *ethstate.State, tx *Transaction) *ethstate.StateObject {
  64. contract := MakeContract(tx, state)
  65. return contract
  66. }
  67. func (self *StateTransition) UseGas(amount *big.Int) error {
  68. if self.gas.Cmp(amount) < 0 {
  69. return OutOfGasError()
  70. }
  71. self.gas.Sub(self.gas, amount)
  72. return nil
  73. }
  74. func (self *StateTransition) AddGas(amount *big.Int) {
  75. self.gas.Add(self.gas, amount)
  76. }
  77. func (self *StateTransition) BuyGas() error {
  78. var err error
  79. sender := self.Sender()
  80. if sender.Balance.Cmp(self.tx.GasValue()) < 0 {
  81. return fmt.Errorf("Insufficient funds to pre-pay gas. Req %v, has %v", self.tx.GasValue(), sender.Balance)
  82. }
  83. coinbase := self.Coinbase()
  84. err = coinbase.BuyGas(self.tx.Gas, self.tx.GasPrice)
  85. if err != nil {
  86. return err
  87. }
  88. self.AddGas(self.tx.Gas)
  89. sender.SubAmount(self.tx.GasValue())
  90. return nil
  91. }
  92. func (self *StateTransition) RefundGas() {
  93. coinbase, sender := self.Coinbase(), self.Sender()
  94. coinbase.RefundGas(self.gas, self.tx.GasPrice)
  95. // Return remaining gas
  96. remaining := new(big.Int).Mul(self.gas, self.tx.GasPrice)
  97. sender.AddAmount(remaining)
  98. }
  99. func (self *StateTransition) preCheck() (err error) {
  100. var (
  101. tx = self.tx
  102. sender = self.Sender()
  103. )
  104. // Make sure this transaction's nonce is correct
  105. if sender.Nonce != tx.Nonce {
  106. return NonceError(tx.Nonce, sender.Nonce)
  107. }
  108. // Pre-pay gas / Buy gas of the coinbase account
  109. if err = self.BuyGas(); err != nil {
  110. return err
  111. }
  112. return nil
  113. }
  114. func (self *StateTransition) TransitionState() (err error) {
  115. statelogger.Debugf("(~) %x\n", self.tx.Hash())
  116. /*
  117. defer func() {
  118. if r := recover(); r != nil {
  119. logger.Infoln(r)
  120. err = fmt.Errorf("state transition err %v", r)
  121. }
  122. }()
  123. */
  124. // XXX Transactions after this point are considered valid.
  125. if err = self.preCheck(); err != nil {
  126. return
  127. }
  128. var (
  129. tx = self.tx
  130. sender = self.Sender()
  131. receiver *ethstate.StateObject
  132. )
  133. defer self.RefundGas()
  134. // Increment the nonce for the next transaction
  135. sender.Nonce += 1
  136. // Transaction gas
  137. if err = self.UseGas(ethvm.GasTx); err != nil {
  138. return
  139. }
  140. // Pay data gas
  141. dataPrice := big.NewInt(int64(len(self.data)))
  142. dataPrice.Mul(dataPrice, ethvm.GasData)
  143. if err = self.UseGas(dataPrice); err != nil {
  144. return
  145. }
  146. if sender.Balance.Cmp(self.value) < 0 {
  147. return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance)
  148. }
  149. var snapshot *ethstate.State
  150. // If the receiver is nil it's a contract (\0*32).
  151. if tx.CreatesContract() {
  152. // Subtract the (irreversible) amount from the senders account
  153. sender.SubAmount(self.value)
  154. snapshot = self.state.Copy()
  155. // Create a new state object for the contract
  156. receiver = self.MakeStateObject(self.state, tx)
  157. self.rec = receiver
  158. if receiver == nil {
  159. return fmt.Errorf("Unable to create contract")
  160. }
  161. // Add the amount to receivers account which should conclude this transaction
  162. receiver.AddAmount(self.value)
  163. } else {
  164. receiver = self.Receiver()
  165. // Subtract the amount from the senders account
  166. sender.SubAmount(self.value)
  167. // Add the amount to receivers account which should conclude this transaction
  168. receiver.AddAmount(self.value)
  169. snapshot = self.state.Copy()
  170. }
  171. msg := self.state.Manifest().AddMessage(&ethstate.Message{
  172. To: receiver.Address(), From: sender.Address(),
  173. Input: self.tx.Data,
  174. Origin: sender.Address(),
  175. Block: self.block.Hash(), Timestamp: self.block.Time, Coinbase: self.block.Coinbase, Number: self.block.Number,
  176. Value: self.value,
  177. })
  178. // Process the init code and create 'valid' contract
  179. if IsContractAddr(self.receiver) {
  180. // Evaluate the initialization script
  181. // and use the return value as the
  182. // script section for the state object.
  183. self.data = nil
  184. code, err := self.Eval(msg, receiver.Init(), receiver, "init")
  185. if err != nil {
  186. self.state.Set(snapshot)
  187. return fmt.Errorf("Error during init execution %v", err)
  188. }
  189. receiver.Code = code
  190. msg.Output = code
  191. } else {
  192. if len(receiver.Code) > 0 {
  193. ret, err := self.Eval(msg, receiver.Code, receiver, "code")
  194. if err != nil {
  195. self.state.Set(snapshot)
  196. return fmt.Errorf("Error during code execution %v", err)
  197. }
  198. msg.Output = ret
  199. }
  200. }
  201. return
  202. }
  203. func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObject) error {
  204. if sender.Balance.Cmp(self.value) < 0 {
  205. return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance)
  206. }
  207. // Subtract the amount from the senders account
  208. sender.SubAmount(self.value)
  209. // Add the amount to receivers account which should conclude this transaction
  210. receiver.AddAmount(self.value)
  211. return nil
  212. }
  213. func (self *StateTransition) Eval(msg *ethstate.Message, script []byte, context *ethstate.StateObject, typ string) (ret []byte, err error) {
  214. var (
  215. transactor = self.Sender()
  216. state = self.state
  217. env = NewEnv(state, self.tx, self.block)
  218. callerClosure = ethvm.NewClosure(msg, transactor, context, script, self.gas, self.gasPrice)
  219. )
  220. vm := ethvm.New(env)
  221. vm.Verbose = true
  222. vm.Fn = typ
  223. ret, _, err = callerClosure.Call(vm, self.tx.Data)
  224. if err == nil {
  225. // Execute POSTs
  226. for e := vm.Queue().Front(); e != nil; e = e.Next() {
  227. msg := e.Value.(*ethvm.Message)
  228. msg.Exec(transactor)
  229. }
  230. }
  231. return
  232. }
  233. // Converts an transaction in to a state object
  234. func MakeContract(tx *Transaction, state *ethstate.State) *ethstate.StateObject {
  235. // Create contract if there's no recipient
  236. if tx.IsContract() {
  237. addr := tx.CreationAddress()
  238. contract := state.NewStateObject(addr)
  239. contract.InitCode = tx.Data
  240. contract.State = ethstate.New(ethtrie.New(ethutil.Config.Db, ""))
  241. return contract
  242. }
  243. return nil
  244. }