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
ethutil.RlpEncodable
GetMem(int64) *ethutil.Value
Address() []byte
}
// Basic inline closure object which implement the 'closure' interface

View File

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

View File

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

View File

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

View File

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