Commit 118ad22e authored by Taylor Gerring's avatar Taylor Gerring

Merge branch 'develop' into rpcfabian

parents 81de8ed0 79828531
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<title>JevCoin</title> <title>JevCoin</title>
<head> <head>
<script type="text/javascript" src="../ext/bignumber.min.js"></script> <script type="text/javascript" src="../ext/bignumber.min.js"></script>
<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> <script type="text/javascript" src="../ext/ethereum.js/dist/ethereum-light.min.js"></script>
</head> </head>
<body> <body>
......
Subproject commit 2536888f817a1a15b05dab4727d30f73d6763f07 Subproject commit 31e046dbecea51d3b99b21f3e7e60ddfb6c39304
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"gopkg.in/fatih/set.v0" "gopkg.in/fatih/set.v0"
...@@ -83,7 +84,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated ...@@ -83,7 +84,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
} }
// Update the state with pending changes // Update the state with pending changes
statedb.Update(nil) statedb.Update()
cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas)) cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas))
receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative) receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative)
...@@ -210,14 +211,16 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big ...@@ -210,14 +211,16 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
return return
} }
// Accumulate static rewards; block reward, uncle's and uncle inclusion. // Verify uncles
if err = sm.AccumulateRewards(state, block, parent); err != nil { if err = sm.VerifyUncles(state, block, parent); err != nil {
return return
} }
// Accumulate static rewards; block reward, uncle's and uncle inclusion.
AccumulateRewards(state, block)
// Commit state objects/accounts to a temporary trie (does not save) // Commit state objects/accounts to a temporary trie (does not save)
// used to calculate the state root. // used to calculate the state root.
state.Update(common.Big0) state.Update()
if header.Root != state.Root() { if header.Root != state.Root() {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
return return
...@@ -252,7 +255,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big ...@@ -252,7 +255,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// an uncle or anything that isn't on the current block chain. // an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult) // Validation validates easy over difficult (dagger takes longer time = difficult)
func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
if len(block.Extra) > 1024 { if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra)) return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
} }
...@@ -261,13 +264,11 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { ...@@ -261,13 +264,11 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
} }
// TODO: use use minGasLimit and gasLimitBoundDivisor from // block.gasLimit - parent.gasLimit <= parent.gasLimit / GasLimitBoundDivisor
// https://github.com/ethereum/common/blob/master/params.json
// block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024
a := new(big.Int).Sub(block.GasLimit, parent.GasLimit) a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
a.Abs(a) a.Abs(a)
b := new(big.Int).Div(parent.GasLimit, big.NewInt(1024)) b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor)
if !(a.Cmp(b) < 0) { if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) {
return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b) return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
} }
...@@ -291,9 +292,27 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { ...@@ -291,9 +292,27 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return nil return nil
} }
func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, parent *types.Block) error { func AccumulateRewards(statedb *state.StateDB, block *types.Block) {
reward := new(big.Int).Set(BlockReward) reward := new(big.Int).Set(BlockReward)
for _, uncle := range block.Uncles() {
num := new(big.Int).Add(big.NewInt(8), uncle.Number)
num.Sub(num, block.Number())
r := new(big.Int)
r.Mul(BlockReward, num)
r.Div(r, big.NewInt(8))
statedb.AddBalance(uncle.Coinbase, r)
reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
}
// Get the account associated with the coinbase
statedb.AddBalance(block.Header().Coinbase, reward)
}
func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error {
ancestors := set.New() ancestors := set.New()
uncles := set.New() uncles := set.New()
ancestorHeaders := make(map[common.Hash]*types.Header) ancestorHeaders := make(map[common.Hash]*types.Header)
...@@ -327,21 +346,8 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren ...@@ -327,21 +346,8 @@ 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.Mul(BlockReward, num)
r.Div(r, big.NewInt(8))
statedb.AddBalance(uncle.Coinbase, r)
reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
} }
// Get the account associated with the coinbase
statedb.AddBalance(block.Header().Coinbase, reward)
return nil return nil
} }
...@@ -358,7 +364,6 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro ...@@ -358,7 +364,6 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
) )
sm.TransitionState(state, parent, block, true) sm.TransitionState(state, parent, block, true)
sm.AccumulateRewards(state, block, parent)
return state.Logs(), nil return state.Logs(), nil
} }
......
...@@ -5,10 +5,10 @@ import ( ...@@ -5,10 +5,10 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/core/state"
) )
// So we can generate blocks easily // So we can generate blocks easily
...@@ -81,7 +81,7 @@ func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Datab ...@@ -81,7 +81,7 @@ func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Datab
cbase := state.GetOrNewStateObject(addr) cbase := state.GetOrNewStateObject(addr)
cbase.SetGasPool(CalcGasLimit(parent, block)) cbase.SetGasPool(CalcGasLimit(parent, block))
cbase.AddBalance(BlockReward) cbase.AddBalance(BlockReward)
state.Update(common.Big0) state.Update()
block.SetRoot(state.Root()) block.SetRoot(state.Root())
return block return block
} }
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
...@@ -32,18 +33,15 @@ type StateQuery interface { ...@@ -32,18 +33,15 @@ type StateQuery interface {
func CalcDifficulty(block, parent *types.Header) *big.Int { func CalcDifficulty(block, parent *types.Header) *big.Int {
diff := new(big.Int) diff := new(big.Int)
diffBoundDiv := big.NewInt(2048) adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
min := big.NewInt(131072) if big.NewInt(int64(block.Time)-int64(parent.Time)).Cmp(params.DurationLimit) < 0 {
adjust := new(big.Int).Div(parent.Difficulty, diffBoundDiv)
if (block.Time - parent.Time) < 8 {
diff.Add(parent.Difficulty, adjust) diff.Add(parent.Difficulty, adjust)
} else { } else {
diff.Sub(parent.Difficulty, adjust) diff.Sub(parent.Difficulty, adjust)
} }
if diff.Cmp(min) < 0 { if diff.Cmp(params.MinimumDifficulty) < 0 {
return min return params.MinimumDifficulty
} }
return diff return diff
...@@ -76,7 +74,7 @@ func CalcGasLimit(parent, block *types.Block) *big.Int { ...@@ -76,7 +74,7 @@ func CalcGasLimit(parent, block *types.Block) *big.Int {
result := new(big.Int).Add(previous, curInt) result := new(big.Int).Add(previous, curInt)
result.Div(result, big.NewInt(1024)) result.Div(result, big.NewInt(1024))
return common.BigMax(GenesisGasLimit, result) return common.BigMax(params.GenesisGasLimit, result)
} }
type ChainManager struct { type ChainManager struct {
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
) )
type Execution struct { type Execution struct {
...@@ -43,7 +44,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm. ...@@ -43,7 +44,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
env := self.env env := self.env
evm := self.evm evm := self.evm
if env.Depth() == vm.MaxCallDepth { if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(self.Gas, self.price) caller.ReturnGas(self.Gas, self.price)
return nil, vm.DepthError{} return nil, vm.DepthError{}
......
...@@ -3,12 +3,12 @@ package core ...@@ -3,12 +3,12 @@ package core
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/big"
"os" "os"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
) )
/* /*
...@@ -18,13 +18,11 @@ import ( ...@@ -18,13 +18,11 @@ import (
var ZeroHash256 = make([]byte, 32) var ZeroHash256 = make([]byte, 32)
var ZeroHash160 = make([]byte, 20) var ZeroHash160 = make([]byte, 20)
var ZeroHash512 = make([]byte, 64) var ZeroHash512 = make([]byte, 64)
var GenesisDiff = big.NewInt(131072)
var GenesisGasLimit = big.NewInt(3141592)
func GenesisBlock(db common.Database) *types.Block { func GenesisBlock(db common.Database) *types.Block {
genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, GenesisDiff, 42, "") genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, params.GenesisDifficulty, 42, "")
genesis.Header().Number = common.Big0 genesis.Header().Number = common.Big0
genesis.Header().GasLimit = GenesisGasLimit genesis.Header().GasLimit = params.GenesisGasLimit
genesis.Header().GasUsed = common.Big0 genesis.Header().GasUsed = common.Big0
genesis.Header().Time = 0 genesis.Header().Time = 0
......
...@@ -72,7 +72,7 @@ func TestNull(t *testing.T) { ...@@ -72,7 +72,7 @@ func TestNull(t *testing.T) {
//value := common.FromHex("0x823140710bf13990e4500136726d8b55") //value := common.FromHex("0x823140710bf13990e4500136726d8b55")
value := make([]byte, 16) value := make([]byte, 16)
state.SetState(address, common.Hash{}, value) state.SetState(address, common.Hash{}, value)
state.Update(nil) state.Update()
state.Sync() state.Sync()
value = state.GetState(address, common.Hash{}) value = state.GetState(address, common.Hash{})
} }
......
...@@ -316,7 +316,7 @@ func (self *StateDB) Refunds() map[string]*big.Int { ...@@ -316,7 +316,7 @@ func (self *StateDB) Refunds() map[string]*big.Int {
return self.refund return self.refund
} }
func (self *StateDB) Update(gasUsed *big.Int) { func (self *StateDB) Update() {
self.refund = make(map[string]*big.Int) self.refund = make(map[string]*big.Int)
for _, stateObject := range self.stateObjects { for _, stateObject := range self.stateObjects {
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
) )
const tryJit = false const tryJit = false
...@@ -178,7 +179,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er ...@@ -178,7 +179,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
) )
// Transaction gas // Transaction gas
if err = self.UseGas(vm.GasTx); err != nil { if err = self.UseGas(params.TxGas); err != nil {
return nil, nil, InvalidTxError(err) return nil, nil, InvalidTxError(err)
} }
...@@ -186,9 +187,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er ...@@ -186,9 +187,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
dgas := new(big.Int) dgas := new(big.Int)
for _, byt := range self.data { for _, byt := range self.data {
if byt != 0 { if byt != 0 {
dgas.Add(dgas, vm.GasTxDataNonzeroByte) dgas.Add(dgas, params.TxDataNonZeroGas)
} else { } else {
dgas.Add(dgas, vm.GasTxDataZeroByte) dgas.Add(dgas, params.TxDataZeroGas)
} }
} }
...@@ -202,7 +203,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er ...@@ -202,7 +203,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value) ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value)
if err == nil { if err == nil {
dataGas := big.NewInt(int64(len(ret))) dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, vm.GasCreateByte) dataGas.Mul(dataGas, params.CreateDataGas)
if err := self.UseGas(dataGas); err == nil { if err := self.UseGas(dataGas); err == nil {
ref.SetCode(ret) ref.SetCode(ret)
} else { } else {
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
) )
type Address interface { type Address interface {
...@@ -27,28 +28,28 @@ func PrecompiledContracts() map[string]*PrecompiledAccount { ...@@ -27,28 +28,28 @@ func PrecompiledContracts() map[string]*PrecompiledAccount {
return map[string]*PrecompiledAccount{ return map[string]*PrecompiledAccount{
// ECRECOVER // ECRECOVER
string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int { string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int {
return GasEcrecover return params.EcrecoverGas
}, ecrecoverFunc}, }, ecrecoverFunc},
// SHA256 // SHA256
string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int { string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32) n := big.NewInt(int64(l+31) / 32)
n.Mul(n, GasSha256Word) n.Mul(n, params.Sha256WordGas)
return n.Add(n, GasSha256Base) return n.Add(n, params.Sha256Gas)
}, sha256Func}, }, sha256Func},
// RIPEMD160 // RIPEMD160
string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int { string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32) n := big.NewInt(int64(l+31) / 32)
n.Mul(n, GasRipemdWord) n.Mul(n, params.Ripemd160WordGas)
return n.Add(n, GasRipemdBase) return n.Add(n, params.Ripemd160Gas)
}, ripemd160Func}, }, ripemd160Func},
string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int { string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32) n := big.NewInt(int64(l+31) / 32)
n.Mul(n, GasIdentityWord) n.Mul(n, params.IdentityWordGas)
return n.Add(n, GasIdentityBase) return n.Add(n, params.IdentityGas)
}, memCpy}, }, memCpy},
} }
} }
......
...@@ -20,8 +20,6 @@ const ( ...@@ -20,8 +20,6 @@ const (
JitVmTy JitVmTy
MaxVmTy MaxVmTy
MaxCallDepth = 1025
LogTyPretty byte = 0x1 LogTyPretty byte = 0x1
LogTyDiff byte = 0x2 LogTyDiff byte = 0x2
) )
......
...@@ -2,6 +2,7 @@ package vm ...@@ -2,6 +2,7 @@ package vm
import ( import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/params"
"math/big" "math/big"
) )
...@@ -42,7 +43,7 @@ func IsStack(err error) bool { ...@@ -42,7 +43,7 @@ func IsStack(err error) bool {
type DepthError struct{} type DepthError struct{}
func (self DepthError) Error() string { func (self DepthError) Error() string {
return fmt.Sprintf("Max call depth exceeded (%d)", MaxCallDepth) return fmt.Sprintf("Max call depth exceeded (%d)", params.CallCreateDepth)
} }
func IsDepthErr(err error) bool { func IsDepthErr(err error) bool {
......
...@@ -2,6 +2,7 @@ package vm ...@@ -2,6 +2,7 @@ package vm
import ( import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/params"
"math/big" "math/big"
) )
...@@ -13,45 +14,10 @@ var ( ...@@ -13,45 +14,10 @@ var (
GasSlowStep = big.NewInt(10) GasSlowStep = big.NewInt(10)
GasExtStep = big.NewInt(20) GasExtStep = big.NewInt(20)
GasStorageGet = big.NewInt(50) GasReturn = big.NewInt(0)
GasStorageAdd = big.NewInt(20000) GasStop = big.NewInt(0)
GasStorageMod = big.NewInt(5000)
GasLogBase = big.NewInt(375)
GasLogTopic = big.NewInt(375)
GasLogByte = big.NewInt(8)
GasCreate = big.NewInt(32000)
GasCreateByte = big.NewInt(200)
GasCall = big.NewInt(40)
GasCallValueTransfer = big.NewInt(9000)
GasStipend = big.NewInt(2300)
GasCallNewAccount = big.NewInt(25000)
GasReturn = big.NewInt(0)
GasStop = big.NewInt(0)
GasJumpDest = big.NewInt(1)
RefundStorage = big.NewInt(15000) GasContractByte = big.NewInt(200)
RefundSuicide = big.NewInt(24000)
GasMemWord = big.NewInt(3)
GasQuadCoeffDenom = big.NewInt(512)
GasContractByte = big.NewInt(200)
GasTransaction = big.NewInt(21000)
GasTxDataNonzeroByte = big.NewInt(68)
GasTxDataZeroByte = big.NewInt(4)
GasTx = big.NewInt(21000)
GasExp = big.NewInt(10)
GasExpByte = big.NewInt(10)
GasSha3Base = big.NewInt(30)
GasSha3Word = big.NewInt(6)
GasSha256Base = big.NewInt(60)
GasSha256Word = big.NewInt(12)
GasRipemdBase = big.NewInt(600)
GasRipemdWord = big.NewInt(12)
GasEcrecover = big.NewInt(3000)
GasIdentityBase = big.NewInt(15)
GasIdentityWord = big.NewInt(3)
GasCopyWord = big.NewInt(3)
) )
func baseCheck(op OpCode, stack *stack, gas *big.Int) error { func baseCheck(op OpCode, stack *stack, gas *big.Int) error {
...@@ -71,8 +37,8 @@ func baseCheck(op OpCode, stack *stack, gas *big.Int) error { ...@@ -71,8 +37,8 @@ func baseCheck(op OpCode, stack *stack, gas *big.Int) error {
return err return err
} }
if r.stackPush && len(stack.data)-r.stackPop+1 > 1024 { if r.stackPush && len(stack.data)-r.stackPop+1 > int(params.StackLimit.Int64()) {
return fmt.Errorf("stack limit reached (%d)", maxStack) return fmt.Errorf("stack limit reached (%d)", params.StackLimit.Int64())
} }
gas.Add(gas, r.gas) gas.Add(gas, r.gas)
...@@ -142,16 +108,16 @@ var _baseCheck = map[OpCode]req{ ...@@ -142,16 +108,16 @@ var _baseCheck = map[OpCode]req{
MSIZE: {0, GasQuickStep, true}, MSIZE: {0, GasQuickStep, true},
GAS: {0, GasQuickStep, true}, GAS: {0, GasQuickStep, true},
BLOCKHASH: {1, GasExtStep, true}, BLOCKHASH: {1, GasExtStep, true},
BALANCE: {0, GasExtStep, true}, BALANCE: {1, GasExtStep, true},
EXTCODESIZE: {1, GasExtStep, true}, EXTCODESIZE: {1, GasExtStep, true},
EXTCODECOPY: {4, GasExtStep, false}, EXTCODECOPY: {4, GasExtStep, false},
SLOAD: {1, GasStorageGet, true}, SLOAD: {1, params.SloadGas, true},
SSTORE: {2, Zero, false}, SSTORE: {2, Zero, false},
SHA3: {1, GasSha3Base, true}, SHA3: {2, params.Sha3Gas, true},
CREATE: {3, GasCreate, true}, CREATE: {3, params.CreateGas, true},
CALL: {7, GasCall, true}, CALL: {7, params.CallGas, true},
CALLCODE: {7, GasCall, true}, CALLCODE: {7, params.CallGas, true},
JUMPDEST: {0, GasJumpDest, false}, JUMPDEST: {0, params.JumpdestGas, false},
SUICIDE: {1, Zero, false}, SUICIDE: {1, Zero, false},
RETURN: {2, Zero, false}, RETURN: {2, Zero, false},
PUSH1: {0, GasFastestStep, true}, PUSH1: {0, GasFastestStep, true},
......
...@@ -5,8 +5,6 @@ import ( ...@@ -5,8 +5,6 @@ import (
"math/big" "math/big"
) )
const maxStack = 1024
func newStack() *stack { func newStack() *stack {
return &stack{} return &stack{}
} }
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
) )
type Vm struct { type Vm struct {
...@@ -640,7 +641,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) { ...@@ -640,7 +641,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
} else { } else {
// gas < len(ret) * CreateDataGas == NO_CODE // gas < len(ret) * CreateDataGas == NO_CODE
dataGas := big.NewInt(int64(len(ret))) dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, GasCreateByte) dataGas.Mul(dataGas, params.CreateDataGas)
if context.UseGas(dataGas) { if context.UseGas(dataGas) {
ref.SetCode(ret) ref.SetCode(ret)
} }
...@@ -667,7 +668,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) { ...@@ -667,7 +668,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
args := mem.Get(inOffset.Int64(), inSize.Int64()) args := mem.Get(inOffset.Int64(), inSize.Int64())
if len(value.Bytes()) > 0 { if len(value.Bytes()) > 0 {
gas.Add(gas, GasStipend) gas.Add(gas, params.CallStipend)
} }
var ( var (
...@@ -759,13 +760,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -759,13 +760,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1] mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
gas.Add(gas, GasLogBase) gas.Add(gas, params.LogGas)
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic)) gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
gas.Add(gas, new(big.Int).Mul(mSize, GasLogByte)) gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
newMemSize = calcMemSize(mStart, mSize) newMemSize = calcMemSize(mStart, mSize)
case EXP: case EXP:
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), GasExpByte)) gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
case SSTORE: case SSTORE:
err := stack.require(2) err := stack.require(2)
if err != nil { if err != nil {
...@@ -777,19 +778,19 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -777,19 +778,19 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
val := statedb.GetState(context.Address(), common.BigToHash(x)) val := statedb.GetState(context.Address(), common.BigToHash(x))
if len(val) == 0 && len(y.Bytes()) > 0 { if len(val) == 0 && len(y.Bytes()) > 0 {
// 0 => non 0 // 0 => non 0
g = GasStorageAdd g = params.SstoreSetGas
} else if len(val) > 0 && len(y.Bytes()) == 0 { } else if len(val) > 0 && len(y.Bytes()) == 0 {
statedb.Refund(self.env.Origin(), RefundStorage) statedb.Refund(self.env.Origin(), params.SstoreRefundGas)
g = GasStorageMod g = params.SstoreClearGas
} else { } else {
// non 0 => non 0 (or 0 => 0) // non 0 => non 0 (or 0 => 0)
g = GasStorageMod g = params.SstoreClearGas
} }
gas.Set(g) gas.Set(g)
case SUICIDE: case SUICIDE:
if !statedb.IsDeleted(context.Address()) { if !statedb.IsDeleted(context.Address()) {
statedb.Refund(self.env.Origin(), RefundSuicide) statedb.Refund(self.env.Origin(), params.SuicideRefundGas)
} }
case MLOAD: case MLOAD:
newMemSize = calcMemSize(stack.peek(), u256(32)) newMemSize = calcMemSize(stack.peek(), u256(32))
...@@ -803,22 +804,22 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -803,22 +804,22 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
words := toWordSize(stack.data[stack.len()-2]) words := toWordSize(stack.data[stack.len()-2])
gas.Add(gas, words.Mul(words, GasSha3Word)) gas.Add(gas, words.Mul(words, params.Sha3WordGas))
case CALLDATACOPY: case CALLDATACOPY:
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
words := toWordSize(stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3])
gas.Add(gas, words.Mul(words, GasCopyWord)) gas.Add(gas, words.Mul(words, params.CopyGas))
case CODECOPY: case CODECOPY:
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
words := toWordSize(stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3])
gas.Add(gas, words.Mul(words, GasCopyWord)) gas.Add(gas, words.Mul(words, params.CopyGas))
case EXTCODECOPY: case EXTCODECOPY:
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4]) newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
words := toWordSize(stack.data[stack.len()-4]) words := toWordSize(stack.data[stack.len()-4])
gas.Add(gas, words.Mul(words, GasCopyWord)) gas.Add(gas, words.Mul(words, params.CopyGas))
case CREATE: case CREATE:
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3]) newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
...@@ -827,12 +828,12 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -827,12 +828,12 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
if op == CALL { if op == CALL {
if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil { if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
gas.Add(gas, GasCallNewAccount) gas.Add(gas, params.CallNewAccountGas)
} }
} }
if len(stack.data[stack.len()-3].Bytes()) > 0 { if len(stack.data[stack.len()-3].Bytes()) > 0 {
gas.Add(gas, GasCallValueTransfer) gas.Add(gas, params.CallValueTransferGas)
} }
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7]) x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
...@@ -848,13 +849,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -848,13 +849,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
oldSize := toWordSize(big.NewInt(int64(mem.Len()))) oldSize := toWordSize(big.NewInt(int64(mem.Len())))
pow := new(big.Int).Exp(oldSize, common.Big2, Zero) pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
linCoef := new(big.Int).Mul(oldSize, GasMemWord) linCoef := new(big.Int).Mul(oldSize, params.MemoryGas)
quadCoef := new(big.Int).Div(pow, GasQuadCoeffDenom) quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
oldTotalFee := new(big.Int).Add(linCoef, quadCoef) oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
pow.Exp(newMemSizeWords, common.Big2, Zero) pow.Exp(newMemSizeWords, common.Big2, Zero)
linCoef = new(big.Int).Mul(newMemSizeWords, GasMemWord) linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas)
quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom) quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv)
newTotalFee := new(big.Int).Add(linCoef, quadCoef) newTotalFee := new(big.Int).Add(linCoef, quadCoef)
fee := new(big.Int).Sub(newTotalFee, oldTotalFee) fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
......
...@@ -18,8 +18,8 @@ import ( ...@@ -18,8 +18,8 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"math/big" "math/big"
"unsafe" "unsafe"
) )
...@@ -330,7 +330,7 @@ func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initData ...@@ -330,7 +330,7 @@ func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initData
ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value) ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value)
if suberr == nil { if suberr == nil {
dataGas := big.NewInt(int64(len(ret))) // TODO: Nto the best design. env.Create can do it, it has the reference to gas counter dataGas := big.NewInt(int64(len(ret))) // TODO: Nto the best design. env.Create can do it, it has the reference to gas counter
dataGas.Mul(dataGas, GasCreateByte) dataGas.Mul(dataGas, params.CreateDataGas)
gas.Sub(gas, dataGas) gas.Sub(gas, dataGas)
*result = hash2llvm(ref.Address()) *result = hash2llvm(ref.Address())
} }
......
...@@ -32,8 +32,8 @@ var ( ...@@ -32,8 +32,8 @@ var (
defaultBootNodes = []*discover.Node{ defaultBootNodes = []*discover.Node{
// ETH/DEV cmd/bootnode // ETH/DEV cmd/bootnode
discover.MustParseNode("enode://09fbeec0d047e9a37e63f60f8618aa9df0e49271f3fadb2c070dc09e2099b95827b63a8b837c6fd01d0802d457dd83e3bd48bd3e6509f8209ed90dabbc30e3d3@52.16.188.185:30303"), discover.MustParseNode("enode://09fbeec0d047e9a37e63f60f8618aa9df0e49271f3fadb2c070dc09e2099b95827b63a8b837c6fd01d0802d457dd83e3bd48bd3e6509f8209ed90dabbc30e3d3@52.16.188.185:30303"),
// ETH/DEV cpp-ethereum (poc-8.ethdev.com) // ETH/DEV cpp-ethereum (poc-9.ethdev.com)
discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"), discover.MustParseNode("enode://487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a@5.1.83.226:30303"),
} }
) )
......
{
"genesisGasLimit": { "v": 1000000, "d": "Gas limit of the Genesis block." },
"minGasLimit": { "v": 125000, "d": "Minimum the gas limit may ever be." },
"gasLimitBoundDivisor": { "v": 1024, "d": "The bound divisor of the gas limit, used in update calculations." },
"genesisDifficulty": { "v": 131072, "d": "Difficulty of the Genesis block." },
"minimumDifficulty": { "v": 131072, "d": "The minimum that the difficulty may ever be." },
"difficultyBoundDivisor": { "v": 2048, "d": "The bound divisor of the difficulty, used in the update calculations." },
"durationLimit": { "v": 8, "d": "The decision boundary on the blocktime duration used to determine whether difficulty should go up or not." },
"maximumExtraDataSize": { "v": 1024, "d": "Maximum size extra data may be after Genesis." },
"epochDuration": { "v": 30000, "d": "Duration between proof-of-work epochs." },
"stackLimit": { "v": 1024, "d": "Maximum size of VM stack allowed." },
"tierStepGas": { "v": [ 0, 2, 3, 5, 8, 10, 20 ], "d": "Once per operation, for a selection of them." },
"expGas": { "v": 10, "d": "Once per EXP instuction." },
"expByteGas": { "v": 10, "d": "Times ceil(log256(exponent)) for the EXP instruction." },
"sha3Gas": { "v": 30, "d": "Once per SHA3 operation." },
"sha3WordGas": { "v": 6, "d": "Once per word of the SHA3 operation's data." },
"sloadGas": { "v": 50, "d": "Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added." },
"sstoreSetGas": { "v": 20000, "d": "Once per SLOAD operation." },
"sstoreResetGas": { "v": 5000, "d": "Once per SSTORE operation if the zeroness changes from zero." },
"sstoreClearGas": { "v": 5000, "d": "Once per SSTORE operation if the zeroness doesn't change." },
"sstoreRefundGas": { "v": 15000, "d": "Once per SSTORE operation if the zeroness changes to zero." },
"jumpdestGas": { "v": 1, "d": "Refunded gas, once per SSTORE operation if the zeroness changes to zero." },
"logGas": { "v": 375, "d": "Per LOG* operation." },
"logDataGas": { "v": 8, "d": "Per byte in a LOG* operation's data." },
"logTopicGas": { "v": 375, "d": "Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas." },
"createGas": { "v": 32000, "d": "Once per CREATE operation & contract-creation transaction." },
"callGas": { "v": 40, "d": "Once per CALL operation & message call transaction." },
"callStipend": { "v": 2300, "d": "Free gas given at beginning of call." },
"callValueTransferGas": { "v": 9000, "d": "Paid for CALL when the value transfor is non-zero." },
"callNewAccountGas": { "v": 25000, "d": "Paid for CALL when the destination address didn't exist prior." },
"suicideRefundGas": { "v": 24000, "d": "Refunded following a suicide operation." },
"memoryGas": { "v": 3, "d": "Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL." },
"quadCoeffDiv": { "v": 512, "d": "Divisor for the quadratic particle of the memory cost equation." },
"createDataGas": { "v": 200, "d": "" },
"txGas": { "v": 21000, "d": "Per transaction. NOTE: Not payable on data of calls between transactions." },
"txDataZeroGas": { "v": 4, "d": "Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions." },
"txDataNonZeroGas": { "v": 68, "d": "Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions." },
"copyGas": { "v": 3, "d": "" },
"ecrecoverGas": { "v": 3000, "d": "" },
"sha256Gas": { "v": 60, "d": "" },
"sha256WordGas": { "v": 12, "d": "" },
"ripemd160Gas": { "v": 600, "d": "" },
"ripemd160WordGas": { "v": 120, "d": "" },
"identityGas": { "v": 15, "d": "" },
"identityWordGas": { "v": 3, "d": ""}
}
...@@ -35,13 +35,16 @@ func main() { ...@@ -35,13 +35,16 @@ func main() {
m := make(map[string]setting) m := make(map[string]setting)
json.Unmarshal(content, &m) json.Unmarshal(content, &m)
filepath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "core", os.Args[2]) filepath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "params", os.Args[2])
output, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, os.ModePerm /*0777*/) output, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, os.ModePerm /*0777*/)
if err != nil { if err != nil {
fatal("error opening file for writing %v\n", err) fatal("error opening file for writing %v\n", err)
} }
output.WriteString(`package core output.WriteString(`// DO NOT EDIT!!!
// AUTOGENERATED FROM generators/defaults.go
package params
import "math/big" import "math/big"
......
This diff is collapsed.
...@@ -23,18 +23,28 @@ function pp(object, indent) { ...@@ -23,18 +23,28 @@ function pp(object, indent) {
} }
} }
str += " ]"; str += " ]";
} else if (object instanceof Error) {
str += "\033[31m" + "Error";
} else if (isBigNumber(object)) {
str += "\033[32m'" + object.toString(10) + "'";
} else if(typeof(object) === "object") { } else if(typeof(object) === "object") {
str += "{\n"; str += "{\n";
indent += " "; indent += " ";
var last = Object.keys(object).pop() var last = Object.getOwnPropertyNames(object).pop()
for(var k in object) { Object.getOwnPropertyNames(object).forEach(function (k) {
str += indent + k + ": " + pp(object[k], indent); str += indent + k + ": ";
try {
str += pp(object[k], indent);
} catch (e) {
str += pp(e, indent);
}
if(k !== last) { if(k !== last) {
str += ","; str += ",";
} }
str += "\n";
} str += "\n";
});
str += indent.substr(2, indent.length) + "}"; str += indent.substr(2, indent.length) + "}";
} else if(typeof(object) === "string") { } else if(typeof(object) === "string") {
str += "\033[32m'" + object + "'"; str += "\033[32m'" + object + "'";
...@@ -43,7 +53,7 @@ function pp(object, indent) { ...@@ -43,7 +53,7 @@ function pp(object, indent) {
} else if(typeof(object) === "number") { } else if(typeof(object) === "number") {
str += "\033[31m" + object; str += "\033[31m" + object;
} else if(typeof(object) === "function") { } else if(typeof(object) === "function") {
str += "\033[35m[Function]"; str += "\033[35m[Function]";
} else { } else {
str += object; str += object;
} }
...@@ -53,6 +63,11 @@ function pp(object, indent) { ...@@ -53,6 +63,11 @@ function pp(object, indent) {
return str; return str;
} }
var isBigNumber = function (object) {
return typeof BigNumber !== 'undefined' && object instanceof BigNumber;
};
function prettyPrint(/* */) { function prettyPrint(/* */) {
var args = arguments; var args = arguments;
var ret = ""; var ret = "";
......
...@@ -60,7 +60,7 @@ out: ...@@ -60,7 +60,7 @@ out:
} }
} }
close(self.quitCurrentOp) //close(self.quitCurrentOp)
done: done:
// Empty channel // Empty channel
for { for {
......
...@@ -171,6 +171,8 @@ func (self *worker) wait() { ...@@ -171,6 +171,8 @@ func (self *worker) wait() {
} }
self.mux.Post(core.NewMinedBlockEvent{block}) self.mux.Post(core.NewMinedBlockEvent{block})
minerlogger.Infof("🔨 Mined block #%v", block.Number())
jsonlogger.LogJson(&logger.EthMinerNewBlock{ jsonlogger.LogJson(&logger.EthMinerNewBlock{
BlockHash: block.Hash().Hex(), BlockHash: block.Hash().Hex(),
BlockNumber: block.Number(), BlockNumber: block.Number(),
...@@ -270,9 +272,9 @@ gasLimit: ...@@ -270,9 +272,9 @@ gasLimit:
self.current.block.SetUncles(uncles) self.current.block.SetUncles(uncles)
self.current.state.AddBalance(self.coinbase, core.BlockReward) core.AccumulateRewards(self.current.state, self.current.block)
self.current.state.Update(common.Big0) self.current.state.Update()
self.push() self.push()
} }
...@@ -297,9 +299,6 @@ func (self *worker) commitUncle(uncle *types.Header) error { ...@@ -297,9 +299,6 @@ func (self *worker) commitUncle(uncle *types.Header) error {
return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash())) return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash()))
} }
self.current.state.AddBalance(uncle.Coinbase, uncleReward)
self.current.state.AddBalance(self.coinbase, inclusionReward)
return nil return nil
} }
......
...@@ -13,6 +13,8 @@ import ( ...@@ -13,6 +13,8 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sync"
"sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
...@@ -30,7 +32,8 @@ type Node struct { ...@@ -30,7 +32,8 @@ type Node struct {
DiscPort int // UDP listening port for discovery protocol DiscPort int // UDP listening port for discovery protocol
TCPPort int // TCP listening port for RLPx TCPPort int // TCP listening port for RLPx
active time.Time // this must be set/read using atomic load and store.
activeStamp int64
} }
func newNode(id NodeID, addr *net.UDPAddr) *Node { func newNode(id NodeID, addr *net.UDPAddr) *Node {
...@@ -39,7 +42,6 @@ func newNode(id NodeID, addr *net.UDPAddr) *Node { ...@@ -39,7 +42,6 @@ func newNode(id NodeID, addr *net.UDPAddr) *Node {
IP: addr.IP, IP: addr.IP,
DiscPort: addr.Port, DiscPort: addr.Port,
TCPPort: addr.Port, TCPPort: addr.Port,
active: time.Now(),
} }
} }
...@@ -48,6 +50,20 @@ func (n *Node) isValid() bool { ...@@ -48,6 +50,20 @@ func (n *Node) isValid() bool {
return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0 return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0
} }
func (n *Node) bumpActive() {
stamp := time.Now().Unix()
atomic.StoreInt64(&n.activeStamp, stamp)
}
func (n *Node) active() time.Time {
stamp := atomic.LoadInt64(&n.activeStamp)
return time.Unix(stamp, 0)
}
func (n *Node) addr() *net.UDPAddr {
return &net.UDPAddr{IP: n.IP, Port: n.DiscPort}
}
// The string representation of a Node is a URL. // The string representation of a Node is a URL.
// Please see ParseNode for a description of the format. // Please see ParseNode for a description of the format.
func (n *Node) String() string { func (n *Node) String() string {
...@@ -304,3 +320,26 @@ func randomID(a NodeID, n int) (b NodeID) { ...@@ -304,3 +320,26 @@ func randomID(a NodeID, n int) (b NodeID) {
} }
return b return b
} }
// nodeDB stores all nodes we know about.
type nodeDB struct {
mu sync.RWMutex
byID map[NodeID]*Node
}
func (db *nodeDB) get(id NodeID) *Node {
db.mu.RLock()
defer db.mu.RUnlock()
return db.byID[id]
}
func (db *nodeDB) add(id NodeID, addr *net.UDPAddr, tcpPort uint16) *Node {
db.mu.Lock()
defer db.mu.Unlock()
if db.byID == nil {
db.byID = make(map[NodeID]*Node)
}
n := &Node{ID: id, IP: addr.IP, DiscPort: addr.Port, TCPPort: int(tcpPort)}
db.byID[n.ID] = n
return n
}
...@@ -14,9 +14,10 @@ import ( ...@@ -14,9 +14,10 @@ import (
) )
const ( const (
alpha = 3 // Kademlia concurrency factor alpha = 3 // Kademlia concurrency factor
bucketSize = 16 // Kademlia bucket size bucketSize = 16 // Kademlia bucket size
nBuckets = nodeIDBits + 1 // Number of buckets nBuckets = nodeIDBits + 1 // Number of buckets
maxBondingPingPongs = 10
) )
type Table struct { type Table struct {
...@@ -24,27 +25,50 @@ type Table struct { ...@@ -24,27 +25,50 @@ type Table struct {
buckets [nBuckets]*bucket // index of known nodes by distance buckets [nBuckets]*bucket // index of known nodes by distance
nursery []*Node // bootstrap nodes nursery []*Node // bootstrap nodes
bondmu sync.Mutex
bonding map[NodeID]*bondproc
bondslots chan struct{} // limits total number of active bonding processes
net transport net transport
self *Node // metadata of the local node self *Node // metadata of the local node
db *nodeDB
}
type bondproc struct {
err error
n *Node
done chan struct{}
} }
// transport is implemented by the UDP transport. // transport is implemented by the UDP transport.
// it is an interface so we can test without opening lots of UDP // it is an interface so we can test without opening lots of UDP
// sockets and without generating a private key. // sockets and without generating a private key.
type transport interface { type transport interface {
ping(*Node) error ping(NodeID, *net.UDPAddr) error
findnode(e *Node, target NodeID) ([]*Node, error) waitping(NodeID) error
findnode(toid NodeID, addr *net.UDPAddr, target NodeID) ([]*Node, error)
close() close()
} }
// bucket contains nodes, ordered by their last activity. // bucket contains nodes, ordered by their last activity.
// the entry that was most recently active is the last element
// in entries.
type bucket struct { type bucket struct {
lastLookup time.Time lastLookup time.Time
entries []*Node entries []*Node
} }
func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr) *Table { func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr) *Table {
tab := &Table{net: t, self: newNode(ourID, ourAddr)} tab := &Table{
net: t,
db: new(nodeDB),
self: newNode(ourID, ourAddr),
bonding: make(map[NodeID]*bondproc),
bondslots: make(chan struct{}, maxBondingPingPongs),
}
for i := 0; i < cap(tab.bondslots); i++ {
tab.bondslots <- struct{}{}
}
for i := range tab.buckets { for i := range tab.buckets {
tab.buckets[i] = new(bucket) tab.buckets[i] = new(bucket)
} }
...@@ -107,8 +131,8 @@ func (tab *Table) Lookup(target NodeID) []*Node { ...@@ -107,8 +131,8 @@ func (tab *Table) Lookup(target NodeID) []*Node {
asked[n.ID] = true asked[n.ID] = true
pendingQueries++ pendingQueries++
go func() { go func() {
result, _ := tab.net.findnode(n, target) r, _ := tab.net.findnode(n.ID, n.addr(), target)
reply <- result reply <- tab.bondall(r)
}() }()
} }
} }
...@@ -116,13 +140,11 @@ func (tab *Table) Lookup(target NodeID) []*Node { ...@@ -116,13 +140,11 @@ func (tab *Table) Lookup(target NodeID) []*Node {
// we have asked all closest nodes, stop the search // we have asked all closest nodes, stop the search
break break
} }
// wait for the next reply // wait for the next reply
for _, n := range <-reply { for _, n := range <-reply {
cn := n if n != nil && !seen[n.ID] {
if !seen[n.ID] {
seen[n.ID] = true seen[n.ID] = true
result.push(cn, bucketSize) result.push(n, bucketSize)
} }
} }
pendingQueries-- pendingQueries--
...@@ -145,8 +167,9 @@ func (tab *Table) refresh() { ...@@ -145,8 +167,9 @@ func (tab *Table) refresh() {
result := tab.Lookup(randomID(tab.self.ID, ld)) result := tab.Lookup(randomID(tab.self.ID, ld))
if len(result) == 0 { if len(result) == 0 {
// bootstrap the table with a self lookup // bootstrap the table with a self lookup
all := tab.bondall(tab.nursery)
tab.mutex.Lock() tab.mutex.Lock()
tab.add(tab.nursery) tab.add(all)
tab.mutex.Unlock() tab.mutex.Unlock()
tab.Lookup(tab.self.ID) tab.Lookup(tab.self.ID)
// TODO: the Kademlia paper says that we're supposed to perform // TODO: the Kademlia paper says that we're supposed to perform
...@@ -176,45 +199,105 @@ func (tab *Table) len() (n int) { ...@@ -176,45 +199,105 @@ func (tab *Table) len() (n int) {
return n return n
} }
// bumpOrAdd updates the activity timestamp for the given node and // bondall bonds with all given nodes concurrently and returns
// attempts to insert the node into a bucket. The returned Node might // those nodes for which bonding has probably succeeded.
// not be part of the table. The caller must hold tab.mutex. func (tab *Table) bondall(nodes []*Node) (result []*Node) {
func (tab *Table) bumpOrAdd(node NodeID, from *net.UDPAddr) (n *Node) { rc := make(chan *Node, len(nodes))
b := tab.buckets[logdist(tab.self.ID, node)] for i := range nodes {
if n = b.bump(node); n == nil { go func(n *Node) {
n = newNode(node, from) nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCPPort))
if len(b.entries) == bucketSize { rc <- nn
tab.pingReplace(n, b) }(nodes[i])
} else { }
b.entries = append(b.entries, n) for _ = range nodes {
if n := <-rc; n != nil {
result = append(result, n)
} }
} }
return n return result
} }
func (tab *Table) pingReplace(n *Node, b *bucket) { // bond ensures the local node has a bond with the given remote node.
old := b.entries[bucketSize-1] // It also attempts to insert the node into the table if bonding succeeds.
go func() { // The caller must not hold tab.mutex.
if err := tab.net.ping(old); err == nil { //
// it responded, we don't need to replace it. // A bond is must be established before sending findnode requests.
return // Both sides must have completed a ping/pong exchange for a bond to
// exist. The total number of active bonding processes is limited in
// order to restrain network use.
//
// bond is meant to operate idempotently in that bonding with a remote
// node which still remembers a previously established bond will work.
// The remote node will simply not send a ping back, causing waitping
// to time out.
//
// If pinged is true, the remote node has just pinged us and one half
// of the process can be skipped.
func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) (*Node, error) {
var n *Node
if n = tab.db.get(id); n == nil {
tab.bondmu.Lock()
w := tab.bonding[id]
if w != nil {
// Wait for an existing bonding process to complete.
tab.bondmu.Unlock()
<-w.done
} else {
// Register a new bonding process.
w = &bondproc{done: make(chan struct{})}
tab.bonding[id] = w
tab.bondmu.Unlock()
// Do the ping/pong. The result goes into w.
tab.pingpong(w, pinged, id, addr, tcpPort)
// Unregister the process after it's done.
tab.bondmu.Lock()
delete(tab.bonding, id)
tab.bondmu.Unlock()
} }
// it didn't respond, replace the node if it is still the oldest node. n = w.n
tab.mutex.Lock() if w.err != nil {
if len(b.entries) > 0 && b.entries[len(b.entries)-1] == old { return nil, w.err
// slide down other entries and put the new one in front.
// TODO: insert in correct position to keep the order
copy(b.entries[1:], b.entries)
b.entries[0] = n
} }
tab.mutex.Unlock() }
}() tab.mutex.Lock()
defer tab.mutex.Unlock()
if b := tab.buckets[logdist(tab.self.ID, n.ID)]; !b.bump(n) {
tab.pingreplace(n, b)
}
return n, nil
}
func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) {
<-tab.bondslots
defer func() { tab.bondslots <- struct{}{} }()
if w.err = tab.net.ping(id, addr); w.err != nil {
close(w.done)
return
}
if !pinged {
// Give the remote node a chance to ping us before we start
// sending findnode requests. If they still remember us,
// waitping will simply time out.
tab.net.waitping(id)
}
w.n = tab.db.add(id, addr, tcpPort)
close(w.done)
} }
// bump updates the activity timestamp for the given node. func (tab *Table) pingreplace(new *Node, b *bucket) {
// The caller must hold tab.mutex. if len(b.entries) == bucketSize {
func (tab *Table) bump(node NodeID) { oldest := b.entries[bucketSize-1]
tab.buckets[logdist(tab.self.ID, node)].bump(node) if err := tab.net.ping(oldest.ID, oldest.addr()); err == nil {
// The node responded, we don't need to replace it.
return
}
} else {
// Add a slot at the end so the last entry doesn't
// fall off when adding the new node.
b.entries = append(b.entries, nil)
}
copy(b.entries[1:], b.entries)
b.entries[0] = new
} }
// add puts the entries into the table if their corresponding // add puts the entries into the table if their corresponding
...@@ -240,17 +323,17 @@ outer: ...@@ -240,17 +323,17 @@ outer:
} }
} }
func (b *bucket) bump(id NodeID) *Node { func (b *bucket) bump(n *Node) bool {
for i, n := range b.entries { for i := range b.entries {
if n.ID == id { if b.entries[i].ID == n.ID {
n.active = time.Now() n.bumpActive()
// move it to the front // move it to the front
copy(b.entries[1:], b.entries[:i+1]) copy(b.entries[1:], b.entries[:i])
b.entries[0] = n b.entries[0] = n
return n return true
} }
} }
return nil return false
} }
// nodesByDistance is a list of nodes, ordered by // nodesByDistance is a list of nodes, ordered by
......
...@@ -2,78 +2,109 @@ package discover ...@@ -2,78 +2,109 @@ package discover
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"errors"
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
"reflect" "reflect"
"testing" "testing"
"testing/quick" "testing/quick"
"time"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
func TestTable_bumpOrAddBucketAssign(t *testing.T) { func TestTable_pingReplace(t *testing.T) {
tab := newTable(nil, NodeID{}, &net.UDPAddr{}) doit := func(newNodeIsResponding, lastInBucketIsResponding bool) {
for i := 1; i < len(tab.buckets); i++ { transport := newPingRecorder()
tab.bumpOrAdd(randomID(tab.self.ID, i), &net.UDPAddr{}) tab := newTable(transport, NodeID{}, &net.UDPAddr{})
} last := fillBucket(tab, 200)
for i, b := range tab.buckets { pingSender := randomID(tab.self.ID, 200)
if i > 0 && len(b.entries) != 1 {
t.Errorf("bucket %d has %d entries, want 1", i, len(b.entries)) // this gotPing should replace the last node
// if the last node is not responding.
transport.responding[last.ID] = lastInBucketIsResponding
transport.responding[pingSender] = newNodeIsResponding
tab.bond(true, pingSender, &net.UDPAddr{}, 0)
// first ping goes to sender (bonding pingback)
if !transport.pinged[pingSender] {
t.Error("table did not ping back sender")
}
if newNodeIsResponding {
// second ping goes to oldest node in bucket
// to see whether it is still alive.
if !transport.pinged[last.ID] {
t.Error("table did not ping last node in bucket")
}
} }
}
}
func TestTable_bumpOrAddPingReplace(t *testing.T) {
pingC := make(pingC)
tab := newTable(pingC, NodeID{}, &net.UDPAddr{})
last := fillBucket(tab, 200)
// this bumpOrAdd should not replace the last node tab.mutex.Lock()
// because the node replies to ping. defer tab.mutex.Unlock()
new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{}) if l := len(tab.buckets[200].entries); l != bucketSize {
t.Errorf("wrong bucket size after gotPing: got %d, want %d", bucketSize, l)
}
pinged := <-pingC if lastInBucketIsResponding || !newNodeIsResponding {
if pinged != last.ID { if !contains(tab.buckets[200].entries, last.ID) {
t.Fatalf("pinged wrong node: %v\nwant %v", pinged, last.ID) t.Error("last entry was removed")
}
if contains(tab.buckets[200].entries, pingSender) {
t.Error("new entry was added")
}
} else {
if contains(tab.buckets[200].entries, last.ID) {
t.Error("last entry was not removed")
}
if !contains(tab.buckets[200].entries, pingSender) {
t.Error("new entry was not added")
}
}
} }
tab.mutex.Lock() doit(true, true)
defer tab.mutex.Unlock() doit(false, true)
if l := len(tab.buckets[200].entries); l != bucketSize { doit(false, true)
t.Errorf("wrong bucket size after bumpOrAdd: got %d, want %d", bucketSize, l) doit(false, false)
}
if !contains(tab.buckets[200].entries, last.ID) {
t.Error("last entry was removed")
}
if contains(tab.buckets[200].entries, new.ID) {
t.Error("new entry was added")
}
} }
func TestTable_bumpOrAddPingTimeout(t *testing.T) { func TestBucket_bumpNoDuplicates(t *testing.T) {
tab := newTable(pingC(nil), NodeID{}, &net.UDPAddr{}) t.Parallel()
last := fillBucket(tab, 200) cfg := &quick.Config{
MaxCount: 1000,
// this bumpOrAdd should replace the last node Rand: quickrand,
// because the node does not reply to ping. Values: func(args []reflect.Value, rand *rand.Rand) {
new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{}) // generate a random list of nodes. this will be the content of the bucket.
n := rand.Intn(bucketSize-1) + 1
// wait for async bucket update. damn. this needs to go away. nodes := make([]*Node, n)
time.Sleep(2 * time.Millisecond) for i := range nodes {
nodes[i] = &Node{ID: randomID(NodeID{}, 200)}
tab.mutex.Lock() }
defer tab.mutex.Unlock() args[0] = reflect.ValueOf(nodes)
if l := len(tab.buckets[200].entries); l != bucketSize { // generate random bump positions.
t.Errorf("wrong bucket size after bumpOrAdd: got %d, want %d", bucketSize, l) bumps := make([]int, rand.Intn(100))
for i := range bumps {
bumps[i] = rand.Intn(len(nodes))
}
args[1] = reflect.ValueOf(bumps)
},
} }
if contains(tab.buckets[200].entries, last.ID) {
t.Error("last entry was not removed") prop := func(nodes []*Node, bumps []int) (ok bool) {
b := &bucket{entries: make([]*Node, len(nodes))}
copy(b.entries, nodes)
for i, pos := range bumps {
b.bump(b.entries[pos])
if hasDuplicates(b.entries) {
t.Logf("bucket has duplicates after %d/%d bumps:", i+1, len(bumps))
for _, n := range b.entries {
t.Logf(" %p", n)
}
return false
}
}
return true
} }
if !contains(tab.buckets[200].entries, new.ID) { if err := quick.Check(prop, cfg); err != nil {
t.Error("new entry was not added") t.Error(err)
} }
} }
...@@ -85,44 +116,27 @@ func fillBucket(tab *Table, ld int) (last *Node) { ...@@ -85,44 +116,27 @@ func fillBucket(tab *Table, ld int) (last *Node) {
return b.entries[bucketSize-1] return b.entries[bucketSize-1]
} }
type pingC chan NodeID type pingRecorder struct{ responding, pinged map[NodeID]bool }
func (t pingC) findnode(n *Node, target NodeID) ([]*Node, error) { func newPingRecorder() *pingRecorder {
return &pingRecorder{make(map[NodeID]bool), make(map[NodeID]bool)}
}
func (t *pingRecorder) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
panic("findnode called on pingRecorder") panic("findnode called on pingRecorder")
} }
func (t pingC) close() { func (t *pingRecorder) close() {
panic("close called on pingRecorder") panic("close called on pingRecorder")
} }
func (t pingC) ping(n *Node) error { func (t *pingRecorder) waitping(from NodeID) error {
if t == nil { return nil // remote always pings
return errTimeout
}
t <- n.ID
return nil
} }
func (t *pingRecorder) ping(toid NodeID, toaddr *net.UDPAddr) error {
func TestTable_bump(t *testing.T) { t.pinged[toid] = true
tab := newTable(nil, NodeID{}, &net.UDPAddr{}) if t.responding[toid] {
return nil
// add an old entry and two recent ones } else {
oldactive := time.Now().Add(-2 * time.Minute) return errTimeout
old := &Node{ID: randomID(tab.self.ID, 200), active: oldactive}
others := []*Node{
&Node{ID: randomID(tab.self.ID, 200), active: time.Now()},
&Node{ID: randomID(tab.self.ID, 200), active: time.Now()},
}
tab.add(append(others, old))
if tab.buckets[200].entries[0] == old {
t.Fatal("old entry is at front of bucket")
}
// bumping the old entry should move it to the front
tab.bump(old.ID)
if old.active == oldactive {
t.Error("activity timestamp not updated")
}
if tab.buckets[200].entries[0] != old {
t.Errorf("bumped entry did not move to the front of bucket")
} }
} }
...@@ -210,7 +224,7 @@ func TestTable_Lookup(t *testing.T) { ...@@ -210,7 +224,7 @@ func TestTable_Lookup(t *testing.T) {
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results) t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
} }
// seed table with initial node (otherwise lookup will terminate immediately) // seed table with initial node (otherwise lookup will terminate immediately)
tab.bumpOrAdd(randomID(target, 200), &net.UDPAddr{Port: 200}) tab.add([]*Node{newNode(randomID(target, 200), &net.UDPAddr{Port: 200})})
results := tab.Lookup(target) results := tab.Lookup(target)
t.Logf("results:") t.Logf("results:")
...@@ -238,16 +252,16 @@ type findnodeOracle struct { ...@@ -238,16 +252,16 @@ type findnodeOracle struct {
target NodeID target NodeID
} }
func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) { func (t findnodeOracle) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
t.t.Logf("findnode query at dist %d", n.DiscPort) t.t.Logf("findnode query at dist %d", toaddr.Port)
// current log distance is encoded in port number // current log distance is encoded in port number
var result []*Node var result []*Node
switch n.DiscPort { switch toaddr.Port {
case 0: case 0:
panic("query to node at distance 0") panic("query to node at distance 0")
default: default:
// TODO: add more randomness to distances // TODO: add more randomness to distances
next := n.DiscPort - 1 next := toaddr.Port - 1
for i := 0; i < bucketSize; i++ { for i := 0; i < bucketSize; i++ {
result = append(result, &Node{ID: randomID(t.target, next), DiscPort: next}) result = append(result, &Node{ID: randomID(t.target, next), DiscPort: next})
} }
...@@ -255,11 +269,9 @@ func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) { ...@@ -255,11 +269,9 @@ func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) {
return result, nil return result, nil
} }
func (t findnodeOracle) close() {} func (t findnodeOracle) close() {}
func (t findnodeOracle) waitping(from NodeID) error { return nil }
func (t findnodeOracle) ping(n *Node) error { func (t findnodeOracle) ping(toid NodeID, toaddr *net.UDPAddr) error { return nil }
return errors.New("ping is not supported by this transport")
}
func hasDuplicates(slice []*Node) bool { func hasDuplicates(slice []*Node) bool {
seen := make(map[NodeID]bool) seen := make(map[NodeID]bool)
......
This diff is collapsed.
This diff is collapsed.
// DO NOT EDIT!!!
// AUTOGENERATED FROM generators/defaults.go
package params
import "math/big"
var (
MaximumExtraDataSize = big.NewInt(1024) // Maximum size extra data may be after Genesis.
ExpByteGas = big.NewInt(10) // Times ceil(log256(exponent)) for the EXP instruction.
SloadGas = big.NewInt(50) // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfor is non-zero.
CallNewAccountGas = big.NewInt(25000) // Paid for CALL when the destination address didn't exist prior.
TxGas = big.NewInt(21000) // Per transaction. NOTE: Not payable on data of calls between transactions.
TxDataZeroGas = big.NewInt(4) // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.
QuadCoeffDiv = big.NewInt(512) // Divisor for the quadratic particle of the memory cost equation.
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
DurationLimit = big.NewInt(8) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
SstoreSetGas = big.NewInt(20000) // Once per SLOAD operation.
LogDataGas = big.NewInt(8) // Per byte in a LOG* operation's data.
CallStipend = big.NewInt(2300) // Free gas given at beginning of call.
EcrecoverGas = big.NewInt(3000) //
Sha256WordGas = big.NewInt(12) //
MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
Sha256Gas = big.NewInt(60) //
IdentityWordGas = big.NewInt(3) //
Sha3WordGas = big.NewInt(6) // Once per word of the SHA3 operation's data.
SstoreResetGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness changes from zero.
SstoreClearGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness doesn't change.
SstoreRefundGas = big.NewInt(15000) // Once per SSTORE operation if the zeroness changes to zero.
JumpdestGas = big.NewInt(1) // Refunded gas, once per SSTORE operation if the zeroness changes to zero.
IdentityGas = big.NewInt(15) //
GasLimitBoundDivisor = big.NewInt(1024) // The bound divisor of the gas limit, used in update calculations.
EpochDuration = big.NewInt(30000) // Duration between proof-of-work epochs.
CallGas = big.NewInt(40) // Once per CALL operation & message call transaction.
CreateDataGas = big.NewInt(200) //
Ripemd160Gas = big.NewInt(600) //
Ripemd160WordGas = big.NewInt(120) //
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
CallCreateDepth = big.NewInt(1024) // Maximum depth of call/create stack.
ExpGas = big.NewInt(10) // Once per EXP instuction.
LogGas = big.NewInt(375) // Per LOG* operation.
CopyGas = big.NewInt(3) //
StackLimit = big.NewInt(1024) // Maximum size of VM stack allowed.
TierStepGas = big.NewInt(0) // Once per operation, for a selection of them.
LogTopicGas = big.NewInt(375) // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
CreateGas = big.NewInt(32000) // Once per CREATE operation & contract-creation transaction.
SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation.
MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
)
...@@ -80,8 +80,9 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err ...@@ -80,8 +80,9 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err return err
} }
v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance() *reply = api.xethAtStateNum(args.BlockNumber).BalanceAt(args.Address)
*reply = common.ToHex(v.Bytes()) //v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
//*reply = common.ToHex(v.Bytes())
case "eth_getStorage", "eth_storageAt": case "eth_getStorage", "eth_storageAt":
args := new(GetStorageArgs) args := new(GetStorageArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { if err := json.Unmarshal(req.Params, &args); err != nil {
...@@ -95,10 +96,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err ...@@ -95,10 +96,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err return err
} }
state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address) *reply = api.xethAtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key)
value := state.StorageString(args.Key)
*reply = common.ToHex(value.Bytes())
case "eth_getTransactionCount": case "eth_getTransactionCount":
args := new(GetTxCountArgs) args := new(GetTxCountArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { if err := json.Unmarshal(req.Params, &args); err != nil {
......
...@@ -114,7 +114,7 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) { ...@@ -114,7 +114,7 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
} }
} }
// sync objects to trie // sync objects to trie
statedb.Update(nil) statedb.Update()
// sync trie to disk // sync trie to disk
statedb.Sync() statedb.Sync()
......
{ {
"genesis_rlp_hex": "f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0", "genesis_rlp_hex": "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
"genesis_state_root": "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e", "genesis_state_root": "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e",
"genesis_hash": "b5d6d8402156c5c1dfadaa4b87c676b5bcadb17ef9bc8e939606daaa0d35f55d" "genesis_hash": "fd4af92a79c7fc2fd8bf0d342f2e832e1d4f485c85b9152d2039e03bc604fdca"
} }
{
"randomStatetest" : {
"env" : {
"currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5",
"currentDifficulty" : "5623894562375",
"currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentNumber" : "0",
"currentTimestamp" : "1",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "972201916",
"code" : "0x7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000019e7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c35036017f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b51916f2620a6e7d187a5560005155",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "912450255",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "999999998115347875",
"code" : "0x",
"nonce" : "1",
"storage" : {
}
}
},
"postStateRoot" : "24e7dcfb7ff0269a9000bedfeafad33c3ccc3610e3031c88bace245f3cbe64d2",
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000019e7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c35036017f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b51916f2620a6e7d187a5560005155",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "46",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "0x7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000019e7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c35036017f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b51916f2620a6e7d187a",
"gasLimit" : "0x3662e2a1",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "972201916"
}
}
}
{
"randomStatetest" : {
"env" : {
"currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5",
"currentDifficulty" : "5623894562375",
"currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentNumber" : "0",
"currentTimestamp" : "1",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x31417f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0315208a675944747f7430661519049a55",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "704316238",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "999999999295683808",
"code" : "0x",
"nonce" : "1",
"storage" : {
}
}
},
"postStateRoot" : "ddb8f27abb51685caa793be133df9db3912648c02498b74a0ae874294acce6f0",
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x31417f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0315208a675944747f7430661519049a55",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "46",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "0x31417f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0315208a675944747f7430661519049a",
"gasLimit" : "0x29fb0320",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "1758540724"
}
}
}
{
"randomStatetest" : {
"env" : {
"currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5",
"currentDifficulty" : "5623894562375",
"currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentNumber" : "0",
"currentTimestamp" : "1",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x44207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000001145344846604627f5560005155",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "620442430",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "999999999379557616",
"code" : "0x",
"nonce" : "1",
"storage" : {
}
}
},
"postStateRoot" : "da70f5af0d1545ec9f0f0e28a55d3f2896bb3d64c71b4908f72ed26c345aafe4",
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x44207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000001145344846604627f5560005155",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "46",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "0x44207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f00000000000000000000000100000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000001145344846604627f",
"gasLimit" : "0x24fb3310",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "1561176030"
}
}
}
{
"randomStatetest" : {
"env" : {
"currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5",
"currentDifficulty" : "5623894562375",
"currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"currentNumber" : "0",
"currentTimestamp" : "1",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x7f0000000000000000000000000000000000000000000000000000000000000001207f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe406f",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "1258533548",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "999999998741466498",
"code" : "0x",
"nonce" : "1",
"storage" : {
}
}
},
"postStateRoot" : "e1881131f80068947922f01c78464f93c46e6e11314d0deceb55809e594aec0a",
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0",
"code" : "0x7f0000000000000000000000000000000000000000000000000000000000000001207f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe406f",
"nonce" : "0",
"storage" : {
}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "46",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
}
}
},
"transaction" : {
"data" : "0x7f0000000000000000000000000000000000000000000000000000000000000001207f000000000000000000000000000000000000000000000000000000000000c3507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000c3507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe406f",
"gasLimit" : "0x4b03b27e",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "781711523"
}
}
}
...@@ -868,7 +868,7 @@ ...@@ -868,7 +868,7 @@
} }
}, },
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
"balance" : "100000", "balance" : "200000",
"code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056", "code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
...@@ -880,17 +880,29 @@ ...@@ -880,17 +880,29 @@
} }
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "999999999999533644", "balance" : "9999999533644",
"code" : "0x", "code" : "0x",
"nonce" : "1", "nonce" : "1",
"storage" : { "storage" : {
} }
} }
}, },
"postStateRoot" : "239c509594811741c8f3ed0a2d89abb00c0398098c80f88a82cebc153dec5c4b", "postStateRoot" : "5500215cdbf8165ca47720ad088ae49c2441560cdf267f1c946ae7b9807cb1d4",
"pre" : { "pre" : {
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
"balance" : "100000",
"code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
"nonce" : "0",
"storage" : {
"0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x01" : "0x42",
"0x02" : "0x23",
"0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x05" : "0x54c98c81"
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000", "balance" : "10000000000000",
"code" : "0x", "code" : "0x",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
......
...@@ -185,7 +185,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state. ...@@ -185,7 +185,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) { if core.IsNonceErr(err) || core.IsInvalidTxErr(err) {
statedb.Set(snapshot) statedb.Set(snapshot)
} }
statedb.Update(vmenv.Gas) statedb.Update()
return ret, vmenv.logs, vmenv.Gas, err return ret, vmenv.logs, vmenv.Gas, err
} }
......
...@@ -308,21 +308,19 @@ func (self *XEth) NumberToHuman(balance string) string { ...@@ -308,21 +308,19 @@ func (self *XEth) NumberToHuman(balance string) string {
} }
func (self *XEth) StorageAt(addr, storageAddr string) string { func (self *XEth) StorageAt(addr, storageAddr string) string {
storage := self.State().SafeGet(addr).StorageString(storageAddr) return common.ToHex(self.State().state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)))
return common.ToHex(storage.Bytes())
} }
func (self *XEth) BalanceAt(addr string) string { func (self *XEth) BalanceAt(addr string) string {
return self.State().SafeGet(addr).Balance().String() return common.ToHex(self.State().state.GetBalance(common.HexToAddress(addr)).Bytes())
} }
func (self *XEth) TxCountAt(address string) int { func (self *XEth) TxCountAt(address string) int {
return int(self.State().SafeGet(address).Nonce()) return int(self.State().state.GetNonce(common.HexToAddress(address)))
} }
func (self *XEth) CodeAt(address string) string { func (self *XEth) CodeAt(address string) string {
return common.ToHex(self.State().SafeGet(address).Code()) return common.ToHex(self.State().state.GetCode(common.HexToAddress(address)))
} }
func (self *XEth) CodeAtBytes(address string) []byte { func (self *XEth) CodeAtBytes(address string) []byte {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment