Added address to account and contract

Contract and account now both have an address field or method for the
sake of simplicity.
This commit is contained in:
obscuren 2014-03-20 23:38:16 +01:00
parent 7705b23f24
commit f567f89b99
5 changed files with 38 additions and 26 deletions

View File

@ -15,6 +15,7 @@ type ClosureBody interface {
Callee Callee
ethutil.RlpEncodable ethutil.RlpEncodable
GetMem(int64) *ethutil.Value GetMem(int64) *ethutil.Value
Address() []byte
} }
// Basic inline closure object which implement the 'closure' interface // Basic inline closure object which implement the 'closure' interface

View File

@ -9,26 +9,22 @@ type Contract struct {
Amount *big.Int Amount *big.Int
Nonce uint64 Nonce uint64
//state *ethutil.Trie //state *ethutil.Trie
state *State state *State
address []byte
} }
func NewContract(Amount *big.Int, root []byte) *Contract { func NewContract(address []byte, Amount *big.Int, root []byte) *Contract {
contract := &Contract{Amount: Amount, Nonce: 0} contract := &Contract{address: address, Amount: Amount, Nonce: 0}
contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, string(root))) contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, string(root)))
return contract return contract
} }
func (c *Contract) RlpEncode() []byte { func NewContractFromBytes(address, data []byte) *Contract {
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root}) contract := &Contract{address: address}
} contract.RlpDecode(data)
func (c *Contract) RlpDecode(data []byte) { return contract
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()))
} }
func (c *Contract) Addr(addr []byte) *ethutil.Value { func (c *Contract) Addr(addr []byte) *ethutil.Value {
@ -54,13 +50,29 @@ func (c *Contract) ReturnGas(val *big.Int, state *State) {
c.Amount.Add(c.Amount, val) c.Amount.Add(c.Amount, val)
} }
func (c *Contract) Address() []byte {
return c.address
}
func (c *Contract) RlpEncode() []byte {
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root})
}
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()))
}
func MakeContract(tx *Transaction, state *State) *Contract { func MakeContract(tx *Transaction, state *State) *Contract {
// Create contract if there's no recipient // Create contract if there's no recipient
if tx.IsContract() { if tx.IsContract() {
addr := tx.Hash()[12:] addr := tx.Hash()[12:]
value := tx.Value value := tx.Value
contract := NewContract(value, []byte("")) contract := NewContract(addr, value, []byte(""))
state.trie.Update(string(addr), string(contract.RlpEncode())) state.trie.Update(string(addr), string(contract.RlpEncode()))
for i, val := range tx.Data { for i, val := range tx.Data {
if len(val) > 0 { if len(val) > 0 {

View File

@ -63,8 +63,7 @@ func (s *State) GetContract(addr []byte) *Contract {
} }
// build contract // build contract
contract := &Contract{} contract := NewContractFromBytes(addr, []byte(data))
contract.RlpDecode([]byte(data))
// Check if there's a cached state for this contract // Check if there's a cached state for this contract
cachedState := s.states[string(addr)] cachedState := s.states[string(addr)]
@ -78,7 +77,9 @@ func (s *State) GetContract(addr []byte) *Contract {
return contract return contract
} }
func (s *State) UpdateContract(addr []byte, contract *Contract) { func (s *State) UpdateContract(contract *Contract) {
addr := contract.Address()
s.states[string(addr)] = contract.state s.states[string(addr)] = contract.state
s.trie.Update(string(addr), string(contract.RlpEncode())) s.trie.Update(string(addr), string(contract.RlpEncode()))
} }

View File

@ -23,14 +23,12 @@ type Vm struct {
} }
type RuntimeVars struct { type RuntimeVars struct {
address []byte origin []byte
blockNumber uint64 blockNumber uint64
sender []byte
prevHash []byte prevHash []byte
coinbase []byte coinbase []byte
time int64 time int64
diff *big.Int diff *big.Int
txValue *big.Int
txData []string txData []string
} }
@ -108,6 +106,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
closure := NewClosure(closure, contract, vm.state, gas, value) closure := NewClosure(closure, contract, vm.state, gas, value)
// Executer the closure and get the return value (if any) // Executer the closure and get the return value (if any)
ret := closure.Call(vm, nil) ret := closure.Call(vm, nil)
mem.Set(retOffset.Int64(), retSize.Int64(), ret) mem.Set(retOffset.Int64(), retSize.Int64(), ret)
case oRETURN: case oRETURN:
size, offset := stack.Popn() size, offset := stack.Popn()
@ -501,7 +500,7 @@ func makeInlineTx(addr []byte, value, from, length *big.Int, contract *Contract,
tx := NewTransaction(addr, value, dataItems) tx := NewTransaction(addr, value, dataItems)
if tx.IsContract() { if tx.IsContract() {
contract := MakeContract(tx, state) contract := MakeContract(tx, state)
state.UpdateContract(tx.Hash()[12:], contract) state.UpdateContract(contract)
} else { } else {
account := state.GetAccount(tx.Recipient) account := state.GetAccount(tx.Recipient)
account.Amount.Add(account.Amount, tx.Value) account.Amount.Add(account.Amount, tx.Value)

View File

@ -130,7 +130,7 @@ func TestRun3(t *testing.T) {
addr := tx.Hash()[12:] addr := tx.Hash()[12:]
fmt.Printf("addr contract %x\n", addr) fmt.Printf("addr contract %x\n", addr)
contract := MakeContract(tx, state) contract := MakeContract(tx, state)
state.UpdateContract(addr, contract) state.UpdateContract(contract)
callerScript := Compile([]string{ callerScript := Compile([]string{
"PUSH", "62", // ret size "PUSH", "62", // ret size
@ -143,21 +143,20 @@ func TestRun3(t *testing.T) {
"CALL", "CALL",
}) })
callerTx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), callerScript) callerTx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), callerScript)
callerAddr := callerTx.Hash()[12:]
// Contract addr as test address
account := NewAccount(ContractAddr, big.NewInt(10000000)) account := NewAccount(ContractAddr, big.NewInt(10000000))
callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int)) callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))
vm := NewVm(state, RuntimeVars{ vm := NewVm(state, RuntimeVars{
address: callerAddr, origin: account.Address,
blockNumber: 1, blockNumber: 1,
sender: ethutil.FromHex("cd1722f3947def4cf144679da39c4c32bdc35681"),
prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"), prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"), coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
time: 1, time: 1,
diff: big.NewInt(256), diff: big.NewInt(256),
txValue: big.NewInt(10000), // XXX Tx data? Could be just an argument to the closure instead
txData: nil, txData: nil,
}) })
callerClosure.Call(vm, nil) callerClosure.Call(vm, nil)
} }