aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-04-16 10:06:51 +0800
committerobscuren <geffobscura@gmail.com>2014-04-16 10:06:51 +0800
commit9c6aca78933c14ca107da30c4690808950718368 (patch)
treeda641b2904ea6ed05870a1ded486543529eae5a3
parentca13e3b1058f0d680b79dc1d9319d427a09493f8 (diff)
downloadgo-tangerine-9c6aca78933c14ca107da30c4690808950718368.tar
go-tangerine-9c6aca78933c14ca107da30c4690808950718368.tar.gz
go-tangerine-9c6aca78933c14ca107da30c4690808950718368.tar.bz2
go-tangerine-9c6aca78933c14ca107da30c4690808950718368.tar.lz
go-tangerine-9c6aca78933c14ca107da30c4690808950718368.tar.xz
go-tangerine-9c6aca78933c14ca107da30c4690808950718368.tar.zst
go-tangerine-9c6aca78933c14ca107da30c4690808950718368.zip
Merged accounts and contracts in to StateObject
* Account removed * Contract removed * Address state changed to CachedStateObject * Added StateObject
-rw-r--r--ethchain/address.go76
-rw-r--r--ethchain/address_test.go8
-rw-r--r--ethchain/block.go7
-rw-r--r--ethchain/block_chain.go6
-rw-r--r--ethchain/contract.go119
-rw-r--r--ethchain/keypair.go4
-rw-r--r--ethchain/state.go65
-rw-r--r--ethchain/state_manager.go54
-rw-r--r--ethchain/state_object.go162
-rw-r--r--ethchain/transaction.go4
-rw-r--r--ethchain/transaction_pool.go14
11 files changed, 219 insertions, 300 deletions
diff --git a/ethchain/address.go b/ethchain/address.go
deleted file mode 100644
index 0b3ef7c05..000000000
--- a/ethchain/address.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package ethchain
-
-import (
- "github.com/ethereum/eth-go/ethutil"
- "math/big"
-)
-
-type Account struct {
- address []byte
- Amount *big.Int
- Nonce uint64
-}
-
-func NewAccount(address []byte, amount *big.Int) *Account {
- return &Account{address, amount, 0}
-}
-
-func NewAccountFromData(address, data []byte) *Account {
- account := &Account{address: address}
- account.RlpDecode(data)
-
- return account
-}
-
-func (a *Account) AddFee(fee *big.Int) {
- a.AddFunds(fee)
-}
-
-func (a *Account) AddFunds(funds *big.Int) {
- a.Amount.Add(a.Amount, funds)
-}
-
-func (a *Account) Address() []byte {
- return a.address
-}
-
-// Implements Callee
-func (a *Account) ReturnGas(value *big.Int, state *State) {
- // Return the value back to the sender
- a.AddFunds(value)
- state.UpdateAccount(a.address, a)
-}
-
-func (a *Account) RlpEncode() []byte {
- return ethutil.Encode([]interface{}{a.Amount, a.Nonce})
-}
-
-func (a *Account) RlpDecode(data []byte) {
- decoder := ethutil.NewValueFromBytes(data)
-
- a.Amount = decoder.Get(0).BigInt()
- a.Nonce = decoder.Get(1).Uint()
-}
-
-type AddrStateStore struct {
- states map[string]*AccountState
-}
-
-func NewAddrStateStore() *AddrStateStore {
- return &AddrStateStore{states: make(map[string]*AccountState)}
-}
-
-func (s *AddrStateStore) Add(addr []byte, account *Account) *AccountState {
- state := &AccountState{Nonce: account.Nonce, Account: account}
- s.states[string(addr)] = state
- return state
-}
-
-func (s *AddrStateStore) Get(addr []byte) *AccountState {
- return s.states[string(addr)]
-}
-
-type AccountState struct {
- Nonce uint64
- Account *Account
-}
diff --git a/ethchain/address_test.go b/ethchain/address_test.go
deleted file mode 100644
index 161e1b251..000000000
--- a/ethchain/address_test.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package ethchain
-
-import (
- "testing"
-)
-
-func TestAddressState(t *testing.T) {
-}
diff --git a/ethchain/block.go b/ethchain/block.go
index 732739c1b..8c93947fb 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -142,12 +142,13 @@ func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
data := block.state.trie.Get(string(block.Coinbase))
// Get the ether (Coinbase) and add the fee (gief fee to miner)
- ether := NewAccountFromData(block.Coinbase, []byte(data))
+ account := NewStateObjectFromBytes(block.Coinbase, []byte(data))
base = new(big.Int)
- ether.Amount = base.Add(ether.Amount, fee)
+ account.Amount = base.Add(account.Amount, fee)
- block.state.trie.Update(string(block.Coinbase), string(ether.RlpEncode()))
+ //block.state.trie.Update(string(block.Coinbase), string(ether.RlpEncode()))
+ block.state.UpdateStateObject(account)
return true
}
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 2a50ef687..d65c38fe4 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -262,9 +262,9 @@ func AddTestNetFunds(block *Block) {
} {
//log.Println("2^200 Wei to", addr)
codedAddr := ethutil.FromHex(addr)
- addr := block.state.GetAccount(codedAddr)
- addr.Amount = ethutil.BigPow(2, 200)
- block.state.UpdateAccount(codedAddr, addr)
+ account := block.state.GetAccount(codedAddr)
+ account.Amount = ethutil.BigPow(2, 200)
+ block.state.UpdateStateObject(account)
}
}
diff --git a/ethchain/contract.go b/ethchain/contract.go
deleted file mode 100644
index af348667c..000000000
--- a/ethchain/contract.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package ethchain
-
-import (
- "github.com/ethereum/eth-go/ethutil"
- "math/big"
-)
-
-type Contract struct {
- Amount *big.Int
- Nonce uint64
- //state *ethutil.Trie
- state *State
- address []byte
- script []byte
- initScript []byte
-}
-
-func NewContract(address []byte, Amount *big.Int, root []byte) *Contract {
- contract := &Contract{address: address, Amount: Amount, Nonce: 0}
- contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, string(root)))
-
- return contract
-}
-
-func NewContractFromBytes(address, data []byte) *Contract {
- contract := &Contract{address: address}
- contract.RlpDecode(data)
-
- return contract
-}
-
-func (c *Contract) Addr(addr []byte) *ethutil.Value {
- return ethutil.NewValueFromBytes([]byte(c.state.trie.Get(string(addr))))
-}
-
-func (c *Contract) SetAddr(addr []byte, value interface{}) {
- c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
-}
-
-func (c *Contract) State() *State {
- return c.state
-}
-
-func (c *Contract) GetMem(num *big.Int) *ethutil.Value {
- nb := ethutil.BigToBytes(num, 256)
-
- return c.Addr(nb)
-}
-
-func (c *Contract) GetInstr(pc *big.Int) *ethutil.Value {
- if int64(len(c.script)-1) < pc.Int64() {
- return ethutil.NewValue(0)
- }
-
- return ethutil.NewValueFromBytes([]byte{c.script[pc.Int64()]})
-}
-
-func (c *Contract) SetMem(num *big.Int, val *ethutil.Value) {
- addr := ethutil.BigToBytes(num, 256)
- c.state.trie.Update(string(addr), string(val.Encode()))
-}
-
-// Return the gas back to the origin. Used by the Virtual machine or Closures
-func (c *Contract) ReturnGas(val *big.Int, state *State) {
- c.Amount.Add(c.Amount, val)
-}
-
-func (c *Contract) Address() []byte {
- return c.address
-}
-
-func (c *Contract) Script() []byte {
- return c.script
-}
-
-func (c *Contract) Init() []byte {
- return c.initScript
-}
-
-func (c *Contract) RlpEncode() []byte {
- return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root, c.script, c.initScript})
-}
-
-func (c *Contract) RlpDecode(data []byte) {
- decoder := ethutil.NewValueFromBytes(data)
-
- c.Amount = decoder.Get(0).BigInt()
- c.Nonce = decoder.Get(1).Uint()
- c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
- c.script = decoder.Get(3).Bytes()
- c.initScript = decoder.Get(4).Bytes()
-}
-
-func MakeContract(tx *Transaction, state *State) *Contract {
- // Create contract if there's no recipient
- if tx.IsContract() {
- addr := tx.Hash()[12:]
-
- value := tx.Value
- contract := NewContract(addr, value, []byte(""))
- state.trie.Update(string(addr), string(contract.RlpEncode()))
- contract.script = tx.Data
- contract.initScript = tx.Init
-
- /*
- for i, val := range tx.Data {
- if len(val) > 0 {
- bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256)
- contract.state.trie.Update(string(bytNum), string(ethutil.Encode(val)))
- }
- }
- */
- state.trie.Update(string(addr), string(contract.RlpEncode()))
-
- return contract
- }
-
- return nil
-}
diff --git a/ethchain/keypair.go b/ethchain/keypair.go
index 9daaedbee..a5af791d0 100644
--- a/ethchain/keypair.go
+++ b/ethchain/keypair.go
@@ -10,7 +10,7 @@ type KeyPair struct {
PublicKey []byte
// The associated account
- account *Account
+ account *StateObject
state *State
}
@@ -24,7 +24,7 @@ func (k *KeyPair) Address() []byte {
return ethutil.Sha3Bin(k.PublicKey[1:])[12:]
}
-func (k *KeyPair) Account() *Account {
+func (k *KeyPair) Account() *StateObject {
if k.account == nil {
k.account = k.state.GetAccount(k.Address())
}
diff --git a/ethchain/state.go b/ethchain/state.go
index 1860647f2..655848932 100644
--- a/ethchain/state.go
+++ b/ethchain/state.go
@@ -47,23 +47,14 @@ func (s *State) Purge() int {
return s.trie.NewIterator().Purge()
}
-func (s *State) GetContract(addr []byte) *Contract {
+func (s *State) GetContract(addr []byte) *StateObject {
data := s.trie.Get(string(addr))
if data == "" {
return nil
}
- // Whet get contract is called the retrieved value might
- // be an account. The StateManager uses this to check
- // to see if the address a tx was sent to is a contract
- // or an account
- value := ethutil.NewValueFromBytes([]byte(data))
- if value.Len() == 2 {
- return nil
- }
-
// build contract
- contract := NewContractFromBytes(addr, []byte(data))
+ contract := NewStateObjectFromBytes(addr, []byte(data))
// Check if there's a cached state for this contract
cachedState := s.states[string(addr)]
@@ -77,28 +68,17 @@ func (s *State) GetContract(addr []byte) *Contract {
return contract
}
-func (s *State) UpdateContract(contract *Contract) {
- addr := contract.Address()
-
- s.states[string(addr)] = contract.state
- s.trie.Update(string(addr), string(contract.RlpEncode()))
-}
-
-func (s *State) GetAccount(addr []byte) (account *Account) {
+func (s *State) GetAccount(addr []byte) (account *StateObject) {
data := s.trie.Get(string(addr))
if data == "" {
account = NewAccount(addr, big.NewInt(0))
} else {
- account = NewAccountFromData(addr, []byte(data))
+ account = NewStateObjectFromBytes(addr, []byte(data))
}
return
}
-func (s *State) UpdateAccount(addr []byte, account *Account) {
- s.trie.Update(string(addr), string(account.RlpEncode()))
-}
-
func (s *State) Cmp(other *State) bool {
return s.trie.Cmp(other.trie)
}
@@ -119,7 +99,7 @@ const (
// Returns the object stored at key and the type stored at key
// Returns nil if nothing is stored
-func (s *State) Get(key []byte) (*ethutil.Value, ObjType) {
+func (s *State) GetStateObject(key []byte) (*ethutil.Value, ObjType) {
// Fetch data from the trie
data := s.trie.Get(string(key))
// Returns the nil type, indicating nothing could be retrieved.
@@ -145,34 +125,21 @@ func (s *State) Get(key []byte) (*ethutil.Value, ObjType) {
return val, typ
}
-func (s *State) Put(key, object []byte) {
- s.trie.Update(string(key), string(object))
-}
+// Updates any given state object
+func (s *State) UpdateStateObject(object *StateObject) {
+ addr := object.Address()
-func (s *State) Root() interface{} {
- return s.trie.Root
-}
-
-// Script compilation functions
-// Compiles strings to machine code
-func Compile(code []string) (script []string) {
- script = make([]string, len(code))
- for i, val := range code {
- instr, _ := ethutil.CompileInstr(val)
-
- script[i] = string(instr)
+ if object.state != nil {
+ s.states[string(addr)] = object.state
}
- return
+ s.trie.Update(string(addr), string(object.RlpEncode()))
}
-func CompileToValues(code []string) (script []*ethutil.Value) {
- script = make([]*ethutil.Value, len(code))
- for i, val := range code {
- instr, _ := ethutil.CompileInstr(val)
-
- script[i] = ethutil.NewValue(instr)
- }
+func (s *State) Put(key, object []byte) {
+ s.trie.Update(string(key), string(object))
+}
- return
+func (s *State) Root() interface{} {
+ return s.trie.Root
}
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 549d59959..5e30d7280 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -30,7 +30,7 @@ type StateManager struct {
bc *BlockChain
// States for addresses. You can watch any address
// at any given time
- addrStateStore *AddrStateStore
+ stateObjectCache *StateObjectCache
// Stack for processing contracts
stack *Stack
@@ -54,12 +54,12 @@ type StateManager struct {
func NewStateManager(ethereum EthManager) *StateManager {
sm := &StateManager{
- stack: NewStack(),
- mem: make(map[string]*big.Int),
- Pow: &EasyPow{},
- Ethereum: ethereum,
- addrStateStore: NewAddrStateStore(),
- bc: ethereum.BlockChain(),
+ stack: NewStack(),
+ mem: make(map[string]*big.Int),
+ Pow: &EasyPow{},
+ Ethereum: ethereum,
+ stateObjectCache: NewStateObjectCache(),
+ bc: ethereum.BlockChain(),
}
sm.procState = ethereum.BlockChain().CurrentBlock.State()
return sm
@@ -70,18 +70,18 @@ func (sm *StateManager) ProcState() *State {
}
// Watches any given address and puts it in the address state store
-func (sm *StateManager) WatchAddr(addr []byte) *AccountState {
+func (sm *StateManager) WatchAddr(addr []byte) *CachedStateObject {
//XXX account := sm.bc.CurrentBlock.state.GetAccount(addr)
account := sm.procState.GetAccount(addr)
- return sm.addrStateStore.Add(addr, account)
+ return sm.stateObjectCache.Add(addr, account)
}
-func (sm *StateManager) GetAddrState(addr []byte) *AccountState {
- account := sm.addrStateStore.Get(addr)
+func (sm *StateManager) GetAddrState(addr []byte) *CachedStateObject {
+ account := sm.stateObjectCache.Get(addr)
if account == nil {
a := sm.procState.GetAccount(addr)
- account = &AccountState{Nonce: a.Nonce, Account: a}
+ account = &CachedStateObject{Nonce: a.Nonce, Object: a}
}
return account
@@ -116,7 +116,7 @@ func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
if contract := sm.procState.GetContract(tx.Recipient); contract != nil {
err = sm.Ethereum.TxPool().ProcessTransaction(tx, block, true)
if err == nil {
- sm.ProcessContract(contract, tx, block)
+ sm.EvalScript(contract.Script(), contract, tx, block)
}
} else {
err = sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
@@ -180,7 +180,6 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
return err
}
- // if !sm.compState.Cmp(sm.procState)
if !sm.compState.Cmp(sm.procState) {
return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root)
}
@@ -190,9 +189,6 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
// Sync the current block's state to the database and cancelling out the deferred Undo
sm.procState.Sync()
- // Broadcast the valid block back to the wire
- //sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})
-
// Add the block to the chain
sm.bc.Add(block)
@@ -282,22 +278,20 @@ func CalculateUncleReward(block *Block) *big.Int {
}
func (sm *StateManager) AccumelateRewards(block *Block) error {
-
- // Get the coinbase rlp data
- acc := sm.procState.GetAccount(block.Coinbase)
+ // Get the account associated with the coinbase
+ account := sm.procState.GetAccount(block.Coinbase)
// Reward amount of ether to the coinbase address
- acc.AddFee(CalculateBlockReward(block, len(block.Uncles)))
+ account.AddAmount(CalculateBlockReward(block, len(block.Uncles)))
addr := make([]byte, len(block.Coinbase))
copy(addr, block.Coinbase)
- sm.procState.UpdateAccount(addr, acc)
+ sm.procState.UpdateStateObject(account)
for _, uncle := range block.Uncles {
- uncleAddr := sm.procState.GetAccount(uncle.Coinbase)
- uncleAddr.AddFee(CalculateUncleReward(uncle))
+ uncleAccount := sm.procState.GetAccount(uncle.Coinbase)
+ uncleAccount.AddAmount(CalculateUncleReward(uncle))
- //processor.state.UpdateAccount(uncle.Coinbase, uncleAddr)
- sm.procState.UpdateAccount(uncle.Coinbase, uncleAddr)
+ sm.procState.UpdateStateObject(uncleAccount)
}
return nil
@@ -307,7 +301,7 @@ func (sm *StateManager) Stop() {
sm.bc.Stop()
}
-func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, block *Block) {
+func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Transaction, block *Block) {
// Recovering function in case the VM had any errors
defer func() {
if r := recover(); r != nil {
@@ -316,7 +310,7 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
}()
caller := sm.procState.GetAccount(tx.Sender())
- closure := NewClosure(caller, contract, contract.script, sm.procState, tx.Gas, tx.Value)
+ closure := NewClosure(caller, object, script, sm.procState, tx.Gas, tx.Value)
vm := NewVm(sm.procState, RuntimeVars{
Origin: caller.Address(),
BlockNumber: block.BlockInfo().Number,
@@ -324,11 +318,9 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
- // XXX Tx data? Could be just an argument to the closure instead
- TxData: nil,
})
closure.Call(vm, nil, nil)
// Update the account (refunds)
- sm.procState.UpdateAccount(tx.Sender(), caller)
+ sm.procState.UpdateStateObject(caller)
}
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
new file mode 100644
index 000000000..8b4de0c4f
--- /dev/null
+++ b/ethchain/state_object.go
@@ -0,0 +1,162 @@
+package ethchain
+
+import (
+ "github.com/ethereum/eth-go/ethutil"
+ "math/big"
+)
+
+type StateObject struct {
+ // Address of the object
+ address []byte
+ // Shared attributes
+ Amount *big.Int
+ Nonce uint64
+ // Contract related attributes
+ state *State
+ script []byte
+ initScript []byte
+}
+
+func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject {
+ contract := &StateObject{address: address, Amount: Amount, Nonce: 0}
+ contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, string(root)))
+
+ return contract
+}
+
+// Returns a newly created account
+func NewAccount(address []byte, amount *big.Int) *StateObject {
+ account := &StateObject{address: address, Amount: amount, Nonce: 0}
+
+ return account
+}
+
+func NewStateObjectFromBytes(address, data []byte) *StateObject {
+ object := &StateObject{address: address}
+ object.RlpDecode(data)
+
+ return object
+}
+
+func (c *StateObject) Addr(addr []byte) *ethutil.Value {
+ return ethutil.NewValueFromBytes([]byte(c.state.trie.Get(string(addr))))
+}
+
+func (c *StateObject) SetAddr(addr []byte, value interface{}) {
+ c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
+}
+
+func (c *StateObject) State() *State {
+ return c.state
+}
+
+func (c *StateObject) GetMem(num *big.Int) *ethutil.Value {
+ nb := ethutil.BigToBytes(num, 256)
+
+ return c.Addr(nb)
+}
+
+func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
+ if int64(len(c.script)-1) < pc.Int64() {
+ return ethutil.NewValue(0)
+ }
+
+ return ethutil.NewValueFromBytes([]byte{c.script[pc.Int64()]})
+}
+
+func (c *StateObject) SetMem(num *big.Int, val *ethutil.Value) {
+ addr := ethutil.BigToBytes(num, 256)
+ c.state.trie.Update(string(addr), string(val.Encode()))
+}
+
+// Return the gas back to the origin. Used by the Virtual machine or Closures
+func (c *StateObject) ReturnGas(val *big.Int, state *State) {
+ c.AddAmount(val)
+}
+
+func (c *StateObject) AddAmount(amount *big.Int) {
+ c.Amount.Add(c.Amount, amount)
+}
+
+func (c *StateObject) SubAmount(amount *big.Int) {
+ c.Amount.Sub(c.Amount, amount)
+}
+
+func (c *StateObject) Address() []byte {
+ return c.address
+}
+
+func (c *StateObject) Script() []byte {
+ return c.script
+}
+
+func (c *StateObject) Init() []byte {
+ return c.initScript
+}
+
+func (c *StateObject) RlpEncode() []byte {
+ var root interface{}
+ if c.state != nil {
+ root = c.state.trie.Root
+ } else {
+ root = nil
+ }
+ return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, c.script})
+}
+
+func (c *StateObject) RlpDecode(data []byte) {
+ decoder := ethutil.NewValueFromBytes(data)
+
+ c.Amount = decoder.Get(0).BigInt()
+ c.Nonce = decoder.Get(1).Uint()
+ c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
+ c.script = decoder.Get(3).Bytes()
+}
+
+func MakeContract(tx *Transaction, state *State) *StateObject {
+ // Create contract if there's no recipient
+ if tx.IsContract() {
+ // FIXME
+ addr := tx.Hash()[12:]
+
+ value := tx.Value
+ contract := NewContract(addr, value, []byte(""))
+ state.UpdateStateObject(contract)
+
+ contract.script = tx.Data
+ contract.initScript = tx.Init
+
+ state.UpdateStateObject(contract)
+
+ return contract
+ }
+
+ return nil
+}
+
+// The cached state and state object cache are helpers which will give you somewhat
+// control over the nonce. When creating new transactions you're interested in the 'next'
+// nonce rather than the current nonce. This to avoid creating invalid-nonce transactions.
+type StateObjectCache struct {
+ cachedObjects map[string]*CachedStateObject
+}
+
+func NewStateObjectCache() *StateObjectCache {
+ return &StateObjectCache{cachedObjects: make(map[string]*CachedStateObject)}
+}
+
+func (s *StateObjectCache) Add(addr []byte, object *StateObject) *CachedStateObject {
+ state := &CachedStateObject{Nonce: object.Nonce, Object: object}
+ s.cachedObjects[string(addr)] = state
+
+ return state
+}
+
+func (s *StateObjectCache) Get(addr []byte) *CachedStateObject {
+ return s.cachedObjects[string(addr)]
+}
+
+type CachedStateObject struct {
+ Nonce uint64
+ Object *StateObject
+}
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index b359c9151..78044e840 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -23,8 +23,8 @@ type Transaction struct {
contractCreation bool
}
-func NewContractCreationTx(value, gasprice *big.Int, data []byte) *Transaction {
- return &Transaction{Value: value, Gasprice: gasprice, Data: data, contractCreation: true}
+func NewContractCreationTx(value, gasprice *big.Int, script []byte, init []byte) *Transaction {
+ return &Transaction{Value: value, Gasprice: gasprice, Data: script, Init: init, contractCreation: true}
}
func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []byte) *Transaction {
diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go
index 0bcfe6923..5cdda17e2 100644
--- a/ethchain/transaction_pool.go
+++ b/ethchain/transaction_pool.go
@@ -118,20 +118,20 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
// Send Tx to self
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
// Subtract the fee
- sender.Amount.Sub(sender.Amount, new(big.Int).Mul(TxFee, TxFeeRat))
+ sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
} else if toContract {
- sender.Amount.Sub(sender.Amount, new(big.Int).Mul(TxFee, TxFeeRat))
+ sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
} else {
// Subtract the amount from the senders account
- sender.Amount.Sub(sender.Amount, totAmount)
+ sender.SubAmount(totAmount)
// Add the amount to receivers account which should conclude this transaction
- receiver.Amount.Add(receiver.Amount, tx.Value)
+ receiver.AddAmount(tx.Value)
- block.state.UpdateAccount(tx.Recipient, receiver)
+ block.state.UpdateStateObject(receiver)
}
- block.state.UpdateAccount(tx.Sender(), sender)
+ block.state.UpdateStateObject(sender)
log.Printf("[TXPL] Processed Tx %x\n", tx.Hash())
@@ -151,7 +151,7 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
// Get the sender
accountState := pool.Ethereum.StateManager().GetAddrState(tx.Sender())
- sender := accountState.Account
+ sender := accountState.Object
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
// Make sure there's enough in the sender's account. Having insufficient