aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaylor Gerring <taylor.gerring@gmail.com>2015-04-02 19:39:46 +0800
committerTaylor Gerring <taylor.gerring@gmail.com>2015-04-02 19:39:46 +0800
commit118ad22ee59658ec8ff476999e48d9bffb0c7db6 (patch)
treeb60422477450918993bdce27f22cd45d81952bd8
parent81de8ed0912f767b2e3104aaad5c7f31920aaf2a (diff)
parent79828531b1e6a1d5073f45e0e672c54a019de7c0 (diff)
downloaddexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.tar
dexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.tar.gz
dexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.tar.bz2
dexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.tar.lz
dexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.tar.xz
dexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.tar.zst
dexon-118ad22ee59658ec8ff476999e48d9bffb0c7db6.zip
Merge branch 'develop' into rpcfabian
-rw-r--r--cmd/mist/assets/examples/coin.html2
m---------cmd/mist/assets/ext/ethereum.js0
-rw-r--r--core/block_processor.go55
-rw-r--r--core/chain_makers.go4
-rw-r--r--core/chain_manager.go14
-rw-r--r--core/execution.go3
-rw-r--r--core/genesis.go8
-rw-r--r--core/state/state_test.go2
-rw-r--r--core/state/statedb.go2
-rw-r--r--core/state_transition.go9
-rw-r--r--core/vm/address.go15
-rw-r--r--core/vm/common.go2
-rw-r--r--core/vm/errors.go3
-rw-r--r--core/vm/gas.go60
-rw-r--r--core/vm/stack.go2
-rw-r--r--core/vm/vm.go43
-rw-r--r--core/vm/vm_jit.go4
-rw-r--r--eth/backend.go4
-rw-r--r--generators/default.json56
-rw-r--r--generators/defaults.go7
-rw-r--r--jsre/ethereum_js.go3
-rw-r--r--jsre/pp_js.go29
-rw-r--r--miner/agent.go2
-rw-r--r--miner/worker.go9
-rw-r--r--p2p/discover/node.go43
-rw-r--r--p2p/discover/table.go185
-rw-r--r--p2p/discover/table_test.go202
-rw-r--r--p2p/discover/udp.go218
-rw-r--r--p2p/discover/udp_test.go422
-rwxr-xr-xparams/protocol_params.go54
-rw-r--r--rpc/api.go10
-rw-r--r--tests/blocktest.go2
-rw-r--r--tests/files/BasicTests/genesishashestest.json4
-rw-r--r--tests/files/StateTests/RandomTests/st201503261401CPPJIT.json71
-rw-r--r--tests/files/StateTests/RandomTests/st201504011535GO.json71
-rw-r--r--tests/files/StateTests/RandomTests/st201504011536GO.json71
-rw-r--r--tests/files/StateTests/RandomTests/st201504011547GO.json71
-rw-r--r--tests/files/StateTests/stCallCreateCallCodeTest.json20
-rw-r--r--tests/helper/vm.go2
-rw-r--r--xeth/xeth.go10
40 files changed, 1193 insertions, 601 deletions
diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html
index a15345ab3..0528a5ad0 100644
--- a/cmd/mist/assets/examples/coin.html
+++ b/cmd/mist/assets/examples/coin.html
@@ -3,7 +3,7 @@
<title>JevCoin</title>
<head>
<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>
<body>
diff --git a/cmd/mist/assets/ext/ethereum.js b/cmd/mist/assets/ext/ethereum.js
-Subproject 2536888f817a1a15b05dab4727d30f73d6763f0
+Subproject 31e046dbecea51d3b99b21f3e7e60ddfb6c3930
diff --git a/core/block_processor.go b/core/block_processor.go
index f7f0cd188..97c885536 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"gopkg.in/fatih/set.v0"
@@ -83,7 +84,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
}
// Update the state with pending changes
- statedb.Update(nil)
+ statedb.Update()
cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas))
receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative)
@@ -210,14 +211,16 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
return
}
- // Accumulate static rewards; block reward, uncle's and uncle inclusion.
- if err = sm.AccumulateRewards(state, block, parent); err != nil {
+ // Verify uncles
+ if err = sm.VerifyUncles(state, block, parent); err != nil {
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)
// used to calculate the state root.
- state.Update(common.Big0)
+ state.Update()
if header.Root != state.Root() {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
return
@@ -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.
// Validation validates easy over difficult (dagger takes longer time = difficult)
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))
}
@@ -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)
}
- // TODO: use use minGasLimit and gasLimitBoundDivisor from
- // https://github.com/ethereum/common/blob/master/params.json
- // block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024
+ // block.gasLimit - parent.gasLimit <= parent.gasLimit / GasLimitBoundDivisor
a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
a.Abs(a)
- b := new(big.Int).Div(parent.GasLimit, big.NewInt(1024))
- if !(a.Cmp(b) < 0) {
+ b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor)
+ 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)
}
@@ -291,9 +292,27 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
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)
+ 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()
uncles := set.New()
ancestorHeaders := make(map[common.Hash]*types.Header)
@@ -327,21 +346,8 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
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
}
@@ -358,7 +364,6 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
)
sm.TransitionState(state, parent, block, true)
- sm.AccumulateRewards(state, block, parent)
return state.Logs(), nil
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index d559b2a3a..52cb367c5 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -5,10 +5,10 @@ import (
"math/big"
"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/event"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/core/state"
)
// So we can generate blocks easily
@@ -81,7 +81,7 @@ func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Datab
cbase := state.GetOrNewStateObject(addr)
cbase.SetGasPool(CalcGasLimit(parent, block))
cbase.AddBalance(BlockReward)
- state.Update(common.Big0)
+ state.Update()
block.SetRoot(state.Root())
return block
}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index f0d3fd4cf..d97a94b06 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -32,18 +33,15 @@ type StateQuery interface {
func CalcDifficulty(block, parent *types.Header) *big.Int {
diff := new(big.Int)
- diffBoundDiv := big.NewInt(2048)
- min := big.NewInt(131072)
-
- adjust := new(big.Int).Div(parent.Difficulty, diffBoundDiv)
- if (block.Time - parent.Time) < 8 {
+ adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
+ if big.NewInt(int64(block.Time)-int64(parent.Time)).Cmp(params.DurationLimit) < 0 {
diff.Add(parent.Difficulty, adjust)
} else {
diff.Sub(parent.Difficulty, adjust)
}
- if diff.Cmp(min) < 0 {
- return min
+ if diff.Cmp(params.MinimumDifficulty) < 0 {
+ return params.MinimumDifficulty
}
return diff
@@ -76,7 +74,7 @@ func CalcGasLimit(parent, block *types.Block) *big.Int {
result := new(big.Int).Add(previous, curInt)
result.Div(result, big.NewInt(1024))
- return common.BigMax(GenesisGasLimit, result)
+ return common.BigMax(params.GenesisGasLimit, result)
}
type ChainManager struct {
diff --git a/core/execution.go b/core/execution.go
index 93fb03ecc..8134471d1 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
)
type Execution struct {
@@ -43,7 +44,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
env := self.env
evm := self.evm
- if env.Depth() == vm.MaxCallDepth {
+ if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(self.Gas, self.price)
return nil, vm.DepthError{}
diff --git a/core/genesis.go b/core/genesis.go
index 7958157a4..13656c40c 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -3,12 +3,12 @@ package core
import (
"encoding/json"
"fmt"
- "math/big"
"os"
"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/params"
)
/*
@@ -18,13 +18,11 @@ import (
var ZeroHash256 = make([]byte, 32)
var ZeroHash160 = make([]byte, 20)
var ZeroHash512 = make([]byte, 64)
-var GenesisDiff = big.NewInt(131072)
-var GenesisGasLimit = big.NewInt(3141592)
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().GasLimit = GenesisGasLimit
+ genesis.Header().GasLimit = params.GenesisGasLimit
genesis.Header().GasUsed = common.Big0
genesis.Header().Time = 0
diff --git a/core/state/state_test.go b/core/state/state_test.go
index da597d773..09a65de54 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -72,7 +72,7 @@ func TestNull(t *testing.T) {
//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
value := make([]byte, 16)
state.SetState(address, common.Hash{}, value)
- state.Update(nil)
+ state.Update()
state.Sync()
value = state.GetState(address, common.Hash{})
}
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 2dc8239ef..e69bb34fe 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -316,7 +316,7 @@ func (self *StateDB) Refunds() map[string]*big.Int {
return self.refund
}
-func (self *StateDB) Update(gasUsed *big.Int) {
+func (self *StateDB) Update() {
self.refund = make(map[string]*big.Int)
for _, stateObject := range self.stateObjects {
diff --git a/core/state_transition.go b/core/state_transition.go
index 7616686db..1994cabf6 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
)
const tryJit = false
@@ -178,7 +179,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
)
// Transaction gas
- if err = self.UseGas(vm.GasTx); err != nil {
+ if err = self.UseGas(params.TxGas); err != nil {
return nil, nil, InvalidTxError(err)
}
@@ -186,9 +187,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
dgas := new(big.Int)
for _, byt := range self.data {
if byt != 0 {
- dgas.Add(dgas, vm.GasTxDataNonzeroByte)
+ dgas.Add(dgas, params.TxDataNonZeroGas)
} 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
ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value)
if err == nil {
dataGas := big.NewInt(int64(len(ret)))
- dataGas.Mul(dataGas, vm.GasCreateByte)
+ dataGas.Mul(dataGas, params.CreateDataGas)
if err := self.UseGas(dataGas); err == nil {
ref.SetCode(ret)
} else {
diff --git a/core/vm/address.go b/core/vm/address.go
index 0b3a95dd0..df801863f 100644
--- a/core/vm/address.go
+++ b/core/vm/address.go
@@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
)
type Address interface {
@@ -27,28 +28,28 @@ func PrecompiledContracts() map[string]*PrecompiledAccount {
return map[string]*PrecompiledAccount{
// ECRECOVER
string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int {
- return GasEcrecover
+ return params.EcrecoverGas
}, ecrecoverFunc},
// SHA256
string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32)
- n.Mul(n, GasSha256Word)
- return n.Add(n, GasSha256Base)
+ n.Mul(n, params.Sha256WordGas)
+ return n.Add(n, params.Sha256Gas)
}, sha256Func},
// RIPEMD160
string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32)
- n.Mul(n, GasRipemdWord)
- return n.Add(n, GasRipemdBase)
+ n.Mul(n, params.Ripemd160WordGas)
+ return n.Add(n, params.Ripemd160Gas)
}, ripemd160Func},
string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int {
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},
}
}
diff --git a/core/vm/common.go b/core/vm/common.go
index 5ff4e05f2..0a93c3dd9 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -20,8 +20,6 @@ const (
JitVmTy
MaxVmTy
- MaxCallDepth = 1025
-
LogTyPretty byte = 0x1
LogTyDiff byte = 0x2
)
diff --git a/core/vm/errors.go b/core/vm/errors.go
index ab011bd62..fc3459de0 100644
--- a/core/vm/errors.go
+++ b/core/vm/errors.go
@@ -2,6 +2,7 @@ package vm
import (
"fmt"
+ "github.com/ethereum/go-ethereum/params"
"math/big"
)
@@ -42,7 +43,7 @@ func IsStack(err error) bool {
type DepthError struct{}
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 {
diff --git a/core/vm/gas.go b/core/vm/gas.go
index 2d5d7ae18..f7abe63f8 100644
--- a/core/vm/gas.go
+++ b/core/vm/gas.go
@@ -2,6 +2,7 @@ package vm
import (
"fmt"
+ "github.com/ethereum/go-ethereum/params"
"math/big"
)
@@ -13,45 +14,10 @@ var (
GasSlowStep = big.NewInt(10)
GasExtStep = big.NewInt(20)
- GasStorageGet = big.NewInt(50)
- GasStorageAdd = big.NewInt(20000)
- 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)
+ GasReturn = big.NewInt(0)
+ GasStop = big.NewInt(0)
- RefundStorage = big.NewInt(15000)
- 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)
+ GasContractByte = big.NewInt(200)
)
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
}
- if r.stackPush && len(stack.data)-r.stackPop+1 > 1024 {
- return fmt.Errorf("stack limit reached (%d)", maxStack)
+ if r.stackPush && len(stack.data)-r.stackPop+1 > int(params.StackLimit.Int64()) {
+ return fmt.Errorf("stack limit reached (%d)", params.StackLimit.Int64())
}
gas.Add(gas, r.gas)
@@ -142,16 +108,16 @@ var _baseCheck = map[OpCode]req{
MSIZE: {0, GasQuickStep, true},
GAS: {0, GasQuickStep, true},
BLOCKHASH: {1, GasExtStep, true},
- BALANCE: {0, GasExtStep, true},
+ BALANCE: {1, GasExtStep, true},
EXTCODESIZE: {1, GasExtStep, true},
EXTCODECOPY: {4, GasExtStep, false},
- SLOAD: {1, GasStorageGet, true},
+ SLOAD: {1, params.SloadGas, true},
SSTORE: {2, Zero, false},
- SHA3: {1, GasSha3Base, true},
- CREATE: {3, GasCreate, true},
- CALL: {7, GasCall, true},
- CALLCODE: {7, GasCall, true},
- JUMPDEST: {0, GasJumpDest, false},
+ SHA3: {2, params.Sha3Gas, true},
+ CREATE: {3, params.CreateGas, true},
+ CALL: {7, params.CallGas, true},
+ CALLCODE: {7, params.CallGas, true},
+ JUMPDEST: {0, params.JumpdestGas, false},
SUICIDE: {1, Zero, false},
RETURN: {2, Zero, false},
PUSH1: {0, GasFastestStep, true},
diff --git a/core/vm/stack.go b/core/vm/stack.go
index 168637708..bb232d0b9 100644
--- a/core/vm/stack.go
+++ b/core/vm/stack.go
@@ -5,8 +5,6 @@ import (
"math/big"
)
-const maxStack = 1024
-
func newStack() *stack {
return &stack{}
}
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 59c64e8a3..6222ef8c2 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
)
type Vm struct {
@@ -640,7 +641,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
} else {
// gas < len(ret) * CreateDataGas == NO_CODE
dataGas := big.NewInt(int64(len(ret)))
- dataGas.Mul(dataGas, GasCreateByte)
+ dataGas.Mul(dataGas, params.CreateDataGas)
if context.UseGas(dataGas) {
ref.SetCode(ret)
}
@@ -667,7 +668,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
args := mem.Get(inOffset.Int64(), inSize.Int64())
if len(value.Bytes()) > 0 {
- gas.Add(gas, GasStipend)
+ gas.Add(gas, params.CallStipend)
}
var (
@@ -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]
- gas.Add(gas, GasLogBase)
- gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic))
- gas.Add(gas, new(big.Int).Mul(mSize, GasLogByte))
+ gas.Add(gas, params.LogGas)
+ gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
+ gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
newMemSize = calcMemSize(mStart, mSize)
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:
err := stack.require(2)
if err != nil {
@@ -777,19 +778,19 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
val := statedb.GetState(context.Address(), common.BigToHash(x))
if len(val) == 0 && len(y.Bytes()) > 0 {
// 0 => non 0
- g = GasStorageAdd
+ g = params.SstoreSetGas
} 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 {
// non 0 => non 0 (or 0 => 0)
- g = GasStorageMod
+ g = params.SstoreClearGas
}
gas.Set(g)
case SUICIDE:
if !statedb.IsDeleted(context.Address()) {
- statedb.Refund(self.env.Origin(), RefundSuicide)
+ statedb.Refund(self.env.Origin(), params.SuicideRefundGas)
}
case MLOAD:
newMemSize = calcMemSize(stack.peek(), u256(32))
@@ -803,22 +804,22 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
newMemSize = calcMemSize(stack.peek(), 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:
newMemSize = calcMemSize(stack.peek(), 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:
newMemSize = calcMemSize(stack.peek(), 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:
newMemSize = calcMemSize(stack.data[stack.len()-2], 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:
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
if op == CALL {
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 {
- gas.Add(gas, GasCallValueTransfer)
+ gas.Add(gas, params.CallValueTransferGas)
}
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
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
oldSize := toWordSize(big.NewInt(int64(mem.Len())))
pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
- linCoef := new(big.Int).Mul(oldSize, GasMemWord)
- quadCoef := new(big.Int).Div(pow, GasQuadCoeffDenom)
+ linCoef := new(big.Int).Mul(oldSize, params.MemoryGas)
+ quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
pow.Exp(newMemSizeWords, common.Big2, Zero)
- linCoef = new(big.Int).Mul(newMemSizeWords, GasMemWord)
- quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom)
+ linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas)
+ quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv)
newTotalFee := new(big.Int).Add(linCoef, quadCoef)
fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
diff --git a/core/vm/vm_jit.go b/core/vm/vm_jit.go
index 2b88d8620..991ade318 100644
--- a/core/vm/vm_jit.go
+++ b/core/vm/vm_jit.go
@@ -18,8 +18,8 @@ import (
"bytes"
"errors"
"fmt"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/crypto"
"math/big"
"unsafe"
)
@@ -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)
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.Mul(dataGas, GasCreateByte)
+ dataGas.Mul(dataGas, params.CreateDataGas)
gas.Sub(gas, dataGas)
*result = hash2llvm(ref.Address())
}
diff --git a/eth/backend.go b/eth/backend.go
index b1fa68e72..cc4f807bf 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -32,8 +32,8 @@ var (
defaultBootNodes = []*discover.Node{
// ETH/DEV cmd/bootnode
discover.MustParseNode("enode://09fbeec0d047e9a37e63f60f8618aa9df0e49271f3fadb2c070dc09e2099b95827b63a8b837c6fd01d0802d457dd83e3bd48bd3e6509f8209ed90dabbc30e3d3@52.16.188.185:30303"),
- // ETH/DEV cpp-ethereum (poc-8.ethdev.com)
- discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"),
+ // ETH/DEV cpp-ethereum (poc-9.ethdev.com)
+ discover.MustParseNode("enode://487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a@5.1.83.226:30303"),
}
)
diff --git a/generators/default.json b/generators/default.json
deleted file mode 100644
index 181a9dd54..000000000
--- a/generators/default.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "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": ""}
-}
diff --git a/generators/defaults.go b/generators/defaults.go
index b0c71111c..41d46729c 100644
--- a/generators/defaults.go
+++ b/generators/defaults.go
@@ -35,13 +35,16 @@ func main() {
m := make(map[string]setting)
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*/)
if err != nil {
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"
diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go
index 403c438bc..0c38cd0e4 100644
--- a/jsre/ethereum_js.go
+++ b/jsre/ethereum_js.go
@@ -1,3 +1,4 @@
package jsre
-const Ethereum_JS = `require=function t(e,n,r){function o(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=t("./types"),i=t("./formatters"),a=function(t){throw new Error("parser does not support type: "+t)},u=function(t){return"[]"===t.slice(-2)},s=function(t,e){return u(t)||"bytes"===t?i.formatInputInt(e.length):""},c=o.inputTypes(),l=function(t,e){var n="",r="",o="";return t.forEach(function(t,r){n+=s(t.type,e[r])}),t.forEach(function(n,i){for(var s=!1,l=0;l<c.length&&!s;l++)s=c[l].type(t[i].type,e[i]);s||a(t[i].type);var f=c[l-1].format;u(t[i].type)?o+=e[i].reduce(function(t,e){return t+f(e)},""):"bytes"===t[i].type?o+=f(e[i]):r+=f(e[i])}),n+=r+o},f=function(t){return u(t)||"bytes"===t?2*r.ETH_PADDING:0},p=o.outputTypes(),m=function(t,e){e=e.slice(2);var n=[],s=2*r.ETH_PADDING,c=t.reduce(function(t,e){return t+f(e.type)},0),l=e.slice(0,c);return e=e.slice(c),t.forEach(function(r,c){for(var f=!1,m=0;m<p.length&&!f;m++)f=p[m].type(t[c].type);f||a(t[c].type);var d=p[m-1].format;if(u(t[c].type)){var h=i.formatOutputUInt(l.slice(0,s));l=l.slice(s);for(var g=[],y=0;h>y;y++)g.push(d(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(d(e.slice(0,s))),e=e.slice(s)):(n.push(d(e.slice(0,s))),e=e.slice(s))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),i(r.toTwosComplement(t).round().toString(16),e)},u=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},c=function(t){return a(new n(t).times(new n(2).pow(128)))},l=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},f=function(t){return t=t||"0",l(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},p=function(t){return t=t||"0",new n(t,16)},m=function(t){return f(t).dividedBy(new n(2).pow(128))},d=function(t){return p(t).dividedBy(new n(2).pow(128))},h=function(t){return"0x"+t},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},y=function(t){return r.toAscii(t)},b=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:u,formatInputBool:s,formatInputReal:c,formatOutputInt:f,formatOutputUInt:p,formatOutputReal:m,formatOutputUReal:d,formatOutputHash:h,formatOutputBool:g,formatOutputString:y,formatOutputAddress:b}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e){for(var n=!1,r=0;r<t.length&&!n;r++)n=e(t[r]);return n?r-1:-1},i=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},a=function(t){for(var e="",n=0;n<t.length;n++){var r=t.charCodeAt(n).toString(16);e+=r.length<2?"0"+r:r}return e},u=function(t,e){e=void 0===e?0:e;for(var n=a(t);n.length<2*e;)n+="00";return"0x"+n},s=function(t){var e=t.indexOf("(");return-1!==e?t.substr(0,e):t},c=function(t){var e=t.indexOf("(");return-1!==e?t.substr(e+1,t.length-1-(e+1)).replace(" ",""):""},l=function(t){return t.filter(function(t){return"function"===t.type})},f=function(t){return t.filter(function(t){return"event"===t.type})},p=function(t){return b(t).toNumber()},m=function(t){var e=b(t),n=e.toString(16);return e.lessThan(0)?"-0x"+n.substr(1):"0x"+n},d=function(t){if(B(t))return t;if(x(t))return m(t);if(F(t))return u(JSON.stringify(t));if(_(t)){if(0===t.indexOf("-0x"))return m(t);if(!isFinite(t))return u(t)}return m(t)},h=function(t){t=t?t.toLowerCase():"ether";var e=r[t];if(void 0===e)throw new Error("This unit doesn't exists, please use the one of the following units"+JSON.stringify(r,null,2));return new n(e,10)},g=function(t,e){var n=b(t).dividedBy(h(e));return x(t)?n:n.toString(10)},y=function(t,e){var n=b(t).times(h(e));return x(t)?n:n.toString(10)},b=function(t){return t=t||0,x(t)?t:!_(t)||0!==t.indexOf("0x")&&0!==t.indexOf("-0x")?new n(t.toString(10),10):new n(t.replace("0x",""),16)},v=function(t){var e=b(t);return e.lessThan(0)?new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(e).plus(1):e},w=function(t){return _(t)?0===t.indexOf("0x")&&42===t.length||-1===t.indexOf("0x")&&40===t.length:!1},x=function(t){return t instanceof n||t&&t.constructor&&"BigNumber"===t.constructor.name},_=function(t){return"string"==typeof t||t&&t.constructor&&"String"===t.constructor.name},T=function(t){return"function"==typeof t},F=function(t){return"object"==typeof t},B=function(t){return"boolean"==typeof t},D=function(t){return t instanceof Array};e.exports={findIndex:o,toHex:d,toDecimal:p,fromDecimal:m,toAscii:i,fromAscii:u,extractDisplayName:s,extractTypeName:c,filterFunctions:l,filterEvents:f,toWei:y,fromWei:g,toBigNumber:b,toTwosComplement:v,isBigNumber:x,isAddress:w,isFunction:T,isString:_,isObject:F,isBoolean:B,isArray:D}},{"bignumber.js":"bignumber.js"}],7:[function(t,e){e.exports={version:"0.1.3"}},{}],8:[function(t,e){var n=t("./version.json"),r=t("./web3/net"),o=t("./web3/eth"),i=t("./web3/db"),a=t("./web3/shh"),u=t("./web3/watches"),s=t("./web3/filter"),c=t("./utils/utils"),l=t("./web3/formatters"),f=t("./web3/requestmanager"),p=t("./utils/config"),m=[{name:"sha3",call:"web3_sha3",inputFormatter:c.toHex}],d=[{name:"version.client",getter:"web3_clientVersion"},{name:"version.network",getter:"net_version"}],h=function(t,e){e.forEach(function(e){var n=e.name.split("."),r=function(){var t=null,n=Array.prototype.slice.call(arguments),r="function"==typeof e.call?e.call(n):e.call;return"function"==typeof n[n.length-1]&&(t=n[n.length-1],Array.prototype.pop.call(n)),e.addDefaultblock&&(n.length!==e.addDefaultblock?Array.prototype.push.call(n,isFinite(p.ETH_DEFAULTBLOCK)?c.fromDecimal(p.ETH_DEFAULTBLOCK):p.ETH_DEFAULTBLOCK):n[n.length-1]=isFinite(n[n.length-1])?c.fromDecimal(n[n.length-1]):n[n.length-1]),e.newMethod&&console.warn("This method is deprecated please use web3."+e.newMethod+"() instead."),x.manager.send({method:r,params:n,outputFormatter:e.outputFormatter,inputFormatter:e.inputFormatter,addDefaultblock:e.addDefaultblock},t)};n.length>1?(t[n[0]]||(t[n[0]]={}),t[n[0]][n[1]]=r):t[n[0]]=r})},g=function(t,e){e.forEach(function(e){var n=e.name.split("."),r={};r.get=function(){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.getter,outputFormatter:e.outputFormatter})},e.setter&&(r.set=function(t){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.setter,params:[t],inputFormatter:e.inputFormatter})}),r.enumerable=!e.newProperty,n.length>1?(t[n[0]]||(t[n[0]]={}),Object.defineProperty(t[n[0]],n[1],r)):Object.defineProperty(t,e.name,r)})},y=function(t,e,n,r){x.manager.startPolling({method:t,params:[e]},e,n,r)},b=function(t){x.manager.stopPolling(t)},v={startPolling:y.bind(null,"eth_getFilterChanges"),stopPolling:b},w={startPolling:y.bind(null,"shh_getFilterChanges"),stopPolling:b},x={version:{api:n.version},manager:f(),providers:{},setProvider:function(t){x.manager.setProvider(t)},reset:function(){x.manager.reset()},toHex:c.toHex,toAscii:c.toAscii,fromAscii:c.fromAscii,toDecimal:c.toDecimal,fromDecimal:c.fromDecimal,toBigNumber:c.toBigNumber,toWei:c.toWei,fromWei:c.fromWei,isAddress:c.isAddress,net:{},eth:{contractFromAbi:function(t){return console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=x.eth.contract(e,t);return n.address=e,n}},filter:function(t,e,n){return t._isEvent?t(e,n):s(t,v,l.outputLogFormatter)},watch:function(t,e,n){return console.warn("eth.watch() is deprecated please use eth.filter() instead."),this.filter(t,e,n)}},db:{},shh:{filter:function(t){return s(t,w,l.outputPostFormatter)},watch:function(t){return console.warn("shh.watch() is deprecated please use shh.filter() instead."),this.filter(t)}}};Object.defineProperty(x.eth,"defaultBlock",{get:function(){return p.ETH_DEFAULTBLOCK},set:function(t){return p.ETH_DEFAULTBLOCK=t,p.ETH_DEFAULTBLOCK}}),h(x,m),g(x,d),h(x.net,r.methods),g(x.net,r.properties),h(x.eth,o.methods),g(x.eth,o.properties),h(x.db,i.methods()),h(x.shh,a.methods()),h(v,u.eth()),h(w,u.shh()),e.exports=x},{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/db":10,"./web3/eth":11,"./web3/filter":13,"./web3/formatters":14,"./web3/net":17,"./web3/requestmanager":19,"./web3/shh":20,"./web3/watches":22}],9:[function(t,e){function n(t,e){t.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return c(n),l(n,t,e),f(n,t,e),p(n,t,e),n}var r=t("../web3"),o=t("../solidity/abi"),i=t("../utils/utils"),a=t("./event"),u=t("./signature"),s=function(t){r._currentContractAbi=t.abi,r._currentContractAddress=t.address,r._currentContractMethodName=t.method,r._currentContractMethodParams=t.params},c=function(t){t.call=function(e){return t._isTransaction=!1,t._options=e,t},t.sendTransaction=function(e){return t._isTransaction=!0,t._options=e,t},t.transact=function(e){return console.warn("myContract.transact() is deprecated please use myContract.sendTransaction() instead."),t.sendTransaction(e)},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},l=function(t,e,n){var a=o.inputParser(e),c=o.outputParser(e);i.filterFunctions(e).forEach(function(o){var l=i.extractDisplayName(o.name),f=i.extractTypeName(o.name),p=function(){var i=Array.prototype.slice.call(arguments),p=u.functionSignatureFromAscii(o.name),m=a[l][f].apply(null,i),d=t._options||{};d.to=n,d.data=p+m;var h=t._isTransaction===!0||t._isTransaction!==!1&&!o.constant,g=d.collapse!==!1;if(t._options={},t._isTransaction=null,h)return s({abi:e,address:n,method:o.name,params:i}),void r.eth.sendTransaction(d);var y=r.eth.call(d),b=c[l][f](y);return g&&(1===b.length?b=b[0]:0===b.length&&(b=null)),b};void 0===t[l]&&(t[l]=p),t[l][f]=p})},f=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=a.outputParser(n);return r(t)},Object.defineProperty(t,"topics",{get:function(){return i.filterEvents(e).map(function(t){return u.eventSignatureFromAscii(t.name)})}})},p=function(t,e,n){i.filterEvents(e).forEach(function(e){var o=function(){var t=Array.prototype.slice.call(arguments),o=u.eventSignatureFromAscii(e.name),i=a.inputParser(n,o,e),s=i.apply(null,t),c=function(t){var n=a.outputParser(e);return n(t)};return r.eth.filter(s,void 0,void 0,c)};o._isEvent=!0;var s=i.extractDisplayName(e.name),c=i.extractTypeName(e.name);void 0===t[s]&&(t[s]=o),t[s][c]=o})},m=function(t){return t instanceof Array&&1===arguments.length?n.bind(null,t):(console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),new n(arguments[1],arguments[0]))};e.exports=m},{"../solidity/abi":1,"../utils/utils":6,"../web3":8,"./event":12,"./signature":21}],10:[function(t,e){var n=function(){return[{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"},{name:"putHex",call:"db_putHex"},{name:"getHex",call:"db_getHex"}]};e.exports={methods:n}},{}],11:[function(t,e){var n=t("./formatters"),r=t("../utils/utils"),o=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockByHash":"eth_getBlockByNumber"},i=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getTransactionByBlockHashAndIndex":"eth_getTransactionByBlockNumberAndIndex"},a=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleByBlockHashAndIndex":"eth_getUncleByBlockNumberAndIndex"},u=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockTransactionCountByHash":"eth_getBlockTransactionCountByNumber"},s=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleCountByBlockHash":"eth_getUncleCountByBlockNumber"},c=[{name:"getBalance",call:"eth_getBalance",addDefaultblock:2,outputFormatter:n.convertToBigNumber},{name:"getStorage",call:"eth_getStorage",addDefaultblock:2},{name:"getStorageAt",call:"eth_getStorageAt",addDefaultblock:3,inputFormatter:r.toHex},{name:"getCode",call:"eth_getCode",addDefaultblock:2},{name:"getBlock",call:o,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,function(t){return t?!0:!1}]},{name:"getUncle",call:a,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,r.toHex,function(t){return t?!0:!1}]},{name:"getCompilers",call:"eth_getCompilers"},{name:"getBlockTransactionCount",call:u,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getBlockUncleCount",call:s,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getTransaction",call:"eth_getTransactionByHash",outputFormatter:n.outputTransactionFormatter},{name:"getTransactionFromBlock",call:i,outputFormatter:n.outputTransactionFormatter,inputFormatter:r.toHex},{name:"getTransactionCount",call:"eth_getTransactionCount",addDefaultblock:2,outputFormatter:r.toDecimal},{name:"sendTransaction",call:"eth_sendTransaction",inputFormatter:n.inputTransactionFormatter},{name:"call",call:"eth_call",addDefaultblock:2,inputFormatter:n.inputCallFormatter},{name:"compile.solidity",call:"eth_compileSolidity"},{name:"compile.lll",call:"eth_compileLLL",inputFormatter:r.toHex},{name:"compile.serpent",call:"eth_compileSerpent",inputFormatter:r.toHex},{name:"flush",call:"eth_flush"},{name:"balanceAt",call:"eth_balanceAt",newMethod:"eth.getBalance"},{name:"stateAt",call:"eth_stateAt",newMethod:"eth.getStorageAt"},{name:"storageAt",call:"eth_storageAt",newMethod:"eth.getStorage"},{name:"countAt",call:"eth_countAt",newMethod:"eth.getTransactionCount"},{name:"codeAt",call:"eth_codeAt",newMethod:"eth.getCode"},{name:"transact",call:"eth_transact",newMethod:"eth.sendTransaction"},{name:"block",call:o,newMethod:"eth.getBlock"},{name:"transaction",call:i,newMethod:"eth.getTransaction"},{name:"uncle",call:a,newMethod:"eth.getUncle"},{name:"compilers",call:"eth_compilers",newMethod:"eth.getCompilers"},{name:"solidity",call:"eth_solidity",newMethod:"eth.compile.solidity"},{name:"lll",call:"eth_lll",newMethod:"eth.compile.lll"},{name:"serpent",call:"eth_serpent",newMethod:"eth.compile.serpent"},{name:"transactionCount",call:u,newMethod:"eth.getBlockTransactionCount"},{name:"uncleCount",call:s,newMethod:"eth.getBlockUncleCount"},{name:"logs",call:"eth_logs"}],l=[{name:"coinbase",getter:"eth_coinbase"},{name:"mining",getter:"eth_mining"},{name:"gasPrice",getter:"eth_gasPrice",outputFormatter:n.convertToBigNumber},{name:"accounts",getter:"eth_accounts"},{name:"blockNumber",getter:"eth_blockNumber",outputFormatter:r.toDecimal},{name:"listening",getter:"net_listening",setter:"eth_setListening",newProperty:"net.listening"},{name:"peerCount",getter:"net_peerCount",newProperty:"net.peerCount"},{name:"number",getter:"eth_number",newProperty:"eth.blockNumber"}];e.exports={methods:c,properties:l}},{"../utils/utils":6,"./formatters":14}],12:[function(t,e){var n=t("../solidity/abi"),r=t("../utils/utils"),o=t("./signature"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},a=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},u=function(t,e){return Object.keys(e).map(function(r){var o=[a(i(t.inputs,!0),r)],u=e[r];return u instanceof Array?u.map(function(t){return n.formatInput(o,[t])}):"0x"+n.formatInput(o,[u])})},s=function(t,e,n){return function(r,o){var i=o||{};return i.address=t,i.topics=[],i.topics.push(e),r&&(i.topics=i.topics.concat(u(n,r))),i}},c=function(t,e,n){var r=e.slice(),o=n.slice();return t.reduce(function(t,e){var n;return n=e.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[e.name]=n,t},{})},l=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,hash:e.hash,args:{}};if(e.topics=e.topic,!e.topics)return o;var a=i(t.inputs,!0),u="0x"+e.topics.slice(1,e.topics.length).map(function(t){return t.slice(2)}).join(""),s=n.formatOutput(a,u),l=i(t.inputs,!1),f=n.formatOutput(l,e.data);return o.args=c(t.inputs,s,f),o}},f=function(t,e){for(var n=0;n<t.length;n++){var r=o.eventSignatureFromAscii(t[n].name);if(r===e.topics[0])return t[n]}return void 0};e.exports={inputParser:s,outputParser:l,getMatchingEvent:f}},{"../solidity/abi":1,"../utils/utils":6,"./signature":21}],13:[function(t,e){var n=t("../utils/utils"),r=function(t){return!!t&&"function"==typeof t.newFilter&&"function"==typeof t.getLogs&&"function"==typeof t.uninstallFilter&&"function"==typeof t.startPolling&&"function"==typeof t.stopPolling},o=function(t){if("string"==typeof t)return t;t=t||{},t.topic&&(console.warn('"topic" is deprecated, is "topics" instead'),t.topics=t.topic),t.earliest&&(console.warn('"earliest" is deprecated, is "fromBlock" instead'),t.fromBlock=t.earliest),t.latest&&(console.warn('"latest" is deprecated, is "toBlock" instead'),t.toBlock=t.latest),t.topics instanceof Array&&(t.topics=t.topics.map(function(t){return n.toHex(t)}));var e=function(t){return null===t||"undefined"==typeof t?void 0:"latest"===t||"pending"===t?t:n.toHex(t)};return{fromBlock:e(t.fromBlock),toBlock:e(t.toBlock),to:t.to,address:t.address,topics:t.topics}},i=function(t,e,i){if(!r(e))return void console.error("filter implemenation is invalid");t=o(t);var a=[],u=e.newFilter(t),s=function(t){t.forEach(function(t){t=i?i(t):t,a.forEach(function(e){e(t)})})};e.startPolling(u,s,e.uninstallFilter);var c=function(t){a.push(t)},l=function(){e.stopPolling(u),e.uninstallFilter(u),a=[]},f=function(){var t=e.getLogs(u);return n.isArray(t)?t.map(function(t){return i?i(t):t}):t};return{watch:c,stopWatching:l,get:f,changed:function(){return console.warn("watch().changed() is deprecated please use filter().watch() instead."),c.apply(this,arguments)},arrived:function(){return console.warn("watch().arrived() is deprecated please use filter().watch() instead."),c.apply(this,arguments)},happened:function(){return console.warn("watch().happened() is deprecated please use filter().watch() instead."),c.apply(this,arguments)},uninstall:function(){return console.warn("watch().uninstall() is deprecated please use filter().stopWatching() instead."),l.apply(this,arguments)},messages:function(){return console.warn("watch().messages() is deprecated please use filter().get() instead."),f.apply(this,arguments)},logs:function(){return console.warn("watch().logs() is deprecated please use filter().get() instead."),f.apply(this,arguments)}}};e.exports=i},{"../utils/utils":6}],14:[function(t,e){var n=t("../utils/utils"),r=function(t){return n.toBigNumber(t)},o=function(t){return t.code&&(t.data=t.code,delete t.code),["gasPrice","gas","value"].forEach(function(e){t[e]=n.fromDecimal(t[e])}),t},i=function(t){return t.gas=n.toDecimal(t.gas),t.gasPrice=n.toBigNumber(t.gasPrice),t.value=n.toBigNumber(t.value),t},a=function(t){return t.code&&(t.data=t.code,delete t.code),t},u=function(t){return t.gasLimit=n.toDecimal(t.gasLimit),t.gasUsed=n.toDecimal(t.gasUsed),t.size=n.toDecimal(t.size),t.timestamp=n.toDecimal(t.timestamp),t.number=n.toDecimal(t.number),t.minGasPrice=n.toBigNumber(t.minGasPrice),t.difficulty=n.toBigNumber(t.difficulty),t.totalDifficulty=n.toBigNumber(t.totalDifficulty),t.transactions instanceof Array&&t.transactions.forEach(function(t){return n.isString(t)?void 0:i(t)}),t},s=function(t){return t.blockNumber=n.toDecimal(t.blockNumber),t.transactionIndex=n.toDecimal(t.transactionIndex),t.logIndex=n.toDecimal(t.logIndex),t},c=function(t){return t.payload=n.toHex(t.payload),t.ttl=n.fromDecimal(t.ttl),t.priority=n.fromDecimal(t.priority),t.topics instanceof Array||(t.topics=[t.topics]),t.topics=t.topics.map(function(t){return n.fromAscii(t)}),t},l=function(t){if(t.expiry=n.toDecimal(t.expiry),t.sent=n.toDecimal(t.sent),t.ttl=n.toDecimal(t.ttl),t.workProved=n.toDecimal(t.workProved),t.payloadRaw=t.payload,t.payload=n.toAscii(t.payload),0===t.payload.indexOf("{")||0===t.payload.indexOf("["))try{t.payload=JSON.parse(t.payload)}catch(e){}return t.topics=t.topics.map(function(t){return n.toAscii(t)}),t};e.exports={convertToBigNumber:r,inputTransactionFormatter:o,outputTransactionFormatter:i,inputCallFormatter:a,outputBlockFormatter:u,outputLogFormatter:s,inputPostFormatter:c,outputPostFormatter:l}},{"../utils/utils":6}],15:[function(t,e){var n=t("xmlhttprequest").XMLHttpRequest,r=function(t){this.name="HTTP",this.host=t||"http://localhost:8080"};r.prototype.send=function(t,e){var r=new n;if("function"!=typeof e){if(r.open("POST",this.host,!1),r.send(JSON.stringify(t)),200!==r.status)return;return JSON.parse(r.responseText)}r.onreadystatechange=function(){if(4===r.readyState){var t="";try{t=JSON.parse(r.responseText)}catch(n){t=n}e(t,r.status)}},r.open("POST",this.host,!0),r.send(JSON.stringify(t))},e.exports=r},{xmlhttprequest:4}],16:[function(t,e){var n=1,r=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:n++}},o=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},i=function(t){return t.map(function(t){return r(t.method,t.params)})};e.exports={toPayload:r,isValidResponse:o,toBatchPayload:i}},{}],17:[function(t,e){var n=t("../utils/utils"),r=[],o=[{name:"listening",getter:"net_listening"},{name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal}];e.exports={methods:r,properties:o}},{"../utils/utils":6}],18:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],19:[function(t,e){var n=t("./jsonrpc"),r=t("../utils/config"),o=function(){var t,e=[],o=null,i=function(e,r){"function"==typeof e.inputFormatter?e.params=Array.prototype.map.call(e.params,function(t,n){return!e.addDefaultblock||n+1<e.addDefaultblock?e.inputFormatter(t):t}):e.inputFormatter instanceof Array&&(e.params=Array.prototype.map.call(e.inputFormatter,function(t,n){return!e.addDefaultblock||n+1<e.addDefaultblock?t(e.params[n]):e.params[n]}));var o=n.toPayload(e.method,e.params);if(!t)return console.error("provider is not set"),null;if("function"!=typeof r||"HTTP"!==t.name){var i=t.send(o);return n.isValidResponse(i)?"function"==typeof e.outputFormatter?e.outputFormatter(i.result):i.result:("object"==typeof i&&i.error&&i.error.message&&console.error(i.error.message),null)}t.send(o,function(t,o){return n.isValidResponse(t)?void r(null,"function"==typeof e.outputFormatter?e.outputFormatter(t.result):t.result):("object"==typeof t&&t.error&&t.error.message?(console.error(t.error.message),r(t.error)):r(new Error({status:o,error:t,message:"Bad Request"})),null)})},a=function(e){t=e},u=function(t,n,r,o){e.push({data:t,id:n,callback:r,uninstall:o})},s=function(t){for(var n=e.length;n--;){var r=e[n];r.id===t&&e.splice(n,1)}},c=function(){e.forEach(function(t){t.uninstall(t.id)}),e=[],o&&(clearTimeout(o),o=null),l()},l=function(){e.forEach(function(t){i(t.data,function(e,n){n instanceof Array&&0!==n.length&&t.callback(n)})}),o=setTimeout(l,r.ETH_POLLING_TIMEOUT)};return l(),{send:i,setProvider:a,startPolling:u,stopPolling:s,reset:c}};e.exports=o},{"../utils/config":5,"./jsonrpc":16}],20:[function(t,e){var n=t("./formatters"),r=function(){return[{name:"post",call:"shh_post",inputFormatter:n.inputPostFormatter},{name:"newIdentity",call:"shh_newIdentity"},{name:"hasIdentity",call:"shh_hasIdentity"},{name:"newGroup",call:"shh_newGroup"},{name:"addToGroup",call:"shh_addToGroup"},{name:"haveIdentity",call:"shh_haveIdentity",newMethod:"shh.hasIdentity"}]};e.exports={methods:r}},{"./formatters":14}],21:[function(t,e){var n=t("../web3"),r=t("../utils/config"),o=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*r.ETH_SIGNATURE_LENGTH)},i=function(t){return n.sha3(n.fromAscii(t))};e.exports={functionSignatureFromAscii:o,eventSignatureFromAscii:i}},{"../utils/config":5,"../web3":8}],22:[function(t,e){var n=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"};return[{name:"newFilter",call:t},{name:"uninstallFilter",call:"eth_uninstallFilter"},{name:"getLogs",call:"eth_getFilterLogs"}]},r=function(){return[{name:"newFilter",call:"shh_newFilter"},{name:"uninstallFilter",call:"shh_uninstallFilter"},{name:"getLogs",call:"shh_getMessages"}]};e.exports={eth:n,shh:r}},{}],23:[function(){},{}],"bignumber.js":[function(t,e){"use strict";e.exports=BigNumber},{}],"ethereum.js":[function(t,e){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":8,"./lib/web3/contract":9,"./lib/web3/httpprovider":15,"./lib/web3/qtsync":18}]},{},["ethereum.js"]);`
+const Ethereum_JS = `
+require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=t("./types"),i=t("./formatters"),a=function(t){throw new Error("parser does not support type: "+t)},s=function(t){return"[]"===t.slice(-2)},u=function(t,e){return s(t)||"bytes"===t?i.formatInputInt(e.length):""},c=o.inputTypes(),l=function(t,e){var n="",r="",o="";return t.forEach(function(t,r){n+=u(t.type,e[r])}),t.forEach(function(n,i){for(var u=!1,l=0;l<c.length&&!u;l++)u=c[l].type(t[i].type,e[i]);u||a(t[i].type);var f=c[l-1].format;s(t[i].type)?o+=e[i].reduce(function(t,e){return t+f(e)},""):"bytes"===t[i].type?o+=f(e[i]):r+=f(e[i])}),n+=r+o},f=function(t){return s(t)||"bytes"===t?2*r.ETH_PADDING:0},p=o.outputTypes(),m=function(t,e){e=e.slice(2);var n=[],u=2*r.ETH_PADDING,c=t.reduce(function(t,e){return t+f(e.type)},0),l=e.slice(0,c);return e=e.slice(c),t.forEach(function(r,c){for(var f=!1,m=0;m<p.length&&!f;m++)f=p[m].type(t[c].type);f||a(t[c].type);var h=p[m-1].format;if(s(t[c].type)){var d=i.formatOutputUInt(l.slice(0,u));l=l.slice(u);for(var g=[],v=0;d>v;v++)g.push(h(e.slice(0,u))),e=e.slice(u);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(u),n.push(h(e.slice(0,u))),e=e.slice(u)):(n.push(h(e.slice(0,u))),e=e.slice(u))}),n},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:h,outputParser:d,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),r.padLeft(r.toTwosComplement(t).round().toString(16),e)},a=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},u=function(t){return i(new n(t).times(new n(2).pow(128)))},c=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},l=function(t){return t=t||"0",c(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},f=function(t){return t=t||"0",new n(t,16)},p=function(t){return l(t).dividedBy(new n(2).pow(128))},m=function(t){return f(t).dividedBy(new n(2).pow(128))},h=function(t){return"0x"+t},d=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return r.toAscii(t)},v=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:i,formatInputString:a,formatInputBool:s,formatInputReal:u,formatOutputInt:l,formatOutputUInt:f,formatOutputReal:p,formatOutputUReal:m,formatOutputHash:h,formatOutputBool:d,formatOutputString:g,formatOutputAddress:v}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},i=function(t,e){for(var n=!1,r=0;r<t.length&&!n;r++)n=e(t[r]);return n?r-1:-1},a=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},s=function(t){for(var e="",n=0;n<t.length;n++){var r=t.charCodeAt(n).toString(16);e+=r.length<2?"0"+r:r}return e},u=function(t,e){e=void 0===e?0:e;for(var n=s(t);n.length<2*e;)n+="00";return"0x"+n},c=function(t){var e=t.indexOf("(");return-1!==e?t.substr(0,e):t},l=function(t){var e=t.indexOf("(");return-1!==e?t.substr(e+1,t.length-1-(e+1)).replace(" ",""):""},f=function(t){return t.filter(function(t){return"function"===t.type})},p=function(t){return t.filter(function(t){return"event"===t.type})},m=function(t){return b(t).toNumber()},h=function(t){var e=b(t),n=e.toString(16);return e.lessThan(0)?"-0x"+n.substr(1):"0x"+n},d=function(t){if(O(t))return h(+t);if(F(t))return h(t);if(N(t))return u(JSON.stringify(t));if(_(t)){if(0===t.indexOf("-0x"))return h(t);if(!isFinite(t))return u(t)}return h(t)},g=function(t){t=t?t.toLowerCase():"ether";var e=r[t];if(void 0===e)throw new Error("This unit doesn't exists, please use the one of the following units"+JSON.stringify(r,null,2));return new n(e,10)},v=function(t,e){var n=b(t).dividedBy(g(e));return F(t)?n:n.toString(10)},y=function(t,e){var n=b(t).times(g(e));return F(t)?n:n.toString(10)},b=function(t){return t=t||0,F(t)?t:!_(t)||0!==t.indexOf("0x")&&0!==t.indexOf("-0x")?new n(t.toString(10),10):new n(t.replace("0x",""),16)},w=function(t){var e=b(t);return e.lessThan(0)?new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(e).plus(1):e},x=function(t){return/^0x[0-9a-f]{40}$/.test(t)},I=function(t){return x(t)?t:/^[0-9a-f]{40}$/.test(t)?"0x"+t:"0x"+o(d(t).substr(2),40)},F=function(t){return t instanceof n||t&&t.constructor&&"BigNumber"===t.constructor.name},_=function(t){return"string"==typeof t||t&&t.constructor&&"String"===t.constructor.name},T=function(t){return"function"==typeof t},N=function(t){return"object"==typeof t},O=function(t){return"boolean"==typeof t},B=function(t){return t instanceof Array},D=function(t){try{return!!JSON.parse(t)}catch(e){return!1}};e.exports={padLeft:o,findIndex:i,toHex:d,toDecimal:m,fromDecimal:h,toAscii:a,fromAscii:u,extractDisplayName:c,extractTypeName:l,filterFunctions:f,filterEvents:p,toWei:y,fromWei:v,toBigNumber:b,toTwosComplement:w,toAddress:I,isBigNumber:F,isAddress:x,isFunction:T,isString:_,isObject:N,isBoolean:O,isArray:B,isJson:D}},{"bignumber.js":"bignumber.js"}],7:[function(t,e){e.exports={version:"0.2.2"}},{}],8:[function(t,e){var n=t("./version.json"),r=t("./web3/net"),o=t("./web3/eth"),i=t("./web3/db"),a=t("./web3/shh"),s=t("./web3/watches"),u=t("./web3/filter"),c=t("./utils/utils"),l=t("./web3/formatters"),f=t("./web3/requestmanager"),p=t("./utils/config"),m=t("./web3/method"),h=t("./web3/property"),d=[new m({name:"sha3",call:"web3_sha3",params:1})],g=[new h({name:"version.client",getter:"web3_clientVersion"}),new h({name:"version.network",getter:"net_version",inputFormatter:c.toDecimal}),new h({name:"version.ethereum",getter:"eth_version",inputFormatter:c.toDecimal}),new h({name:"version.whisper",getter:"shh_version",inputFormatter:c.toDecimal})],v=function(t,e){e.forEach(function(e){e.attachToObject(t)})},y=function(t,e){e.forEach(function(e){e.attachToObject(t)})},b={};b.providers={},b.version={},b.version.api=n.version,b.eth={},b.eth.filter=function(t,e,n,r){return t._isEvent?t(e,n):new u(t,s.eth(),r||l.outputLogFormatter)},b.shh={},b.shh.filter=function(t){return new u(t,s.shh(),l.outputPostFormatter)},b.net={},b.db={},b.setProvider=function(t){f.getInstance().setProvider(t)},b.reset=function(){f.getInstance().reset()},b.toHex=c.toHex,b.toAscii=c.toAscii,b.fromAscii=c.fromAscii,b.toDecimal=c.toDecimal,b.fromDecimal=c.fromDecimal,b.toBigNumber=c.toBigNumber,b.toWei=c.toWei,b.fromWei=c.fromWei,b.isAddress=c.isAddress,Object.defineProperty(b.eth,"defaultBlock",{get:function(){return p.ETH_DEFAULTBLOCK},set:function(t){return p.ETH_DEFAULTBLOCK=t,p.ETH_DEFAULTBLOCK}}),v(b,d),y(b,g),v(b.net,r.methods),y(b.net,r.properties),v(b.eth,o.methods),y(b.eth,o.properties),v(b.db,i.methods),v(b.shh,a.methods),e.exports=b},{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/db":10,"./web3/eth":12,"./web3/filter":14,"./web3/formatters":15,"./web3/method":18,"./web3/net":19,"./web3/property":20,"./web3/requestmanager":22,"./web3/shh":23,"./web3/watches":25}],9:[function(t,e){function n(t,e){t.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return u(n),c(n,t,e),l(n,t,e),f(n,t,e),n}var r=t("../web3"),o=t("../solidity/abi"),i=t("../utils/utils"),a=t("./event"),s=t("./signature"),u=function(t){t.call=function(e){return t._isTransaction=!1,t._options=e,t},t.sendTransaction=function(e){return t._isTransaction=!0,t._options=e,t}},c=function(t,e,n){var a=o.inputParser(e),u=o.outputParser(e);i.filterFunctions(e).forEach(function(e){var o=i.extractDisplayName(e.name),c=i.extractTypeName(e.name),l=function(){var i=Array.prototype.slice.call(arguments),l=s.functionSignatureFromAscii(e.name),f=a[o][c].apply(null,i),p=t._options||{};p.to=n,p.data=l+f;var m=t._isTransaction===!0||t._isTransaction!==!1&&!e.constant,h=p.collapse!==!1;if(t._options={},t._isTransaction=null,m)return void r.eth.sendTransaction(p);var d=r.eth.call(p),g=u[o][c](d);return h&&(1===g.length?g=g[0]:0===g.length&&(g=null)),g};void 0===t[o]&&(t[o]=l),t[o][c]=l})},l=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=a.outputParser(n);return r(t)},Object.defineProperty(t,"topics",{get:function(){return i.filterEvents(e).map(function(t){return s.eventSignatureFromAscii(t.name)})}})},f=function(t,e,n){i.filterEvents(e).forEach(function(e){var o=function(){var t=Array.prototype.slice.call(arguments),o=s.eventSignatureFromAscii(e.name),i=a.inputParser(n,o,e),u=i.apply(null,t),c=function(t){var n=a.outputParser(e);return n(t)};return r.eth.filter(u,void 0,void 0,c)};o._isEvent=!0;var u=i.extractDisplayName(e.name),c=i.extractTypeName(e.name);void 0===t[u]&&(t[u]=o),t[u][c]=o})},p=function(t){return n.bind(null,t)};e.exports=p},{"../solidity/abi":1,"../utils/utils":6,"../web3":8,"./event":13,"./signature":24}],10:[function(t,e){var n=t("./method"),r=new n({name:"putString",call:"db_putString",params:3}),o=new n({name:"getString",call:"db_getString",params:2}),i=new n({name:"putHex",call:"db_putHex",params:3}),a=new n({name:"getHex",call:"db_getHex",params:2}),s=[r,o,i,a];e.exports={methods:s}},{"./method":18}],11:[function(t,e){var n=t("../utils/utils");e.exports={InvalidNumberOfParams:new Error("Invalid number of input parameters"),InvalidProvider:new Error("Providor not set or invalid"),InvalidResponse:function(t){var e="Invalid JSON RPC response";return n.isObject(t)&&t.error&&t.error.message&&(e=t.error.message),new Error(e)}}},{"../utils/utils":6}],12:[function(t,e){"use strict";var n=t("./formatters"),r=t("../utils/utils"),o=t("./method"),i=t("./property"),a=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockByHash":"eth_getBlockByNumber"},s=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getTransactionByBlockHashAndIndex":"eth_getTransactionByBlockNumberAndIndex"},u=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleByBlockHashAndIndex":"eth_getUncleByBlockNumberAndIndex"},c=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockTransactionCountByHash":"eth_getBlockTransactionCountByNumber"},l=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleCountByBlockHash":"eth_getUncleCountByBlockNumber"},f=new o({name:"getBalance",call:"eth_getBalance",params:2,inputFormatter:[r.toAddress,n.inputDefaultBlockNumberFormatter],outputFormatter:n.outputBigNumberFormatter}),p=new o({name:"getStorageAt",call:"eth_getStorageAt",params:3,inputFormatter:[null,r.toHex,n.inputDefaultBlockNumberFormatter]}),m=new o({name:"getCode",call:"eth_getCode",params:2,inputFormatter:[r.toAddress,n.inputDefaultBlockNumberFormatter]}),h=new o({name:"getBlock",call:a,params:2,inputFormatter:[r.toHex,function(t){return!!t}],outputFormatter:n.outputBlockFormatter}),d=new o({name:"getUncle",call:u,params:3,inputFormatter:[r.toHex,r.toHex,function(t){return!!t}],outputFormatter:n.outputBlockFormatter}),g=new o({name:"getCompilers",call:"eth_getCompilers",params:0}),v=new o({name:"getBlockTransactionCount",call:c,params:1,inputFormatter:[r.toHex],outputFormatter:r.toDecimal}),y=new o({name:"getBlockUncleCount",call:l,params:1,inputFormatter:[r.toHex],outputFormatter:r.toDecimal}),b=new o({name:"getTransaction",call:"eth_getTransactionByHash",params:1,outputFormatter:n.outputTransactionFormatter}),w=new o({name:"getTransactionFromBlock",call:s,params:2,inputFormatter:[r.toHex,r.toHex],outputFormatter:n.outputTransactionFormatter}),x=new o({name:"getTransactionCount",call:"eth_getTransactionCount",params:2,inputFormatter:[null,n.inputDefaultBlockNumberFormatter],outputFormatter:r.toDecimal}),I=new o({name:"sendTransaction",call:"eth_sendTransaction",params:1,inputFormatter:[n.inputTransactionFormatter]}),F=new o({name:"call",call:"eth_call",params:2,inputFormatter:[n.inputTransactionFormatter,n.inputDefaultBlockNumberFormatter]}),_=new o({name:"compile.solidity",call:"eth_compileSolidity",params:1}),T=new o({name:"compile.lll",call:"eth_compileLLL",params:1}),N=new o({name:"compile.serpent",call:"eth_compileSerpent",params:1}),O=new o({name:"flush",call:"eth_flush",params:0}),B=[f,p,m,h,d,g,v,y,b,w,x,F,I,_,T,N,O],D=[new i({name:"coinbase",getter:"eth_coinbase"}),new i({name:"mining",getter:"eth_mining"}),new i({name:"gasPrice",getter:"eth_gasPrice",outputFormatter:n.inputNumberFormatter}),new i({name:"accounts",getter:"eth_accounts"}),new i({name:"blockNumber",getter:"eth_blockNumber",outputFormatter:r.toDecimal})];e.exports={methods:B,properties:D}},{"../utils/utils":6,"./formatters":15,"./method":18,"./property":20}],13:[function(t,e){var n=t("../solidity/abi"),r=t("../utils/utils"),o=t("./signature"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},a=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},s=function(t,e){return Object.keys(e).map(function(r){var o=[a(i(t.inputs,!0),r)],s=e[r];return s instanceof Array?s.map(function(t){return n.formatInput(o,[t])}):"0x"+n.formatInput(o,[s])})},u=function(t,e,n){return function(r,o){var i=o||{};return i.address=t,i.topics=[],i.topics.push(e),r&&(i.topics=i.topics.concat(s(n,r))),i}},c=function(t,e,n){var r=e.slice(),o=n.slice();return t.reduce(function(t,e){var n;return n=e.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[e.name]=n,t},{})},l=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,hash:e.hash,args:{}};if(!e.topics)return o;e.data=e.data||"";var a=i(t.inputs,!0),s="0x"+e.topics.slice(1,e.topics.length).map(function(t){return t.slice(2)}).join(""),u=n.formatOutput(a,s),l=i(t.inputs,!1),f=n.formatOutput(l,e.data);return o.args=c(t.inputs,u,f),o}},f=function(t,e){for(var n=0;n<t.length;n++){var r=o.eventSignatureFromAscii(t[n].name);if(r===e.topics[0])return t[n]}return void 0};e.exports={inputParser:u,outputParser:l,getMatchingEvent:f}},{"../solidity/abi":1,"../utils/utils":6,"./signature":24}],14:[function(t,e){var n=t("./requestmanager"),r=t("./formatters"),o=t("../utils/utils"),i=function(t){return o.isString(t)?t:(t=t||{},t.topics=t.topics||[],t.topics=t.topics.map(function(t){return o.toHex(t)}),{topics:t.topics,to:t.to,address:t.address,fromBlock:r.inputBlockNumberFormatter(t.fromBlock),toBlock:r.inputBlockNumberFormatter(t.toBlock)})},a=function(t,e,n){var r={};e.forEach(function(t){t.attachToObject(r)}),this.options=i(t),this.implementation=r,this.callbacks=[],this.formatter=n,this.filterId=this.implementation.newFilter(this.options)};a.prototype.watch=function(t){this.callbacks.push(t);var e=this,r=function(t,n){return t?e.callbacks.forEach(function(e){e(t)}):void n.forEach(function(t){t=e.formatter?e.formatter(t):t,e.callbacks.forEach(function(e){e(null,t)})})};n.getInstance().startPolling({method:this.implementation.poll.call,params:[this.filterId]},this.filterId,r,this.stopWatching.bind(this))},a.prototype.stopWatching=function(){n.getInstance().stopPolling(this.filterId),this.implementation.uninstallFilter(this.filterId),this.callbacks=[]},a.prototype.get=function(){var t=this.implementation.getLogs(this.filterId),e=this;return t.map(function(t){return e.formatter?e.formatter(t):t})},e.exports=a},{"../utils/utils":6,"./formatters":15,"./requestmanager":22}],15:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=function(t){return n.toBigNumber(t)},i=function(t){return"latest"===t||"pending"===t||"earliest"===t},a=function(t){return void 0===t?r.ETH_DEFAULTBLOCK:s(t)},s=function(t){return void 0===t?void 0:i(t)?t:n.toHex(t)},u=function(t){return t.code&&(t.data=t.code,delete t.code),["gasPrice","gas","value"].filter(function(e){return void 0!==t[e]}).forEach(function(e){t[e]=n.fromDecimal(t[e])}),t},c=function(t){return t.blockNumber=n.toDecimal(t.blockNumber),t.transactionIndex=n.toDecimal(t.transactionIndex),t.gas=n.toDecimal(t.gas),t.gasPrice=n.toBigNumber(t.gasPrice),t.value=n.toBigNumber(t.value),t},l=function(t){return t.gasLimit=n.toDecimal(t.gasLimit),t.gasUsed=n.toDecimal(t.gasUsed),t.size=n.toDecimal(t.size),t.timestamp=n.toDecimal(t.timestamp),t.number=n.toDecimal(t.number),t.minGasPrice=n.toBigNumber(t.minGasPrice),t.difficulty=n.toBigNumber(t.difficulty),t.totalDifficulty=n.toBigNumber(t.totalDifficulty),n.isArray(t.transactions)&&t.transactions.forEach(function(t){return n.isString(t)?void 0:c(t)}),t},f=function(t){return null===t?null:(t.blockNumber=n.toDecimal(t.blockNumber),t.transactionIndex=n.toDecimal(t.transactionIndex),t.logIndex=n.toDecimal(t.logIndex),t)},p=function(t){return t.payload=n.toHex(t.payload),t.ttl=n.fromDecimal(t.ttl),t.priority=n.fromDecimal(t.priority),n.isArray(t.topics)||(t.topics=[t.topics]),t.topics=t.topics.map(function(t){return n.fromAscii(t)}),t},m=function(t){return t.expiry=n.toDecimal(t.expiry),t.sent=n.toDecimal(t.sent),t.ttl=n.toDecimal(t.ttl),t.workProved=n.toDecimal(t.workProved),t.payloadRaw=t.payload,t.payload=n.toAscii(t.payload),n.isJson(t.payload)&&(t.payload=JSON.parse(t.payload)),t.topics=t.topics.map(function(t){return n.toAscii(t)}),t};e.exports={inputDefaultBlockNumberFormatter:a,inputBlockNumberFormatter:s,inputTransactionFormatter:u,inputPostFormatter:p,outputBigNumberFormatter:o,outputTransactionFormatter:c,outputBlockFormatter:l,outputLogFormatter:f,outputPostFormatter:m}},{"../utils/config":5,"../utils/utils":6}],16:[function(t,e){"use strict";var n=t("xmlhttprequest").XMLHttpRequest,r=function(t){this.host=t||"http://localhost:8080"};r.prototype.send=function(t){var e=new n;return e.open("POST",this.host,!1),e.send(JSON.stringify(t)),JSON.parse(e.responseText)},r.prototype.sendAsync=function(t,e){var r=new n;r.onreadystatechange=function(){4===r.readyState&&e(null,JSON.parse(r.responseText))},r.open("POST",this.host,!0),r.send(JSON.stringify(t))},e.exports=r},{xmlhttprequest:4}],17:[function(t,e){var n=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};n.getInstance=function(){var t=new n;return t},n.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},n.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},n.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=n},{}],18:[function(t,e){var n=t("./requestmanager"),r=t("../utils/utils"),o=t("./errors"),i=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};i.prototype.getCall=function(t){return r.isFunction(this.call)?this.call(t):this.call},i.prototype.extractCallback=function(t){return r.isFunction(t[t.length-1])?t.pop():null},i.prototype.validateArgs=function(t){if(t.length!==this.params)throw o.InvalidNumberOfParams},i.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},i.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},i.prototype.attachToObject=function(t){var e=this.send.bind(this);e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},i.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},i.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return n.getInstance().sendAsync(t,function(n,r){t.callback(null,e.formatOutput(r))})}return this.formatOutput(n.getInstance().send(t))},e.exports=i},{"../utils/utils":6,"./errors":11,"./requestmanager":22}],19:[function(t,e){var n=t("../utils/utils"),r=t("./property"),o=[],i=[new r({name:"listening",getter:"net_listening"}),new r({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:o,properties:i}},{"../utils/utils":6,"./property":20}],20:[function(t,e){var n=t("./requestmanager"),r=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};r.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},r.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},r.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},r.prototype.get=function(){return this.formatOutput(n.getInstance().send({method:this.getter}))},r.prototype.set=function(t){return n.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=r},{"./requestmanager":22}],21:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],22:[function(t,e){var n=t("./jsonrpc"),r=t("../utils/utils"),o=t("../utils/config"),i=t("./errors"),a=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};a.getInstance=function(){var t=new a;return t},a.prototype.send=function(t){if(!this.provider)return console.error(i.InvalidProvider),null;var e=n.getInstance().toPayload(t.method,t.params),r=this.provider.send(e);if(!n.getInstance().isValidResponse(r))throw i.InvalidResponse(r);return r.result},a.prototype.sendAsync=function(t,e){if(!this.provider)return e(i.InvalidProvider);var r=n.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(r,function(t,r){return t?e(t):n.getInstance().isValidResponse(r)?void e(null,r.result):e(i.InvalidResponse(r))})},a.prototype.setProvider=function(t){this.provider=t},a.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},a.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},a.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},a.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(i.InvalidProvider);var t=n.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,o){if(!t){if(!r.isArray(o))throw i.InvalidResponse(o);o.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var e=n.getInstance().isValidResponse(t);return e||t.callback(i.InvalidResponse(t)),e}).filter(function(t){return r.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=a},{"../utils/config":5,"../utils/utils":6,"./errors":11,"./jsonrpc":17}],23:[function(t,e){var n=t("./method"),r=t("./formatters"),o=new n({name:"post",call:"shh_post",params:1,inputFormatter:r.inputPostFormatter}),i=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),a=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),s=new n({name:"newGroup",call:"shh_newGroup",params:0}),u=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),c=[o,i,a,s,u];e.exports={methods:c}},{"./formatters":15,"./method":18}],24:[function(t,e){var n=t("../web3"),r=t("../utils/config"),o=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*r.ETH_SIGNATURE_LENGTH)},i=function(t){return n.sha3(n.fromAscii(t))};e.exports={functionSignatureFromAscii:o,eventSignatureFromAscii:i}},{"../utils/config":5,"../web3":8}],25:[function(t,e){var n=t("./method"),r=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new n({name:"poll",call:"eth_getFilterChanges",params:1});return[e,r,o,i]},o=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1}),o=new n({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,r,o]};e.exports={eth:r,shh:o}},{"./method":18}],26:[function(){},{}],"bignumber.js":[function(t,e){"use strict";e.exports=BigNumber},{}],"ethereum.js":[function(t,e){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":8,"./lib/web3/contract":9,"./lib/web3/httpprovider":16,"./lib/web3/qtsync":21}]},{},["ethereum.js"]);`
diff --git a/jsre/pp_js.go b/jsre/pp_js.go
index 3352f23ce..0b22afe6d 100644
--- a/jsre/pp_js.go
+++ b/jsre/pp_js.go
@@ -23,18 +23,28 @@ function pp(object, indent) {
}
}
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") {
str += "{\n";
- indent += " ";
- var last = Object.keys(object).pop()
- for(var k in object) {
- str += indent + k + ": " + pp(object[k], indent);
+ indent += " ";
+ var last = Object.getOwnPropertyNames(object).pop()
+ Object.getOwnPropertyNames(object).forEach(function (k) {
+ str += indent + k + ": ";
+ try {
+ str += pp(object[k], indent);
+ } catch (e) {
+ str += pp(e, indent);
+ }
if(k !== last) {
str += ",";
}
- str += "\n";
- }
+
+ str += "\n";
+ });
str += indent.substr(2, indent.length) + "}";
} else if(typeof(object) === "string") {
str += "\033[32m'" + object + "'";
@@ -43,7 +53,7 @@ function pp(object, indent) {
} else if(typeof(object) === "number") {
str += "\033[31m" + object;
} else if(typeof(object) === "function") {
- str += "\033[35m[Function]";
+ str += "\033[35m[Function]";
} else {
str += object;
}
@@ -53,6 +63,11 @@ function pp(object, indent) {
return str;
}
+var isBigNumber = function (object) {
+ return typeof BigNumber !== 'undefined' && object instanceof BigNumber;
+};
+
+
function prettyPrint(/* */) {
var args = arguments;
var ret = "";
diff --git a/miner/agent.go b/miner/agent.go
index c650fa2f3..ad08e3841 100644
--- a/miner/agent.go
+++ b/miner/agent.go
@@ -60,7 +60,7 @@ out:
}
}
- close(self.quitCurrentOp)
+ //close(self.quitCurrentOp)
done:
// Empty channel
for {
diff --git a/miner/worker.go b/miner/worker.go
index e3680dea3..4385b51c8 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -171,6 +171,8 @@ func (self *worker) wait() {
}
self.mux.Post(core.NewMinedBlockEvent{block})
+ minerlogger.Infof("🔨 Mined block #%v", block.Number())
+
jsonlogger.LogJson(&logger.EthMinerNewBlock{
BlockHash: block.Hash().Hex(),
BlockNumber: block.Number(),
@@ -270,9 +272,9 @@ gasLimit:
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()
}
@@ -297,9 +299,6 @@ func (self *worker) commitUncle(uncle *types.Header) error {
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
}
diff --git a/p2p/discover/node.go b/p2p/discover/node.go
index e1130e0b5..99cb549a5 100644
--- a/p2p/discover/node.go
+++ b/p2p/discover/node.go
@@ -13,6 +13,8 @@ import (
"net/url"
"strconv"
"strings"
+ "sync"
+ "sync/atomic"
"time"
"github.com/ethereum/go-ethereum/crypto"
@@ -30,7 +32,8 @@ type Node struct {
DiscPort int // UDP listening port for discovery protocol
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 {
@@ -39,7 +42,6 @@ func newNode(id NodeID, addr *net.UDPAddr) *Node {
IP: addr.IP,
DiscPort: addr.Port,
TCPPort: addr.Port,
- active: time.Now(),
}
}
@@ -48,6 +50,20 @@ func (n *Node) isValid() bool {
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.
// Please see ParseNode for a description of the format.
func (n *Node) String() string {
@@ -304,3 +320,26 @@ func randomID(a NodeID, n int) (b NodeID) {
}
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
+}
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index 33b705a12..dbf86c084 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -14,9 +14,10 @@ import (
)
const (
- alpha = 3 // Kademlia concurrency factor
- bucketSize = 16 // Kademlia bucket size
- nBuckets = nodeIDBits + 1 // Number of buckets
+ alpha = 3 // Kademlia concurrency factor
+ bucketSize = 16 // Kademlia bucket size
+ nBuckets = nodeIDBits + 1 // Number of buckets
+ maxBondingPingPongs = 10
)
type Table struct {
@@ -24,27 +25,50 @@ type Table struct {
buckets [nBuckets]*bucket // index of known nodes by distance
nursery []*Node // bootstrap nodes
+ bondmu sync.Mutex
+ bonding map[NodeID]*bondproc
+ bondslots chan struct{} // limits total number of active bonding processes
+
net transport
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.
// it is an interface so we can test without opening lots of UDP
// sockets and without generating a private key.
type transport interface {
- ping(*Node) error
- findnode(e *Node, target NodeID) ([]*Node, error)
+ ping(NodeID, *net.UDPAddr) error
+ waitping(NodeID) error
+ findnode(toid NodeID, addr *net.UDPAddr, target NodeID) ([]*Node, error)
close()
}
// bucket contains nodes, ordered by their last activity.
+// the entry that was most recently active is the last element
+// in entries.
type bucket struct {
lastLookup time.Time
entries []*Node
}
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 {
tab.buckets[i] = new(bucket)
}
@@ -107,8 +131,8 @@ func (tab *Table) Lookup(target NodeID) []*Node {
asked[n.ID] = true
pendingQueries++
go func() {
- result, _ := tab.net.findnode(n, target)
- reply <- result
+ r, _ := tab.net.findnode(n.ID, n.addr(), target)
+ reply <- tab.bondall(r)
}()
}
}
@@ -116,13 +140,11 @@ func (tab *Table) Lookup(target NodeID) []*Node {
// we have asked all closest nodes, stop the search
break
}
-
// wait for the next reply
for _, n := range <-reply {
- cn := n
- if !seen[n.ID] {
+ if n != nil && !seen[n.ID] {
seen[n.ID] = true
- result.push(cn, bucketSize)
+ result.push(n, bucketSize)
}
}
pendingQueries--
@@ -145,8 +167,9 @@ func (tab *Table) refresh() {
result := tab.Lookup(randomID(tab.self.ID, ld))
if len(result) == 0 {
// bootstrap the table with a self lookup
+ all := tab.bondall(tab.nursery)
tab.mutex.Lock()
- tab.add(tab.nursery)
+ tab.add(all)
tab.mutex.Unlock()
tab.Lookup(tab.self.ID)
// TODO: the Kademlia paper says that we're supposed to perform
@@ -176,45 +199,105 @@ func (tab *Table) len() (n int) {
return n
}
-// bumpOrAdd updates the activity timestamp for the given node and
-// attempts to insert the node into a bucket. The returned Node might
-// not be part of the table. The caller must hold tab.mutex.
-func (tab *Table) bumpOrAdd(node NodeID, from *net.UDPAddr) (n *Node) {
- b := tab.buckets[logdist(tab.self.ID, node)]
- if n = b.bump(node); n == nil {
- n = newNode(node, from)
- if len(b.entries) == bucketSize {
- tab.pingReplace(n, b)
- } else {
- b.entries = append(b.entries, n)
+// bondall bonds with all given nodes concurrently and returns
+// those nodes for which bonding has probably succeeded.
+func (tab *Table) bondall(nodes []*Node) (result []*Node) {
+ rc := make(chan *Node, len(nodes))
+ for i := range nodes {
+ go func(n *Node) {
+ nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCPPort))
+ rc <- nn
+ }(nodes[i])
+ }
+ for _ = range nodes {
+ if n := <-rc; n != nil {
+ result = append(result, n)
}
}
- return n
+ return result
}
-func (tab *Table) pingReplace(n *Node, b *bucket) {
- old := b.entries[bucketSize-1]
- go func() {
- if err := tab.net.ping(old); err == nil {
- // it responded, we don't need to replace it.
- return
+// bond ensures the local node has a bond with the given remote node.
+// It also attempts to insert the node into the table if bonding succeeds.
+// The caller must not hold tab.mutex.
+//
+// A bond is must be established before sending findnode requests.
+// 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.
- tab.mutex.Lock()
- if len(b.entries) > 0 && b.entries[len(b.entries)-1] == old {
- // 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
+ n = w.n
+ if w.err != nil {
+ return nil, w.err
}
- 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.
-// The caller must hold tab.mutex.
-func (tab *Table) bump(node NodeID) {
- tab.buckets[logdist(tab.self.ID, node)].bump(node)
+func (tab *Table) pingreplace(new *Node, b *bucket) {
+ if len(b.entries) == bucketSize {
+ oldest := b.entries[bucketSize-1]
+ 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
@@ -240,17 +323,17 @@ outer:
}
}
-func (b *bucket) bump(id NodeID) *Node {
- for i, n := range b.entries {
- if n.ID == id {
- n.active = time.Now()
+func (b *bucket) bump(n *Node) bool {
+ for i := range b.entries {
+ if b.entries[i].ID == n.ID {
+ n.bumpActive()
// move it to the front
- copy(b.entries[1:], b.entries[:i+1])
+ copy(b.entries[1:], b.entries[:i])
b.entries[0] = n
- return n
+ return true
}
}
- return nil
+ return false
}
// nodesByDistance is a list of nodes, ordered by
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index 08faea68e..a98376bca 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -2,78 +2,109 @@ package discover
import (
"crypto/ecdsa"
- "errors"
"fmt"
"math/rand"
"net"
"reflect"
"testing"
"testing/quick"
- "time"
"github.com/ethereum/go-ethereum/crypto"
)
-func TestTable_bumpOrAddBucketAssign(t *testing.T) {
- tab := newTable(nil, NodeID{}, &net.UDPAddr{})
- for i := 1; i < len(tab.buckets); i++ {
- tab.bumpOrAdd(randomID(tab.self.ID, i), &net.UDPAddr{})
- }
- for i, b := range tab.buckets {
- if i > 0 && len(b.entries) != 1 {
- t.Errorf("bucket %d has %d entries, want 1", i, len(b.entries))
+func TestTable_pingReplace(t *testing.T) {
+ doit := func(newNodeIsResponding, lastInBucketIsResponding bool) {
+ transport := newPingRecorder()
+ tab := newTable(transport, NodeID{}, &net.UDPAddr{})
+ last := fillBucket(tab, 200)
+ pingSender := randomID(tab.self.ID, 200)
+
+ // 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
- // because the node replies to ping.
- new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{})
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+ 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 pinged != last.ID {
- t.Fatalf("pinged wrong node: %v\nwant %v", pinged, last.ID)
+ if lastInBucketIsResponding || !newNodeIsResponding {
+ if !contains(tab.buckets[200].entries, 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()
- defer tab.mutex.Unlock()
- if l := len(tab.buckets[200].entries); l != bucketSize {
- t.Errorf("wrong bucket size after bumpOrAdd: got %d, want %d", bucketSize, l)
- }
- 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")
- }
+ doit(true, true)
+ doit(false, true)
+ doit(false, true)
+ doit(false, false)
}
-func TestTable_bumpOrAddPingTimeout(t *testing.T) {
- tab := newTable(pingC(nil), NodeID{}, &net.UDPAddr{})
- last := fillBucket(tab, 200)
-
- // this bumpOrAdd should replace the last node
- // because the node does not reply to ping.
- new := tab.bumpOrAdd(randomID(tab.self.ID, 200), &net.UDPAddr{})
-
- // wait for async bucket update. damn. this needs to go away.
- time.Sleep(2 * time.Millisecond)
-
- tab.mutex.Lock()
- defer tab.mutex.Unlock()
- if l := len(tab.buckets[200].entries); l != bucketSize {
- t.Errorf("wrong bucket size after bumpOrAdd: got %d, want %d", bucketSize, l)
+func TestBucket_bumpNoDuplicates(t *testing.T) {
+ t.Parallel()
+ cfg := &quick.Config{
+ MaxCount: 1000,
+ Rand: quickrand,
+ Values: func(args []reflect.Value, rand *rand.Rand) {
+ // generate a random list of nodes. this will be the content of the bucket.
+ n := rand.Intn(bucketSize-1) + 1
+ nodes := make([]*Node, n)
+ for i := range nodes {
+ nodes[i] = &Node{ID: randomID(NodeID{}, 200)}
+ }
+ args[0] = reflect.ValueOf(nodes)
+ // generate random bump positions.
+ 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) {
- t.Error("new entry was not added")
+ if err := quick.Check(prop, cfg); err != nil {
+ t.Error(err)
}
}
@@ -85,44 +116,27 @@ func fillBucket(tab *Table, ld int) (last *Node) {
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")
}
-func (t pingC) close() {
+func (t *pingRecorder) close() {
panic("close called on pingRecorder")
}
-func (t pingC) ping(n *Node) error {
- if t == nil {
- return errTimeout
- }
- t <- n.ID
- return nil
+func (t *pingRecorder) waitping(from NodeID) error {
+ return nil // remote always pings
}
-
-func TestTable_bump(t *testing.T) {
- tab := newTable(nil, NodeID{}, &net.UDPAddr{})
-
- // add an old entry and two recent ones
- oldactive := time.Now().Add(-2 * time.Minute)
- 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")
+func (t *pingRecorder) ping(toid NodeID, toaddr *net.UDPAddr) error {
+ t.pinged[toid] = true
+ if t.responding[toid] {
+ return nil
+ } else {
+ return errTimeout
}
}
@@ -210,7 +224,7 @@ func TestTable_Lookup(t *testing.T) {
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
}
// 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)
t.Logf("results:")
@@ -238,16 +252,16 @@ type findnodeOracle struct {
target NodeID
}
-func (t findnodeOracle) findnode(n *Node, target NodeID) ([]*Node, error) {
- t.t.Logf("findnode query at dist %d", n.DiscPort)
+func (t findnodeOracle) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
+ t.t.Logf("findnode query at dist %d", toaddr.Port)
// current log distance is encoded in port number
var result []*Node
- switch n.DiscPort {
+ switch toaddr.Port {
case 0:
panic("query to node at distance 0")
default:
// TODO: add more randomness to distances
- next := n.DiscPort - 1
+ next := toaddr.Port - 1
for i := 0; i < bucketSize; i++ {
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) {
return result, nil
}
-func (t findnodeOracle) close() {}
-
-func (t findnodeOracle) ping(n *Node) error {
- return errors.New("ping is not supported by this transport")
-}
+func (t findnodeOracle) close() {}
+func (t findnodeOracle) waitping(from NodeID) error { return nil }
+func (t findnodeOracle) ping(toid NodeID, toaddr *net.UDPAddr) error { return nil }
func hasDuplicates(slice []*Node) bool {
seen := make(map[NodeID]bool)
diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go
index 69e9f3c2e..e9ede1397 100644
--- a/p2p/discover/udp.go
+++ b/p2p/discover/udp.go
@@ -16,13 +16,18 @@ import (
var log = logger.NewLogger("P2P Discovery")
+const Version = 3
+
// Errors
var (
- errPacketTooSmall = errors.New("too small")
- errBadHash = errors.New("bad hash")
- errExpired = errors.New("expired")
- errTimeout = errors.New("RPC timeout")
- errClosed = errors.New("socket closed")
+ errPacketTooSmall = errors.New("too small")
+ errBadHash = errors.New("bad hash")
+ errExpired = errors.New("expired")
+ errBadVersion = errors.New("version mismatch")
+ errUnsolicitedReply = errors.New("unsolicited reply")
+ errUnknownNode = errors.New("unknown node")
+ errTimeout = errors.New("RPC timeout")
+ errClosed = errors.New("socket closed")
)
// Timeouts
@@ -45,6 +50,7 @@ const (
// RPC request structures
type (
ping struct {
+ Version uint // must match Version
IP string // our IP
Port uint16 // our port
Expiration uint64
@@ -76,14 +82,27 @@ type rpcNode struct {
ID NodeID
}
+type packet interface {
+ handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error
+}
+
+type conn interface {
+ ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
+ WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error)
+ Close() error
+ LocalAddr() net.Addr
+}
+
// udp implements the RPC protocol.
type udp struct {
- conn *net.UDPConn
- priv *ecdsa.PrivateKey
+ conn conn
+ priv *ecdsa.PrivateKey
+
addpending chan *pending
- replies chan reply
- closing chan struct{}
- nat nat.Interface
+ gotreply chan reply
+
+ closing chan struct{}
+ nat nat.Interface
*Table
}
@@ -120,6 +139,9 @@ type reply struct {
from NodeID
ptype byte
data interface{}
+ // loop indicates whether there was
+ // a matching request by sending on this channel.
+ matched chan<- bool
}
// ListenUDP returns a new table that listens for UDP packets on laddr.
@@ -132,15 +154,20 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface) (*Table
if err != nil {
return nil, err
}
+ tab, _ := newUDP(priv, conn, natm)
+ log.Infoln("Listening,", tab.self)
+ return tab, nil
+}
+
+func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface) (*Table, *udp) {
udp := &udp{
- conn: conn,
+ conn: c,
priv: priv,
closing: make(chan struct{}),
+ gotreply: make(chan reply),
addpending: make(chan *pending),
- replies: make(chan reply),
}
-
- realaddr := conn.LocalAddr().(*net.UDPAddr)
+ realaddr := c.LocalAddr().(*net.UDPAddr)
if natm != nil {
if !realaddr.IP.IsLoopback() {
go nat.Map(natm, udp.closing, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
@@ -151,11 +178,9 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface) (*Table
}
}
udp.Table = newTable(udp, PubkeyID(&priv.PublicKey), realaddr)
-
go udp.loop()
go udp.readLoop()
- log.Infoln("Listening, ", udp.self)
- return udp.Table, nil
+ return udp.Table, udp
}
func (t *udp) close() {
@@ -165,10 +190,11 @@ func (t *udp) close() {
}
// ping sends a ping message to the given node and waits for a reply.
-func (t *udp) ping(e *Node) error {
+func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error {
// TODO: maybe check for ReplyTo field in callback to measure RTT
- errc := t.pending(e.ID, pongPacket, func(interface{}) bool { return true })
- t.send(e, pingPacket, ping{
+ errc := t.pending(toid, pongPacket, func(interface{}) bool { return true })
+ t.send(toaddr, pingPacket, ping{
+ Version: Version,
IP: t.self.IP.String(),
Port: uint16(t.self.TCPPort),
Expiration: uint64(time.Now().Add(expiration).Unix()),
@@ -176,12 +202,16 @@ func (t *udp) ping(e *Node) error {
return <-errc
}
+func (t *udp) waitping(from NodeID) error {
+ return <-t.pending(from, pingPacket, func(interface{}) bool { return true })
+}
+
// findnode sends a findnode request to the given node and waits until
// the node has sent up to k neighbors.
-func (t *udp) findnode(to *Node, target NodeID) ([]*Node, error) {
+func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
nodes := make([]*Node, 0, bucketSize)
nreceived := 0
- errc := t.pending(to.ID, neighborsPacket, func(r interface{}) bool {
+ errc := t.pending(toid, neighborsPacket, func(r interface{}) bool {
reply := r.(*neighbors)
for _, n := range reply.Nodes {
nreceived++
@@ -191,8 +221,7 @@ func (t *udp) findnode(to *Node, target NodeID) ([]*Node, error) {
}
return nreceived >= bucketSize
})
-
- t.send(to, findnodePacket, findnode{
+ t.send(toaddr, findnodePacket, findnode{
Target: target,
Expiration: uint64(time.Now().Add(expiration).Unix()),
})
@@ -214,6 +243,17 @@ func (t *udp) pending(id NodeID, ptype byte, callback func(interface{}) bool) <-
return ch
}
+func (t *udp) handleReply(from NodeID, ptype byte, req packet) bool {
+ matched := make(chan bool)
+ select {
+ case t.gotreply <- reply{from, ptype, req, matched}:
+ // loop will handle it
+ return <-matched
+ case <-t.closing:
+ return false
+ }
+}
+
// loop runs in its own goroutin. it keeps track of
// the refresh timer and the pending reply queue.
func (t *udp) loop() {
@@ -244,6 +284,7 @@ func (t *udp) loop() {
for _, p := range pending {
p.errc <- errClosed
}
+ pending = nil
return
case p := <-t.addpending:
@@ -251,18 +292,21 @@ func (t *udp) loop() {
pending = append(pending, p)
rearmTimeout()
- case reply := <-t.replies:
- // run matching callbacks, remove if they return false.
+ case r := <-t.gotreply:
+ var matched bool
for i := 0; i < len(pending); i++ {
- p := pending[i]
- if reply.from == p.from && reply.ptype == p.ptype && p.callback(reply.data) {
- p.errc <- nil
- copy(pending[i:], pending[i+1:])
- pending = pending[:len(pending)-1]
- i--
+ if p := pending[i]; p.from == r.from && p.ptype == r.ptype {
+ matched = true
+ if p.callback(r.data) {
+ // callback indicates the request is done, remove it.
+ p.errc <- nil
+ copy(pending[i:], pending[i+1:])
+ pending = pending[:len(pending)-1]
+ i--
+ }
}
}
- rearmTimeout()
+ r.matched <- matched
case now := <-timeout.C:
// notify and remove callbacks whose deadline is in the past.
@@ -287,33 +331,38 @@ const (
var headSpace = make([]byte, headSize)
-func (t *udp) send(to *Node, ptype byte, req interface{}) error {
+func (t *udp) send(toaddr *net.UDPAddr, ptype byte, req interface{}) error {
+ packet, err := encodePacket(t.priv, ptype, req)
+ if err != nil {
+ return err
+ }
+ log.DebugDetailf(">>> %v %T %v\n", toaddr, req, req)
+ if _, err = t.conn.WriteToUDP(packet, toaddr); err != nil {
+ log.DebugDetailln("UDP send failed:", err)
+ }
+ return err
+}
+
+func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte, error) {
b := new(bytes.Buffer)
b.Write(headSpace)
b.WriteByte(ptype)
if err := rlp.Encode(b, req); err != nil {
log.Errorln("error encoding packet:", err)
- return err
+ return nil, err
}
-
packet := b.Bytes()
- sig, err := crypto.Sign(crypto.Sha3(packet[headSize:]), t.priv)
+ sig, err := crypto.Sign(crypto.Sha3(packet[headSize:]), priv)
if err != nil {
log.Errorln("could not sign packet:", err)
- return err
+ return nil, err
}
copy(packet[macSize:], sig)
// add the hash to the front. Note: this doesn't protect the
// packet in any way. Our public key will be part of this hash in
- // the future.
+ // The future.
copy(packet, crypto.Sha3(packet[macSize:]))
-
- toaddr := &net.UDPAddr{IP: to.IP, Port: to.DiscPort}
- log.DebugDetailf(">>> %v %T %v\n", toaddr, req, req)
- if _, err = t.conn.WriteToUDP(packet, toaddr); err != nil {
- log.DebugDetailln("UDP send failed:", err)
- }
- return err
+ return packet, nil
}
// readLoop runs in its own goroutine. it handles incoming UDP packets.
@@ -325,29 +374,34 @@ func (t *udp) readLoop() {
if err != nil {
return
}
- if err := t.packetIn(from, buf[:nbytes]); err != nil {
+ packet, fromID, hash, err := decodePacket(buf[:nbytes])
+ if err != nil {
log.Debugf("Bad packet from %v: %v\n", from, err)
+ continue
}
+ log.DebugDetailf("<<< %v %T %v\n", from, packet, packet)
+ go func() {
+ if err := packet.handle(t, from, fromID, hash); err != nil {
+ log.Debugf("error handling %T from %v: %v", packet, from, err)
+ }
+ }()
}
}
-func (t *udp) packetIn(from *net.UDPAddr, buf []byte) error {
+func decodePacket(buf []byte) (packet, NodeID, []byte, error) {
if len(buf) < headSize+1 {
- return errPacketTooSmall
+ return nil, NodeID{}, nil, errPacketTooSmall
}
hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:]
shouldhash := crypto.Sha3(buf[macSize:])
if !bytes.Equal(hash, shouldhash) {
- return errBadHash
+ return nil, NodeID{}, nil, errBadHash
}
fromID, err := recoverNodeID(crypto.Sha3(buf[headSize:]), sig)
if err != nil {
- return err
- }
-
- var req interface {
- handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error
+ return nil, NodeID{}, hash, err
}
+ var req packet
switch ptype := sigdata[0]; ptype {
case pingPacket:
req = new(ping)
@@ -358,31 +412,27 @@ func (t *udp) packetIn(from *net.UDPAddr, buf []byte) error {
case neighborsPacket:
req = new(neighbors)
default:
- return fmt.Errorf("unknown type: %d", ptype)
+ return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype)
}
- if err := rlp.Decode(bytes.NewReader(sigdata[1:]), req); err != nil {
- return err
- }
- log.DebugDetailf("<<< %v %T %v\n", from, req, req)
- return req.handle(t, from, fromID, hash)
+ err = rlp.Decode(bytes.NewReader(sigdata[1:]), req)
+ return req, fromID, hash, err
}
func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error {
if expired(req.Expiration) {
return errExpired
}
- t.mutex.Lock()
- // Note: we're ignoring the provided IP address right now
- n := t.bumpOrAdd(fromID, from)
- if req.Port != 0 {
- n.TCPPort = int(req.Port)
+ if req.Version != Version {
+ return errBadVersion
}
- t.mutex.Unlock()
-
- t.send(n, pongPacket, pong{
+ t.send(from, pongPacket, pong{
ReplyTok: mac,
Expiration: uint64(time.Now().Add(expiration).Unix()),
})
+ if !t.handleReply(fromID, pingPacket, req) {
+ // Note: we're ignoring the provided IP address right now
+ t.bond(true, fromID, from, req.Port)
+ }
return nil
}
@@ -390,11 +440,9 @@ func (req *pong) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er
if expired(req.Expiration) {
return errExpired
}
- t.mutex.Lock()
- t.bump(fromID)
- t.mutex.Unlock()
-
- t.replies <- reply{fromID, pongPacket, req}
+ if !t.handleReply(fromID, pongPacket, req) {
+ return errUnsolicitedReply
+ }
return nil
}
@@ -402,12 +450,21 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
if expired(req.Expiration) {
return errExpired
}
+ if t.db.get(fromID) == nil {
+ // No bond exists, we don't process the packet. This prevents
+ // an attack vector where the discovery protocol could be used
+ // to amplify traffic in a DDOS attack. A malicious actor
+ // would send a findnode request with the IP address and UDP
+ // port of the target as the source address. The recipient of
+ // the findnode packet would then send a neighbors packet
+ // (which is a much bigger packet than findnode) to the victim.
+ return errUnknownNode
+ }
t.mutex.Lock()
- e := t.bumpOrAdd(fromID, from)
closest := t.closest(req.Target, bucketSize).entries
t.mutex.Unlock()
- t.send(e, neighborsPacket, neighbors{
+ t.send(from, neighborsPacket, neighbors{
Nodes: closest,
Expiration: uint64(time.Now().Add(expiration).Unix()),
})
@@ -418,12 +475,9 @@ func (req *neighbors) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byt
if expired(req.Expiration) {
return errExpired
}
- t.mutex.Lock()
- t.bump(fromID)
- t.add(req.Nodes)
- t.mutex.Unlock()
-
- t.replies <- reply{fromID, neighborsPacket, req}
+ if !t.handleReply(fromID, neighborsPacket, req) {
+ return errUnsolicitedReply
+ }
return nil
}
diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go
index 0a8ff6358..c6c4d78e3 100644
--- a/p2p/discover/udp_test.go
+++ b/p2p/discover/udp_test.go
@@ -1,10 +1,18 @@
package discover
import (
+ "bytes"
+ "crypto/ecdsa"
+ "errors"
"fmt"
+ "io"
logpkg "log"
"net"
"os"
+ "path"
+ "reflect"
+ "runtime"
+ "sync"
"testing"
"time"
@@ -15,197 +23,317 @@ func init() {
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel))
}
-func TestUDP_ping(t *testing.T) {
- t.Parallel()
-
- n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- defer n1.Close()
- defer n2.Close()
+type udpTest struct {
+ t *testing.T
+ pipe *dgramPipe
+ table *Table
+ udp *udp
+ sent [][]byte
+ localkey, remotekey *ecdsa.PrivateKey
+ remoteaddr *net.UDPAddr
+}
- if err := n1.net.ping(n2.self); err != nil {
- t.Fatalf("ping error: %v", err)
+func newUDPTest(t *testing.T) *udpTest {
+ test := &udpTest{
+ t: t,
+ pipe: newpipe(),
+ localkey: newkey(),
+ remotekey: newkey(),
+ remoteaddr: &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 30303},
}
- if find(n2, n1.self.ID) == nil {
- t.Errorf("node 2 does not contain id of node 1")
+ test.table, test.udp = newUDP(test.localkey, test.pipe, nil)
+ return test
+}
+
+// handles a packet as if it had been sent to the transport.
+func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error {
+ enc, err := encodePacket(test.remotekey, ptype, data)
+ if err != nil {
+ return test.errorf("packet (%d) encode error: %v", err)
}
- if e := find(n1, n2.self.ID); e != nil {
- t.Errorf("node 1 does contains id of node 2: %v", e)
+ test.sent = append(test.sent, enc)
+ err = data.handle(test.udp, test.remoteaddr, PubkeyID(&test.remotekey.PublicKey), enc[:macSize])
+ if err != wantError {
+ return test.errorf("error mismatch: got %q, want %q", err, wantError)
}
+ return nil
}
-func find(tab *Table, id NodeID) *Node {
- for _, b := range tab.buckets {
- for _, e := range b.entries {
- if e.ID == id {
- return e
- }
- }
+// waits for a packet to be sent by the transport.
+// validate should have type func(*udpTest, X) error, where X is a packet type.
+func (test *udpTest) waitPacketOut(validate interface{}) error {
+ dgram := test.pipe.waitPacketOut()
+ p, _, _, err := decodePacket(dgram)
+ if err != nil {
+ return test.errorf("sent packet decode error: %v", err)
}
+ fn := reflect.ValueOf(validate)
+ exptype := fn.Type().In(0)
+ if reflect.TypeOf(p) != exptype {
+ return test.errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
+ }
+ fn.Call([]reflect.Value{reflect.ValueOf(p)})
return nil
}
-func TestUDP_findnode(t *testing.T) {
+func (test *udpTest) errorf(format string, args ...interface{}) error {
+ _, file, line, ok := runtime.Caller(2) // errorf + waitPacketOut
+ if ok {
+ file = path.Base(file)
+ } else {
+ file = "???"
+ line = 1
+ }
+ err := fmt.Errorf(format, args...)
+ fmt.Printf("\t%s:%d: %v\n", file, line, err)
+ test.t.Fail()
+ return err
+}
+
+// shared test variables
+var (
+ futureExp = uint64(time.Now().Add(10 * time.Hour).Unix())
+ testTarget = MustHexID("01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101")
+)
+
+func TestUDP_packetErrors(t *testing.T) {
+ test := newUDPTest(t)
+ defer test.table.Close()
+
+ test.packetIn(errExpired, pingPacket, &ping{IP: "foo", Port: 99, Version: Version})
+ test.packetIn(errBadVersion, pingPacket, &ping{IP: "foo", Port: 99, Version: 99, Expiration: futureExp})
+ test.packetIn(errUnsolicitedReply, pongPacket, &pong{ReplyTok: []byte{}, Expiration: futureExp})
+ test.packetIn(errUnknownNode, findnodePacket, &findnode{Expiration: futureExp})
+ test.packetIn(errUnsolicitedReply, neighborsPacket, &neighbors{Expiration: futureExp})
+}
+
+func TestUDP_pingTimeout(t *testing.T) {
+ t.Parallel()
+ test := newUDPTest(t)
+ defer test.table.Close()
+
+ toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222}
+ toid := NodeID{1, 2, 3, 4}
+ if err := test.udp.ping(toid, toaddr); err != errTimeout {
+ t.Error("expected timeout error, got", err)
+ }
+}
+
+func TestUDP_findnodeTimeout(t *testing.T) {
t.Parallel()
+ test := newUDPTest(t)
+ defer test.table.Close()
- n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- defer n1.Close()
- defer n2.Close()
+ toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222}
+ toid := NodeID{1, 2, 3, 4}
+ target := NodeID{4, 5, 6, 7}
+ result, err := test.udp.findnode(toid, toaddr, target)
+ if err != errTimeout {
+ t.Error("expected timeout error, got", err)
+ }
+ if len(result) > 0 {
+ t.Error("expected empty result, got", result)
+ }
+}
- // put a few nodes into n2. the exact distribution shouldn't
- // matter much, altough we need to take care not to overflow
- // any bucket.
- target := randomID(n1.self.ID, 100)
+func TestUDP_findnode(t *testing.T) {
+ test := newUDPTest(t)
+ defer test.table.Close()
+
+ // put a few nodes into the table. their exact
+ // distribution shouldn't matter much, altough we need to
+ // take care not to overflow any bucket.
+ target := testTarget
nodes := &nodesByDistance{target: target}
for i := 0; i < bucketSize; i++ {
- n2.add([]*Node{&Node{
+ nodes.push(&Node{
IP: net.IP{1, 2, 3, byte(i)},
DiscPort: i + 2,
TCPPort: i + 2,
- ID: randomID(n2.self.ID, i+2),
- }})
+ ID: randomID(test.table.self.ID, i+2),
+ }, bucketSize)
}
- n2.add(nodes.entries)
- n2.bumpOrAdd(n1.self.ID, &net.UDPAddr{IP: n1.self.IP, Port: n1.self.DiscPort})
- expected := n2.closest(target, bucketSize)
+ test.table.add(nodes.entries)
+
+ // ensure there's a bond with the test node,
+ // findnode won't be accepted otherwise.
+ test.table.db.add(PubkeyID(&test.remotekey.PublicKey), test.remoteaddr, 99)
- err := runUDP(10, func() error {
- result, _ := n1.net.findnode(n2.self, target)
- if len(result) != bucketSize {
- return fmt.Errorf("wrong number of results: got %d, want %d", len(result), bucketSize)
+ // check that closest neighbors are returned.
+ test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp})
+ test.waitPacketOut(func(p *neighbors) {
+ expected := test.table.closest(testTarget, bucketSize)
+ if len(p.Nodes) != bucketSize {
+ t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize)
}
- for i := range result {
- if result[i].ID != expected.entries[i].ID {
- return fmt.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, result[i], expected.entries[i])
+ for i := range p.Nodes {
+ if p.Nodes[i].ID != expected.entries[i].ID {
+ t.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, p.Nodes[i], expected.entries[i])
}
}
- return nil
})
- if err != nil {
- t.Error(err)
- }
}
-func TestUDP_replytimeout(t *testing.T) {
- t.Parallel()
+func TestUDP_findnodeMultiReply(t *testing.T) {
+ test := newUDPTest(t)
+ defer test.table.Close()
- // reserve a port so we don't talk to an existing service by accident
- addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:0")
- fd, err := net.ListenUDP("udp", addr)
- if err != nil {
- t.Fatal(err)
- }
- defer fd.Close()
+ // queue a pending findnode request
+ resultc, errc := make(chan []*Node), make(chan error)
+ go func() {
+ rid := PubkeyID(&test.remotekey.PublicKey)
+ ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget)
+ if err != nil && len(ns) == 0 {
+ errc <- err
+ } else {
+ resultc <- ns
+ }
+ }()
- n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- defer n1.Close()
- n2 := n1.bumpOrAdd(randomID(n1.self.ID, 10), fd.LocalAddr().(*net.UDPAddr))
+ // wait for the findnode to be sent.
+ // after it is sent, the transport is waiting for a reply
+ test.waitPacketOut(func(p *findnode) {
+ if p.Target != testTarget {
+ t.Errorf("wrong target: got %v, want %v", p.Target, testTarget)
+ }
+ })
- if err := n1.net.ping(n2); err != errTimeout {
- t.Error("expected timeout error, got", err)
+ // send the reply as two packets.
+ list := []*Node{
+ MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303"),
+ MustParseNode("enode://81fa361d25f157cd421c60dcc28d8dac5ef6a89476633339c5df30287474520caca09627da18543d9079b5b288698b542d56167aa5c09111e55acdbbdf2ef799@10.0.1.16:30303"),
+ MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301"),
+ MustParseNode("enode://1b5b4aa662d7cb44a7221bfba67302590b643028197a7d5214790f3bac7aaa4a3241be9e83c09cf1f6c69d007c634faae3dc1b1221793e8446c0b3a09de65960@10.0.1.16:30303"),
}
+ test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[:2]})
+ test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[2:]})
- if result, err := n1.net.findnode(n2, n1.self.ID); err != errTimeout {
- t.Error("expected timeout error, got", err)
- } else if len(result) > 0 {
- t.Error("expected empty result, got", result)
+ // check that the sent neighbors are all returned by findnode
+ select {
+ case result := <-resultc:
+ if !reflect.DeepEqual(result, list) {
+ t.Errorf("neighbors mismatch:\n got: %v\n want: %v", result, list)
+ }
+ case err := <-errc:
+ t.Errorf("findnode error: %v", err)
+ case <-time.After(5 * time.Second):
+ t.Error("findnode did not return within 5 seconds")
}
}
-func TestUDP_findnodeMultiReply(t *testing.T) {
- t.Parallel()
+func TestUDP_successfulPing(t *testing.T) {
+ test := newUDPTest(t)
+ defer test.table.Close()
- n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
- udp2 := n2.net.(*udp)
- defer n1.Close()
- defer n2.Close()
-
- err := runUDP(10, func() error {
- nodes := make([]*Node, bucketSize)
- for i := range nodes {
- nodes[i] = &Node{
- IP: net.IP{1, 2, 3, 4},
- DiscPort: i + 1,
- TCPPort: i + 1,
- ID: randomID(n2.self.ID, i+1),
- }
- }
+ done := make(chan struct{})
+ go func() {
+ test.packetIn(nil, pingPacket, &ping{IP: "foo", Port: 99, Version: Version, Expiration: futureExp})
+ close(done)
+ }()
- // ask N2 for neighbors. it will send an empty reply back.
- // the request will wait for up to bucketSize replies.
- resultc := make(chan []*Node)
- errc := make(chan error)
- go func() {
- ns, err := n1.net.findnode(n2.self, n1.self.ID)
- if err != nil {
- errc <- err
- } else {
- resultc <- ns
- }
- }()
-
- // send a few more neighbors packets to N1.
- // it should collect those.
- for end := 0; end < len(nodes); {
- off := end
- if end = end + 5; end > len(nodes) {
- end = len(nodes)
- }
- udp2.send(n1.self, neighborsPacket, neighbors{
- Nodes: nodes[off:end],
- Expiration: uint64(time.Now().Add(10 * time.Second).Unix()),
- })
+ // the ping is replied to.
+ test.waitPacketOut(func(p *pong) {
+ pinghash := test.sent[0][:macSize]
+ if !bytes.Equal(p.ReplyTok, pinghash) {
+ t.Errorf("got ReplyTok %x, want %x", p.ReplyTok, pinghash)
}
+ })
- // check that they are all returned. we cannot just check for
- // equality because they might not be returned in the order they
- // were sent.
- var result []*Node
- select {
- case result = <-resultc:
- case err := <-errc:
- return err
- }
- if hasDuplicates(result) {
- return fmt.Errorf("result slice contains duplicates")
- }
- if len(result) != len(nodes) {
- return fmt.Errorf("wrong number of nodes returned: got %d, want %d", len(result), len(nodes))
- }
- matched := make(map[NodeID]bool)
- for _, n := range result {
- for _, expn := range nodes {
- if n.ID == expn.ID { // && bytes.Equal(n.Addr.IP, expn.Addr.IP) && n.Addr.Port == expn.Addr.Port {
- matched[n.ID] = true
- }
+ // remote is unknown, the table pings back.
+ test.waitPacketOut(func(p *ping) error { return nil })
+ test.packetIn(nil, pongPacket, &pong{Expiration: futureExp})
+
+ // ping should return shortly after getting the pong packet.
+ <-done
+
+ // check that the node was added.
+ rid := PubkeyID(&test.remotekey.PublicKey)
+ rnode := find(test.table, rid)
+ if rnode == nil {
+ t.Fatalf("node %v not found in table", rid)
+ }
+ if !bytes.Equal(rnode.IP, test.remoteaddr.IP) {
+ t.Errorf("node has wrong IP: got %v, want: %v", rnode.IP, test.remoteaddr.IP)
+ }
+ if rnode.DiscPort != test.remoteaddr.Port {
+ t.Errorf("node has wrong Port: got %v, want: %v", rnode.DiscPort, test.remoteaddr.Port)
+ }
+ if rnode.TCPPort != 99 {
+ t.Errorf("node has wrong Port: got %v, want: %v", rnode.TCPPort, 99)
+ }
+}
+
+func find(tab *Table, id NodeID) *Node {
+ for _, b := range tab.buckets {
+ for _, e := range b.entries {
+ if e.ID == id {
+ return e
}
}
- if len(matched) != len(nodes) {
- return fmt.Errorf("wrong number of matching nodes: got %d, want %d", len(matched), len(nodes))
- }
- return nil
- })
- if err != nil {
- t.Error(err)
}
+ return nil
}
-// runUDP runs a test n times and returns an error if the test failed
-// in all n runs. This is necessary because UDP is unreliable even for
-// connections on the local machine, causing test failures.
-func runUDP(n int, test func() error) error {
- errcount := 0
- errors := ""
- for i := 0; i < n; i++ {
- if err := test(); err != nil {
- errors += fmt.Sprintf("\n#%d: %v", i, err)
- errcount++
- }
+// dgramPipe is a fake UDP socket. It queues all sent datagrams.
+type dgramPipe struct {
+ mu *sync.Mutex
+ cond *sync.Cond
+ closing chan struct{}
+ closed bool
+ queue [][]byte
+}
+
+func newpipe() *dgramPipe {
+ mu := new(sync.Mutex)
+ return &dgramPipe{
+ closing: make(chan struct{}),
+ cond: &sync.Cond{L: mu},
+ mu: mu,
}
- if errcount == n {
- return fmt.Errorf("failed on all %d iterations:%s", n, errors)
+}
+
+// WriteToUDP queues a datagram.
+func (c *dgramPipe) WriteToUDP(b []byte, to *net.UDPAddr) (n int, err error) {
+ msg := make([]byte, len(b))
+ copy(msg, b)
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.closed {
+ return 0, errors.New("closed")
+ }
+ c.queue = append(c.queue, msg)
+ c.cond.Signal()
+ return len(b), nil
+}
+
+// ReadFromUDP just hangs until the pipe is closed.
+func (c *dgramPipe) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
+ <-c.closing
+ return 0, nil, io.EOF
+}
+
+func (c *dgramPipe) Close() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if !c.closed {
+ close(c.closing)
+ c.closed = true
}
return nil
}
+
+func (c *dgramPipe) LocalAddr() net.Addr {
+ return &net.UDPAddr{}
+}
+
+func (c *dgramPipe) waitPacketOut() []byte {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ for len(c.queue) == 0 {
+ c.cond.Wait()
+ }
+ p := c.queue[0]
+ copy(c.queue, c.queue[1:])
+ c.queue = c.queue[:len(c.queue)-1]
+ return p
+}
diff --git a/params/protocol_params.go b/params/protocol_params.go
new file mode 100755
index 000000000..d0bc2f4ad
--- /dev/null
+++ b/params/protocol_params.go
@@ -0,0 +1,54 @@
+// 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.
+)
diff --git a/rpc/api.go b/rpc/api.go
index b554dc16b..5e27890ce 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -80,8 +80,9 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
- v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
- *reply = common.ToHex(v.Bytes())
+ *reply = api.xethAtStateNum(args.BlockNumber).BalanceAt(args.Address)
+ //v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
+ //*reply = common.ToHex(v.Bytes())
case "eth_getStorage", "eth_storageAt":
args := new(GetStorageArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
@@ -95,10 +96,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
- state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address)
- value := state.StorageString(args.Key)
-
- *reply = common.ToHex(value.Bytes())
+ *reply = api.xethAtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key)
case "eth_getTransactionCount":
args := new(GetTxCountArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
diff --git a/tests/blocktest.go b/tests/blocktest.go
index fc62eda58..1c4f1c2f2 100644
--- a/tests/blocktest.go
+++ b/tests/blocktest.go
@@ -114,7 +114,7 @@ func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
}
}
// sync objects to trie
- statedb.Update(nil)
+ statedb.Update()
// sync trie to disk
statedb.Sync()
diff --git a/tests/files/BasicTests/genesishashestest.json b/tests/files/BasicTests/genesishashestest.json
index cff9691a1..4687cab9b 100644
--- a/tests/files/BasicTests/genesishashestest.json
+++ b/tests/files/BasicTests/genesishashestest.json
@@ -1,5 +1,5 @@
{
- "genesis_rlp_hex": "f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
+ "genesis_rlp_hex": "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0",
"genesis_state_root": "9178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4e",
- "genesis_hash": "b5d6d8402156c5c1dfadaa4b87c676b5bcadb17ef9bc8e939606daaa0d35f55d"
+ "genesis_hash": "fd4af92a79c7fc2fd8bf0d342f2e832e1d4f485c85b9152d2039e03bc604fdca"
}
diff --git a/tests/files/StateTests/RandomTests/st201503261401CPPJIT.json b/tests/files/StateTests/RandomTests/st201503261401CPPJIT.json
new file mode 100644
index 000000000..074fd18d2
--- /dev/null
+++ b/tests/files/StateTests/RandomTests/st201503261401CPPJIT.json
@@ -0,0 +1,71 @@
+{
+ "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"
+ }
+ }
+}
diff --git a/tests/files/StateTests/RandomTests/st201504011535GO.json b/tests/files/StateTests/RandomTests/st201504011535GO.json
new file mode 100644
index 000000000..449ca0407
--- /dev/null
+++ b/tests/files/StateTests/RandomTests/st201504011535GO.json
@@ -0,0 +1,71 @@
+{
+ "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"
+ }
+ }
+}
diff --git a/tests/files/StateTests/RandomTests/st201504011536GO.json b/tests/files/StateTests/RandomTests/st201504011536GO.json
new file mode 100644
index 000000000..53b487063
--- /dev/null
+++ b/tests/files/StateTests/RandomTests/st201504011536GO.json
@@ -0,0 +1,71 @@
+{
+ "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"
+ }
+ }
+}
diff --git a/tests/files/StateTests/RandomTests/st201504011547GO.json b/tests/files/StateTests/RandomTests/st201504011547GO.json
new file mode 100644
index 000000000..9e94ee717
--- /dev/null
+++ b/tests/files/StateTests/RandomTests/st201504011547GO.json
@@ -0,0 +1,71 @@
+{
+ "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"
+ }
+ }
+}
diff --git a/tests/files/StateTests/stCallCreateCallCodeTest.json b/tests/files/StateTests/stCallCreateCallCodeTest.json
index abed20ae0..04f9cc434 100644
--- a/tests/files/StateTests/stCallCreateCallCodeTest.json
+++ b/tests/files/StateTests/stCallCreateCallCodeTest.json
@@ -868,7 +868,7 @@
}
},
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
- "balance" : "100000",
+ "balance" : "200000",
"code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
"nonce" : "0",
"storage" : {
@@ -880,17 +880,29 @@
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "999999999999533644",
+ "balance" : "9999999533644",
"code" : "0x",
"nonce" : "1",
"storage" : {
}
}
},
- "postStateRoot" : "239c509594811741c8f3ed0a2d89abb00c0398098c80f88a82cebc153dec5c4b",
+ "postStateRoot" : "5500215cdbf8165ca47720ad088ae49c2441560cdf267f1c946ae7b9807cb1d4",
"pre" : {
+ "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
+ "balance" : "100000",
+ "code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
+ "nonce" : "0",
+ "storage" : {
+ "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "0x01" : "0x42",
+ "0x02" : "0x23",
+ "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "0x05" : "0x54c98c81"
+ }
+ },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "1000000000000000000",
+ "balance" : "10000000000000",
"code" : "0x",
"nonce" : "0",
"storage" : {
diff --git a/tests/helper/vm.go b/tests/helper/vm.go
index 052ad6a6e..9f62ada95 100644
--- a/tests/helper/vm.go
+++ b/tests/helper/vm.go
@@ -185,7 +185,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) {
statedb.Set(snapshot)
}
- statedb.Update(vmenv.Gas)
+ statedb.Update()
return ret, vmenv.logs, vmenv.Gas, err
}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 1b6b1ccd0..6c9db16c2 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -308,21 +308,19 @@ func (self *XEth) NumberToHuman(balance string) string {
}
func (self *XEth) StorageAt(addr, storageAddr string) string {
- storage := self.State().SafeGet(addr).StorageString(storageAddr)
-
- return common.ToHex(storage.Bytes())
+ return common.ToHex(self.State().state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)))
}
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 {
- return int(self.State().SafeGet(address).Nonce())
+ return int(self.State().state.GetNonce(common.HexToAddress(address)))
}
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 {