Blocktest fixed, Execution fixed
* Added new CreateAccount method which properly overwrites previous accounts (excluding balance) * Fixed block tests (100% success)
This commit is contained in:
parent
d3e86f9208
commit
0a554a1f27
@ -60,7 +60,7 @@ func runblocktest(ctx *cli.Context) {
|
|||||||
// insert the test blocks, which will execute all transactions
|
// insert the test blocks, which will execute all transactions
|
||||||
chain := ethereum.ChainManager()
|
chain := ethereum.ChainManager()
|
||||||
if err := chain.InsertChain(test.Blocks); err != nil {
|
if err := chain.InsertChain(test.Blocks); err != nil {
|
||||||
utils.Fatalf("Block Test load error: %v", err)
|
utils.Fatalf("Block Test load error: %v %T", err, err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Block Test chain loaded")
|
fmt.Println("Block Test chain loaded")
|
||||||
}
|
}
|
||||||
|
@ -326,8 +326,12 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
|
|||||||
return ValidationError(fmt.Sprintf("%v", err))
|
return ValidationError(fmt.Sprintf("%v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num := new(big.Int).Add(big.NewInt(8), uncle.Number)
|
||||||
|
num.Sub(num, block.Number())
|
||||||
|
|
||||||
r := new(big.Int)
|
r := new(big.Int)
|
||||||
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
|
r.Mul(BlockReward, num)
|
||||||
|
r.Div(r, big.NewInt(8))
|
||||||
|
|
||||||
statedb.AddBalance(uncle.Coinbase, r)
|
statedb.AddBalance(uncle.Coinbase, r)
|
||||||
|
|
||||||
|
@ -50,16 +50,29 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
|
|||||||
}
|
}
|
||||||
|
|
||||||
vsnapshot := env.State().Copy()
|
vsnapshot := env.State().Copy()
|
||||||
|
var createAccount bool
|
||||||
if self.address == nil {
|
if self.address == nil {
|
||||||
// Generate a new address
|
// Generate a new address
|
||||||
nonce := env.State().GetNonce(caller.Address())
|
nonce := env.State().GetNonce(caller.Address())
|
||||||
addr := crypto.CreateAddress(caller.Address(), nonce)
|
|
||||||
env.State().SetNonce(caller.Address(), nonce+1)
|
env.State().SetNonce(caller.Address(), nonce+1)
|
||||||
|
|
||||||
|
addr := crypto.CreateAddress(caller.Address(), nonce)
|
||||||
|
|
||||||
self.address = &addr
|
self.address = &addr
|
||||||
|
createAccount = true
|
||||||
}
|
}
|
||||||
snapshot := env.State().Copy()
|
snapshot := env.State().Copy()
|
||||||
|
|
||||||
from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(*self.address)
|
var (
|
||||||
|
from = env.State().GetStateObject(caller.Address())
|
||||||
|
to *state.StateObject
|
||||||
|
)
|
||||||
|
if createAccount {
|
||||||
|
to = env.State().CreateAccount(*self.address)
|
||||||
|
} else {
|
||||||
|
to = env.State().GetOrNewStateObject(*self.address)
|
||||||
|
}
|
||||||
|
|
||||||
err = env.Transfer(from, to, self.value)
|
err = env.Transfer(from, to, self.value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.State().Set(vsnapshot)
|
env.State().Set(vsnapshot)
|
||||||
|
@ -47,7 +47,7 @@ func GenesisBlock(db common.Database) *types.Block {
|
|||||||
statedb := state.New(genesis.Root(), db)
|
statedb := state.New(genesis.Root(), db)
|
||||||
for addr, account := range accounts {
|
for addr, account := range accounts {
|
||||||
codedAddr := common.Hex2Bytes(addr)
|
codedAddr := common.Hex2Bytes(addr)
|
||||||
accountState := statedb.GetAccount(common.BytesToAddress(codedAddr))
|
accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr))
|
||||||
accountState.SetBalance(common.Big(account.Balance))
|
accountState.SetBalance(common.Big(account.Balance))
|
||||||
accountState.SetCode(common.FromHex(account.Code))
|
accountState.SetCode(common.FromHex(account.Code))
|
||||||
statedb.UpdateStateObject(accountState)
|
statedb.UpdateStateObject(accountState)
|
||||||
|
@ -57,6 +57,10 @@ func (self *StateDB) Refund(address common.Address, gas *big.Int) {
|
|||||||
self.refund[addr].Add(self.refund[addr], gas)
|
self.refund[addr].Add(self.refund[addr], gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GETTERS
|
||||||
|
*/
|
||||||
|
|
||||||
// Retrieve the balance from the given address or 0 if object not found
|
// Retrieve the balance from the given address or 0 if object not found
|
||||||
func (self *StateDB) GetBalance(addr common.Address) *big.Int {
|
func (self *StateDB) GetBalance(addr common.Address) *big.Int {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
@ -67,13 +71,6 @@ func (self *StateDB) GetBalance(addr common.Address) *big.Int {
|
|||||||
return common.Big0
|
return common.Big0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
|
|
||||||
stateObject := self.GetStateObject(addr)
|
|
||||||
if stateObject != nil {
|
|
||||||
stateObject.AddBalance(amount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *StateDB) GetNonce(addr common.Address) uint64 {
|
func (self *StateDB) GetNonce(addr common.Address) uint64 {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
@ -101,22 +98,41 @@ func (self *StateDB) GetState(a common.Address, b common.Hash) []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
|
func (self *StateDB) IsDeleted(addr common.Address) bool {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
|
if stateObject != nil {
|
||||||
|
return stateObject.remove
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SETTERS
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
|
||||||
|
stateObject := self.GetOrNewStateObject(addr)
|
||||||
|
if stateObject != nil {
|
||||||
|
stateObject.AddBalance(amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
|
||||||
|
stateObject := self.GetOrNewStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.SetNonce(nonce)
|
stateObject.SetNonce(nonce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) SetCode(addr common.Address, code []byte) {
|
func (self *StateDB) SetCode(addr common.Address, code []byte) {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetOrNewStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.SetCode(code)
|
stateObject.SetCode(code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) SetState(addr common.Address, key common.Hash, value interface{}) {
|
func (self *StateDB) SetState(addr common.Address, key common.Hash, value interface{}) {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetOrNewStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.SetState(key, common.NewValue(value))
|
stateObject.SetState(key, common.NewValue(value))
|
||||||
}
|
}
|
||||||
@ -134,14 +150,6 @@ func (self *StateDB) Delete(addr common.Address) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) IsDeleted(addr common.Address) bool {
|
|
||||||
stateObject := self.GetStateObject(addr)
|
|
||||||
if stateObject != nil {
|
|
||||||
return stateObject.remove
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setting, updating & deleting state object methods
|
// Setting, updating & deleting state object methods
|
||||||
//
|
//
|
||||||
@ -194,16 +202,14 @@ func (self *StateDB) SetStateObject(object *StateObject) {
|
|||||||
func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
|
func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
|
||||||
stateObject := self.GetStateObject(addr)
|
stateObject := self.GetStateObject(addr)
|
||||||
if stateObject == nil {
|
if stateObject == nil {
|
||||||
stateObject = self.NewStateObject(addr)
|
stateObject = self.CreateAccount(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return stateObject
|
return stateObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a state object whether it exist in the trie or not
|
// NewStateObject create a state object whether it exist in the trie or not
|
||||||
func (self *StateDB) NewStateObject(addr common.Address) *StateObject {
|
func (self *StateDB) newStateObject(addr common.Address) *StateObject {
|
||||||
//addr = common.Address(addr)
|
|
||||||
|
|
||||||
statelogger.Debugf("(+) %x\n", addr)
|
statelogger.Debugf("(+) %x\n", addr)
|
||||||
|
|
||||||
stateObject := NewStateObject(addr, self.db)
|
stateObject := NewStateObject(addr, self.db)
|
||||||
@ -212,9 +218,19 @@ func (self *StateDB) NewStateObject(addr common.Address) *StateObject {
|
|||||||
return stateObject
|
return stateObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated
|
// Creates creates a new state object and takes ownership. This is different from "NewStateObject"
|
||||||
func (self *StateDB) GetAccount(addr common.Address) *StateObject {
|
func (self *StateDB) CreateAccount(addr common.Address) *StateObject {
|
||||||
return self.GetOrNewStateObject(addr)
|
// Get previous (if any)
|
||||||
|
so := self.GetStateObject(addr)
|
||||||
|
// Create a new one
|
||||||
|
newSo := self.newStateObject(addr)
|
||||||
|
|
||||||
|
// If it existed set the balance to the new account
|
||||||
|
if so != nil {
|
||||||
|
newSo.balance = so.balance
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSo
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -183,15 +183,16 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pay data gas
|
// Pay data gas
|
||||||
var dgas int64
|
dgas := new(big.Int)
|
||||||
for _, byt := range self.data {
|
for _, byt := range self.data {
|
||||||
if byt != 0 {
|
if byt != 0 {
|
||||||
dgas += vm.GasTxDataNonzeroByte.Int64()
|
dgas.Add(dgas, vm.GasTxDataNonzeroByte)
|
||||||
} else {
|
} else {
|
||||||
dgas += vm.GasTxDataZeroByte.Int64()
|
dgas.Add(dgas, vm.GasTxDataZeroByte)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = self.UseGas(big.NewInt(dgas)); err != nil {
|
|
||||||
|
if err = self.UseGas(dgas); err != nil {
|
||||||
return nil, nil, InvalidTxError(err)
|
return nil, nil, InvalidTxError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,7 +857,8 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
|
|||||||
quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom)
|
quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom)
|
||||||
newTotalFee := new(big.Int).Add(linCoef, quadCoef)
|
newTotalFee := new(big.Int).Add(linCoef, quadCoef)
|
||||||
|
|
||||||
gas.Add(gas, new(big.Int).Sub(newTotalFee, oldTotalFee))
|
fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
|
||||||
|
gas.Add(gas, fee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -69,7 +68,7 @@ type btBlock struct {
|
|||||||
BlockHeader *btHeader
|
BlockHeader *btHeader
|
||||||
Rlp string
|
Rlp string
|
||||||
Transactions []btTransaction
|
Transactions []btTransaction
|
||||||
UncleHeaders []string
|
UncleHeaders []*btHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockTest struct {
|
type BlockTest struct {
|
||||||
@ -106,13 +105,13 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
|
|||||||
balance, _ := new(big.Int).SetString(acct.Balance, 0)
|
balance, _ := new(big.Int).SetString(acct.Balance, 0)
|
||||||
nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
|
nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
|
||||||
|
|
||||||
obj := statedb.NewStateObject(common.HexToAddress(addrString))
|
obj := statedb.CreateAccount(common.HexToAddress(addrString))
|
||||||
obj.SetCode(code)
|
obj.SetCode(code)
|
||||||
obj.SetBalance(balance)
|
obj.SetBalance(balance)
|
||||||
obj.SetNonce(nonce)
|
obj.SetNonce(nonce)
|
||||||
// for k, v := range acct.Storage {
|
for k, v := range acct.Storage {
|
||||||
// obj.SetState(k, v)
|
statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.FromHex(v))
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
// sync objects to trie
|
// sync objects to trie
|
||||||
statedb.Update(nil)
|
statedb.Update(nil)
|
||||||
@ -120,7 +119,7 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
|
|||||||
statedb.Sync()
|
statedb.Sync()
|
||||||
|
|
||||||
if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) {
|
if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) {
|
||||||
return nil, errors.New("computed state root does not match genesis block")
|
return nil, fmt.Errorf("computed state root does not match genesis block %x %x", t.Genesis.Root().Bytes()[:4], statedb.Root().Bytes()[:4])
|
||||||
}
|
}
|
||||||
return statedb, nil
|
return statedb, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user