Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
bf324bd24b | |||
a2e1e5c6a0 | |||
506c927791 | |||
c0673eefb1 | |||
34b622a248 | |||
cab802b40f | |||
869d9792b3 | |||
d3f8b763bf | |||
4044a8cea4 | |||
61be63bb9b | |||
5f7e74d5c8 | |||
2be2842758 | |||
c2df9d356a | |||
a4f4846fff | |||
7f83e68b13 | |||
5570b11398 | |||
e7fb300053 | |||
4e0fe48e20 | |||
bcf565730b | |||
587bafaa9f | |||
7bb496f737 | |||
61404979ed | |||
300f1e2abf | |||
4ce7970340 | |||
0c17be92fb | |||
b5a0cf488c | |||
b25da7c3f4 | |||
93077941d3 | |||
8cb69b9e9b | |||
c541b38fb3 | |||
336a4d7b8d | |||
8938768f75 | |||
5490437942 | |||
e5532154a5 | |||
f75becc264 | |||
9666db2a44 |
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#### System information
|
||||
|
||||
Geth version: `geth version`
|
||||
OS & Version: Windows/Linux/OSX
|
||||
Commit hash : (if `develop`)
|
||||
|
||||
#### Expected behaviour
|
||||
|
||||
|
||||
#### Actual behaviour
|
||||
|
||||
|
||||
#### Steps to reproduce the behaviour
|
||||
|
||||
|
||||
#### Backtrace
|
||||
|
||||
````
|
||||
[backtrace]
|
||||
````
|
@ -20,10 +20,6 @@ env:
|
||||
global:
|
||||
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libgmp3-dev
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
|
68
Makefile
68
Makefile
@ -10,7 +10,7 @@
|
||||
|
||||
GOBIN = build/bin
|
||||
|
||||
CROSSDEPS = https://gmplib.org/download/gmp/gmp-6.0.0a.tar.bz2
|
||||
MODE ?= default
|
||||
GO ?= latest
|
||||
|
||||
geth:
|
||||
@ -26,32 +26,51 @@ geth-linux: xgo geth-linux-arm geth-linux-386 geth-linux-amd64
|
||||
@echo "Linux cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-*
|
||||
|
||||
geth-linux-arm: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/arm -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux ARM cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep arm
|
||||
|
||||
geth-linux-386: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/386 -v $(shell build/flags.sh) ./cmd/geth
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/386 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux 386 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep 386
|
||||
|
||||
geth-linux-amd64: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/amd64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/amd64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux amd64 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep amd64
|
||||
|
||||
geth-darwin: xgo geth-darwin-386 geth-darwin-amd64
|
||||
geth-linux-arm: geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
|
||||
@echo "Linux ARM cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep arm
|
||||
|
||||
geth-linux-arm-5: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm-5 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux ARMv5 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep arm-5
|
||||
|
||||
geth-linux-arm-6: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm-6 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux ARMv6 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep arm-6
|
||||
|
||||
geth-linux-arm-7: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm-7 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux ARMv7 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep arm-7
|
||||
|
||||
geth-linux-arm64: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Linux ARM64 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-linux-* | grep arm64
|
||||
|
||||
geth-darwin: geth-darwin-386 geth-darwin-amd64
|
||||
@echo "Darwin cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-darwin-*
|
||||
|
||||
geth-darwin-386: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=darwin/386 -v $(shell build/flags.sh) ./cmd/geth
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=darwin/386 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Darwin 386 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-darwin-* | grep 386
|
||||
|
||||
geth-darwin-amd64: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=darwin/amd64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=darwin/amd64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Darwin amd64 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-darwin-* | grep amd64
|
||||
|
||||
@ -60,28 +79,33 @@ geth-windows: xgo geth-windows-386 geth-windows-amd64
|
||||
@ls -l $(GOBIN)/geth-windows-*
|
||||
|
||||
geth-windows-386: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=windows/386 -v $(shell build/flags.sh) ./cmd/geth
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=windows/386 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Windows 386 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-windows-* | grep 386
|
||||
|
||||
geth-windows-amd64: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=windows/amd64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=windows/amd64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Windows amd64 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-windows-* | grep amd64
|
||||
|
||||
geth-android: xgo geth-android-16 geth-android-21
|
||||
geth-android: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=android/* -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Android cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-android-*
|
||||
|
||||
geth-android-16: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android-16/* -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Android 16 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-android-16-*
|
||||
geth-ios: geth-ios-arm-7 geth-ios-arm64
|
||||
@echo "iOS cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-ios-*
|
||||
|
||||
geth-android-21: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android-21/* -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "Android 21 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-android-21-*
|
||||
geth-ios-arm-7: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=ios/arm-7 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "iOS ARMv7 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-ios-* | grep arm-7
|
||||
|
||||
geth-ios-arm64: xgo
|
||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=ios-7.0/arm64 -v $(shell build/flags.sh) ./cmd/geth
|
||||
@echo "iOS ARM64 cross compilation done:"
|
||||
@ls -l $(GOBIN)/geth-ios-* | grep arm64
|
||||
|
||||
evm:
|
||||
build/env.sh $(GOROOT)/bin/go install -v $(shell build/flags.sh) ./cmd/evm
|
||||
|
@ -30,7 +30,7 @@ For prerequisites and detailed build instructions please read the
|
||||
[Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum)
|
||||
on the wiki.
|
||||
|
||||
Building geth requires two external dependencies, Go and GMP.
|
||||
Building geth requires both a Go and a C compiler.
|
||||
You can install them using your favourite package manager.
|
||||
Once the dependencies are installed, run
|
||||
|
||||
|
@ -225,10 +225,15 @@ func (self *VMEnv) Call(caller vm.ContractRef, addr common.Address, data []byte,
|
||||
self.Gas = gas
|
||||
return core.Call(self, caller, addr, data, gas, price, value)
|
||||
}
|
||||
|
||||
func (self *VMEnv) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
|
||||
return core.CallCode(self, caller, addr, data, gas, price, value)
|
||||
}
|
||||
|
||||
func (self *VMEnv) DelegateCall(caller vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
|
||||
return core.DelegateCall(self, caller, addr, data, gas, price)
|
||||
}
|
||||
|
||||
func (self *VMEnv) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
|
||||
return core.Create(self, caller, data, gas, price, value)
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ import (
|
||||
|
||||
const (
|
||||
ClientIdentifier = "Geth"
|
||||
Version = "1.4.0-unstable"
|
||||
Version = "1.3.6"
|
||||
VersionMajor = 1
|
||||
VersionMinor = 4
|
||||
VersionPatch = 0
|
||||
VersionMinor = 3
|
||||
VersionPatch = 6
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -91,6 +91,7 @@ func PromptPassword(prompt string, warnTerm bool) (string, error) {
|
||||
}
|
||||
fmt.Print(prompt)
|
||||
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
input = strings.TrimRight(input, "\r\n")
|
||||
fmt.Println()
|
||||
return input, err
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ var (
|
||||
GasPriceFlag = cli.StringFlag{
|
||||
Name: "gasprice",
|
||||
Usage: "Minimal gas price to accept for mining a transactions",
|
||||
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
|
||||
Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(),
|
||||
}
|
||||
ExtraDataFlag = cli.StringFlag{
|
||||
Name: "extradata",
|
||||
@ -356,7 +356,7 @@ var (
|
||||
GpoMinGasPriceFlag = cli.StringFlag{
|
||||
Name: "gpomin",
|
||||
Usage: "Minimum suggested gas price",
|
||||
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
|
||||
Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(),
|
||||
}
|
||||
GpoMaxGasPriceFlag = cli.StringFlag{
|
||||
Name: "gpomax",
|
||||
@ -472,6 +472,8 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
||||
cfg.DataDir += "/testnet"
|
||||
cfg.NetworkId = 2
|
||||
cfg.TestNet = true
|
||||
// overwrite homestead block
|
||||
params.HomesteadBlock = params.TestNetHomesteadBlock
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(VMEnableJitFlag.Name) {
|
||||
|
@ -82,7 +82,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
||||
return func(i int, gen *BlockGen) {
|
||||
toaddr := common.Address{}
|
||||
data := make([]byte, nbytes)
|
||||
gas := IntrinsicGas(data)
|
||||
gas := IntrinsicGas(data, false, false)
|
||||
tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(benchRootKey)
|
||||
gen.AddTx(tx)
|
||||
}
|
||||
|
@ -30,6 +30,12 @@ import (
|
||||
"gopkg.in/fatih/set.v0"
|
||||
)
|
||||
|
||||
var (
|
||||
ExpDiffPeriod = big.NewInt(100000)
|
||||
big10 = big.NewInt(10)
|
||||
bigMinus99 = big.NewInt(-99)
|
||||
)
|
||||
|
||||
// BlockValidator is responsible for validating block headers, uncles and
|
||||
// processed state.
|
||||
//
|
||||
@ -111,7 +117,7 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
|
||||
// For valid blocks this should always validate to true.
|
||||
rbloom := types.CreateBloom(receipts)
|
||||
if rbloom != header.Bloom {
|
||||
return fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
|
||||
return fmt.Errorf("unable to replicate block's bloom=%x vs calculated bloom=%x", header.Bloom, rbloom)
|
||||
}
|
||||
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
|
||||
receiptSha := types.DeriveSha(receipts)
|
||||
@ -241,3 +247,127 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
||||
// the difficulty that a new block should have when created at time
|
||||
// given the parent block's time and difficulty.
|
||||
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
if params.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
|
||||
return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
|
||||
} else {
|
||||
return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
|
||||
}
|
||||
}
|
||||
|
||||
func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
|
||||
// algorithm:
|
||||
// diff = (parent_diff +
|
||||
// (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
|
||||
// ) + 2^(periodCount - 2)
|
||||
|
||||
bigTime := new(big.Int).SetUint64(time)
|
||||
bigParentTime := new(big.Int).SetUint64(parentTime)
|
||||
|
||||
// holds intermediate values to make the algo easier to read & audit
|
||||
x := new(big.Int)
|
||||
y := new(big.Int)
|
||||
|
||||
// 1 - (block_timestamp -parent_timestamp) // 10
|
||||
x.Sub(bigTime, bigParentTime)
|
||||
x.Div(x, big10)
|
||||
x.Sub(common.Big1, x)
|
||||
|
||||
// max(1 - (block_timestamp - parent_timestamp) // 10, -99)))
|
||||
if x.Cmp(bigMinus99) < 0 {
|
||||
x.Set(bigMinus99)
|
||||
}
|
||||
|
||||
// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
|
||||
y.Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
x.Mul(y, x)
|
||||
x.Add(parentDiff, x)
|
||||
|
||||
// minimum difficulty can ever be (before exponential factor)
|
||||
if x.Cmp(params.MinimumDifficulty) < 0 {
|
||||
x = params.MinimumDifficulty
|
||||
}
|
||||
|
||||
// for the exponential factor
|
||||
periodCount := new(big.Int).Add(parentNumber, common.Big1)
|
||||
periodCount.Div(periodCount, ExpDiffPeriod)
|
||||
|
||||
// the exponential factor, commonly refered to as "the bomb"
|
||||
// diff = diff + 2^(periodCount - 2)
|
||||
if periodCount.Cmp(common.Big1) > 0 {
|
||||
y.Sub(periodCount, common.Big2)
|
||||
y.Exp(common.Big2, y, nil)
|
||||
x.Add(x, y)
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
diff := new(big.Int)
|
||||
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
bigTime := new(big.Int)
|
||||
bigParentTime := new(big.Int)
|
||||
|
||||
bigTime.SetUint64(time)
|
||||
bigParentTime.SetUint64(parentTime)
|
||||
|
||||
if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
|
||||
diff.Add(parentDiff, adjust)
|
||||
} else {
|
||||
diff.Sub(parentDiff, adjust)
|
||||
}
|
||||
if diff.Cmp(params.MinimumDifficulty) < 0 {
|
||||
diff = params.MinimumDifficulty
|
||||
}
|
||||
|
||||
periodCount := new(big.Int).Add(parentNumber, common.Big1)
|
||||
periodCount.Div(periodCount, ExpDiffPeriod)
|
||||
if periodCount.Cmp(common.Big1) > 0 {
|
||||
// diff = diff + 2^(periodCount - 2)
|
||||
expDiff := periodCount.Sub(periodCount, common.Big2)
|
||||
expDiff.Exp(common.Big2, expDiff, nil)
|
||||
diff.Add(diff, expDiff)
|
||||
diff = common.BigMax(diff, params.MinimumDifficulty)
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
||||
|
||||
// CalcGasLimit computes the gas limit of the next block after parent.
|
||||
// The result may be modified by the caller.
|
||||
// This is miner strategy, not consensus protocol.
|
||||
func CalcGasLimit(parent *types.Block) *big.Int {
|
||||
// contrib = (parentGasUsed * 3 / 2) / 1024
|
||||
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
|
||||
contrib = contrib.Div(contrib, big.NewInt(2))
|
||||
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
|
||||
|
||||
// decay = parentGasLimit / 1024 -1
|
||||
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
|
||||
decay.Sub(decay, big.NewInt(1))
|
||||
|
||||
/*
|
||||
strategy: gasLimit of block-to-mine is set based on parent's
|
||||
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
|
||||
increase it, otherwise lower it (or leave it unchanged if it's right
|
||||
at that usage) the amount increased/decreased depends on how far away
|
||||
from parentGasLimit * (2/3) parentGasUsed is.
|
||||
*/
|
||||
gl := new(big.Int).Sub(parent.GasLimit(), decay)
|
||||
gl = gl.Add(gl, contrib)
|
||||
gl.Set(common.BigMax(gl, params.MinGasLimit))
|
||||
|
||||
// however, if we're now below the target (GenesisGasLimit) we increase the
|
||||
// limit as much as we can (parentGasLimit / 1024 -1)
|
||||
if gl.Cmp(params.GenesisGasLimit) < 0 {
|
||||
gl.Add(parent.GasLimit(), decay)
|
||||
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
|
||||
}
|
||||
return gl
|
||||
}
|
||||
|
@ -591,6 +591,19 @@ func (bc *BlockChain) HasBlock(hash common.Hash) bool {
|
||||
return bc.GetBlock(hash) != nil
|
||||
}
|
||||
|
||||
// HasBlockAndState checks if a block and associated state trie is fully present
|
||||
// in the database or not, caching it if present.
|
||||
func (bc *BlockChain) HasBlockAndState(hash common.Hash) bool {
|
||||
// Check first that the block itself is known
|
||||
block := bc.GetBlock(hash)
|
||||
if block == nil {
|
||||
return false
|
||||
}
|
||||
// Ensure the associated state is also present
|
||||
_, err := state.New(block.Root(), bc.chainDb)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// GetBlock retrieves a block from the database by hash, caching it if found.
|
||||
func (self *BlockChain) GetBlock(hash common.Hash) *types.Block {
|
||||
// Short circuit if the block's already in the cache, retrieve otherwise
|
||||
@ -716,14 +729,18 @@ func (self *BlockChain) writeHeader(header *types.Header) error {
|
||||
if ptd == nil {
|
||||
return ParentError(header.ParentHash)
|
||||
}
|
||||
td := new(big.Int).Add(header.Difficulty, ptd)
|
||||
|
||||
localTd := self.GetTd(self.currentHeader.Hash())
|
||||
externTd := new(big.Int).Add(header.Difficulty, ptd)
|
||||
|
||||
// Make sure no inconsistent state is leaked during insertion
|
||||
self.mu.Lock()
|
||||
defer self.mu.Unlock()
|
||||
|
||||
// If the total difficulty is higher than our known, add it to the canonical chain
|
||||
if td.Cmp(self.GetTd(self.currentHeader.Hash())) > 0 {
|
||||
// Second clause in the if statement reduces the vulnerability to selfish mining.
|
||||
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
|
||||
if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) {
|
||||
// Delete any canonical number assignments above the new head
|
||||
for i := header.Number.Uint64() + 1; GetCanonicalHash(self.chainDb, i) != (common.Hash{}); i++ {
|
||||
DeleteCanonicalHash(self.chainDb, i)
|
||||
@ -744,7 +761,7 @@ func (self *BlockChain) writeHeader(header *types.Header) error {
|
||||
self.currentHeader = types.CopyHeader(header)
|
||||
}
|
||||
// Irrelevant of the canonical status, write the header itself to the database
|
||||
if err := WriteTd(self.chainDb, header.Hash(), td); err != nil {
|
||||
if err := WriteTd(self.chainDb, header.Hash(), externTd); err != nil {
|
||||
glog.Fatalf("failed to write header total difficulty: %v", err)
|
||||
}
|
||||
if err := WriteHeader(self.chainDb, header); err != nil {
|
||||
@ -1039,14 +1056,18 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status writeStatus, err
|
||||
if ptd == nil {
|
||||
return NonStatTy, ParentError(block.ParentHash())
|
||||
}
|
||||
td := new(big.Int).Add(block.Difficulty(), ptd)
|
||||
|
||||
localTd := self.GetTd(self.currentBlock.Hash())
|
||||
externTd := new(big.Int).Add(block.Difficulty(), ptd)
|
||||
|
||||
// Make sure no inconsistent state is leaked during insertion
|
||||
self.mu.Lock()
|
||||
defer self.mu.Unlock()
|
||||
|
||||
// If the total difficulty is higher than our known, add it to the canonical chain
|
||||
if td.Cmp(self.GetTd(self.currentBlock.Hash())) > 0 {
|
||||
// Second clause in the if statement reduces the vulnerability to selfish mining.
|
||||
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
|
||||
if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) {
|
||||
// Reorganize the chain if the parent is not the head block
|
||||
if block.ParentHash() != self.currentBlock.Hash() {
|
||||
if err := self.reorg(self.currentBlock, block); err != nil {
|
||||
@ -1060,7 +1081,7 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status writeStatus, err
|
||||
status = SideStatTy
|
||||
}
|
||||
// Irrelevant of the canonical status, write the block itself to the database
|
||||
if err := WriteTd(self.chainDb, block.Hash(), td); err != nil {
|
||||
if err := WriteTd(self.chainDb, block.Hash(), externTd); err != nil {
|
||||
glog.Fatalf("failed to write block total difficulty: %v", err)
|
||||
}
|
||||
if err := WriteBlock(self.chainDb, block); err != nil {
|
||||
|
@ -27,7 +27,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
@ -50,77 +49,9 @@ var (
|
||||
mipmapPre = []byte("mipmap-log-bloom-")
|
||||
MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
|
||||
|
||||
ExpDiffPeriod = big.NewInt(100000)
|
||||
blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
|
||||
)
|
||||
|
||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
||||
// the difficulty that a new block b should have when created at time
|
||||
// given the parent block's time and difficulty.
|
||||
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
diff := new(big.Int)
|
||||
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
bigTime := new(big.Int)
|
||||
bigParentTime := new(big.Int)
|
||||
|
||||
bigTime.SetUint64(time)
|
||||
bigParentTime.SetUint64(parentTime)
|
||||
|
||||
if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
|
||||
diff.Add(parentDiff, adjust)
|
||||
} else {
|
||||
diff.Sub(parentDiff, adjust)
|
||||
}
|
||||
if diff.Cmp(params.MinimumDifficulty) < 0 {
|
||||
diff = params.MinimumDifficulty
|
||||
}
|
||||
|
||||
periodCount := new(big.Int).Add(parentNumber, common.Big1)
|
||||
periodCount.Div(periodCount, ExpDiffPeriod)
|
||||
if periodCount.Cmp(common.Big1) > 0 {
|
||||
// diff = diff + 2^(periodCount - 2)
|
||||
expDiff := periodCount.Sub(periodCount, common.Big2)
|
||||
expDiff.Exp(common.Big2, expDiff, nil)
|
||||
diff.Add(diff, expDiff)
|
||||
diff = common.BigMax(diff, params.MinimumDifficulty)
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
||||
|
||||
// CalcGasLimit computes the gas limit of the next block after parent.
|
||||
// The result may be modified by the caller.
|
||||
// This is miner strategy, not consensus protocol.
|
||||
func CalcGasLimit(parent *types.Block) *big.Int {
|
||||
// contrib = (parentGasUsed * 3 / 2) / 1024
|
||||
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
|
||||
contrib = contrib.Div(contrib, big.NewInt(2))
|
||||
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
|
||||
|
||||
// decay = parentGasLimit / 1024 -1
|
||||
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
|
||||
decay.Sub(decay, big.NewInt(1))
|
||||
|
||||
/*
|
||||
strategy: gasLimit of block-to-mine is set based on parent's
|
||||
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
|
||||
increase it, otherwise lower it (or leave it unchanged if it's right
|
||||
at that usage) the amount increased/decreased depends on how far away
|
||||
from parentGasLimit * (2/3) parentGasUsed is.
|
||||
*/
|
||||
gl := new(big.Int).Sub(parent.GasLimit(), decay)
|
||||
gl = gl.Add(gl, contrib)
|
||||
gl.Set(common.BigMax(gl, params.MinGasLimit))
|
||||
|
||||
// however, if we're now below the target (GenesisGasLimit) we increase the
|
||||
// limit as much as we can (parentGasLimit / 1024 -1)
|
||||
if gl.Cmp(params.GenesisGasLimit) < 0 {
|
||||
gl.Add(parent.GasLimit(), decay)
|
||||
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
|
||||
}
|
||||
return gl
|
||||
}
|
||||
|
||||
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
|
||||
func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
|
||||
data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))
|
||||
|
@ -62,7 +62,7 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestDifficulty(t *testing.T) {
|
||||
func TestDifficultyFrontier(t *testing.T) {
|
||||
file, err := os.Open("../tests/files/BasicTests/difficulty.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -77,7 +77,7 @@ func TestDifficulty(t *testing.T) {
|
||||
|
||||
for name, test := range tests {
|
||||
number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
|
||||
diff := CalcDifficulty(test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
|
||||
diff := calcDifficultyFrontier(test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
|
||||
if diff.Cmp(test.CurrentDifficulty) != 0 {
|
||||
t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
|
||||
}
|
||||
|
@ -33,8 +33,17 @@ func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input
|
||||
|
||||
// CallCode executes the given address' code as the given contract address
|
||||
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
|
||||
prev := caller.Address()
|
||||
ret, _, err = exec(env, caller, &prev, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
|
||||
callerAddr := caller.Address()
|
||||
ret, _, err = exec(env, caller, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope
|
||||
func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
|
||||
callerAddr := caller.Address()
|
||||
originAddr := env.Origin()
|
||||
callerValue := caller.Value()
|
||||
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
@ -52,7 +61,6 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
|
||||
|
||||
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
|
||||
evm := vm.NewVm(env)
|
||||
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if env.Depth() > int(params.CallCreateDepth.Int64()) {
|
||||
@ -69,17 +77,15 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
|
||||
|
||||
var createAccount bool
|
||||
if address == nil {
|
||||
// Generate a new address
|
||||
// Create a new account on the state
|
||||
nonce := env.Db().GetNonce(caller.Address())
|
||||
env.Db().SetNonce(caller.Address(), nonce+1)
|
||||
|
||||
addr = crypto.CreateAddress(caller.Address(), nonce)
|
||||
|
||||
address = &addr
|
||||
createAccount = true
|
||||
}
|
||||
snapshot := env.MakeSnapshot()
|
||||
|
||||
snapshotPreTransfer := env.MakeSnapshot()
|
||||
var (
|
||||
from = env.Db().GetAccount(caller.Address())
|
||||
to vm.Account
|
||||
@ -95,12 +101,68 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
|
||||
}
|
||||
env.Transfer(from, to, value)
|
||||
|
||||
// initialise a new contract and set the code that is to be used by the
|
||||
// EVM. The contract is a scoped environment for this execution context
|
||||
// only.
|
||||
contract := vm.NewContract(caller, to, value, gas, gasPrice)
|
||||
contract.SetCallCode(codeAddr, code)
|
||||
defer contract.Finalise()
|
||||
|
||||
ret, err = evm.Run(contract, input)
|
||||
// if the contract creation ran successfully and no errors were returned
|
||||
// calculate the gas required to store the code. If the code could not
|
||||
// be stored due to not enough gas set an error and let it be handled
|
||||
// by the error checking condition below.
|
||||
if err == nil && createAccount {
|
||||
dataGas := big.NewInt(int64(len(ret)))
|
||||
dataGas.Mul(dataGas, params.CreateDataGas)
|
||||
if contract.UseGas(dataGas) {
|
||||
env.Db().SetCode(*address, ret)
|
||||
} else {
|
||||
err = vm.CodeStoreOutOfGasError
|
||||
}
|
||||
}
|
||||
|
||||
// When an error was returned by the EVM or when setting the creation code
|
||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||
// when we're in homestead this also counts for code storage gas errors.
|
||||
if err != nil && (params.IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
|
||||
contract.UseGas(contract.Gas)
|
||||
|
||||
env.SetSnapshot(snapshotPreTransfer)
|
||||
}
|
||||
|
||||
return ret, addr, err
|
||||
}
|
||||
|
||||
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
|
||||
evm := vm.NewVm(env)
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if env.Depth() > int(params.CallCreateDepth.Int64()) {
|
||||
caller.ReturnGas(gas, gasPrice)
|
||||
return nil, common.Address{}, vm.DepthError
|
||||
}
|
||||
|
||||
snapshot := env.MakeSnapshot()
|
||||
|
||||
var to vm.Account
|
||||
if !env.Db().Exist(*toAddr) {
|
||||
to = env.Db().CreateAccount(*toAddr)
|
||||
} else {
|
||||
to = env.Db().GetAccount(*toAddr)
|
||||
}
|
||||
|
||||
// Iinitialise a new contract and make initialise the delegate values
|
||||
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
|
||||
contract.SetCallCode(codeAddr, code)
|
||||
defer contract.Finalise()
|
||||
|
||||
ret, err = evm.Run(contract, input)
|
||||
if err != nil {
|
||||
env.SetSnapshot(snapshot) //env.Db().Set(snapshot)
|
||||
contract.UseGas(contract.Gas)
|
||||
|
||||
env.SetSnapshot(snapshot)
|
||||
}
|
||||
|
||||
return ret, addr, err
|
||||
|
@ -28,6 +28,7 @@ type Account struct {
|
||||
Nonce uint64 `json:"nonce"`
|
||||
Root string `json:"root"`
|
||||
CodeHash string `json:"codeHash"`
|
||||
Code string `json:"code"`
|
||||
Storage map[string]string `json:"storage"`
|
||||
}
|
||||
|
||||
@ -47,7 +48,7 @@ func (self *StateDB) RawDump() World {
|
||||
addr := self.trie.GetKey(it.Key)
|
||||
stateObject := NewStateObjectFromBytes(common.BytesToAddress(addr), it.Value, self.db)
|
||||
|
||||
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash)}
|
||||
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash), Code: common.Bytes2Hex(stateObject.Code())}
|
||||
account.Storage = make(map[string]string)
|
||||
|
||||
storageIt := stateObject.trie.Iterator()
|
||||
|
@ -260,6 +260,13 @@ func (self *StateObject) Nonce() uint64 {
|
||||
return self.nonce
|
||||
}
|
||||
|
||||
// Never called, but must be present to allow StateObject to be used
|
||||
// as a vm.Account interface that also satisfies the vm.ContractRef
|
||||
// interface. Interfaces are awesome.
|
||||
func (self *StateObject) Value() *big.Int {
|
||||
panic("Value on StateObject should never be called")
|
||||
}
|
||||
|
||||
func (self *StateObject) EachStorage(cb func(key, value []byte)) {
|
||||
// When iterating over the storage check the cache first
|
||||
for h, v := range self.storage {
|
||||
|
@ -55,7 +55,6 @@ type StateDB struct {
|
||||
func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
||||
tr, err := trie.NewSecure(root, db)
|
||||
if err != nil {
|
||||
glog.Errorf("can't create state trie with root %x: %v", root[:], err)
|
||||
return nil, err
|
||||
}
|
||||
return &StateDB{
|
||||
|
@ -43,7 +43,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (ty
|
||||
|
||||
for i, tx := range block.Transactions() {
|
||||
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
||||
|
||||
receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas)
|
||||
if err != nil {
|
||||
return nil, nil, totalUsedGas, err
|
||||
|
@ -27,6 +27,10 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var (
|
||||
Big0 = big.NewInt(0)
|
||||
)
|
||||
|
||||
/*
|
||||
The State Transitioning Model
|
||||
|
||||
@ -59,6 +63,7 @@ type StateTransition struct {
|
||||
// Message represents a message sent to a contract.
|
||||
type Message interface {
|
||||
From() (common.Address, error)
|
||||
FromFrontier() (common.Address, error)
|
||||
To() *common.Address
|
||||
|
||||
GasPrice() *big.Int
|
||||
@ -75,8 +80,13 @@ func MessageCreatesContract(msg Message) bool {
|
||||
|
||||
// IntrinsicGas computes the 'intrisic gas' for a message
|
||||
// with the given data.
|
||||
func IntrinsicGas(data []byte) *big.Int {
|
||||
igas := new(big.Int).Set(params.TxGas)
|
||||
func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
|
||||
igas := new(big.Int)
|
||||
if contractCreation && homestead {
|
||||
igas.Set(params.TxGasContractCreation)
|
||||
} else {
|
||||
igas.Set(params.TxGas)
|
||||
}
|
||||
if len(data) > 0 {
|
||||
var nz int64
|
||||
for _, byt := range data {
|
||||
@ -110,7 +120,15 @@ func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.In
|
||||
}
|
||||
|
||||
func (self *StateTransition) from() (vm.Account, error) {
|
||||
f, err := self.msg.From()
|
||||
var (
|
||||
f common.Address
|
||||
err error
|
||||
)
|
||||
if params.IsHomestead(self.env.BlockNumber()) {
|
||||
f, err = self.msg.From()
|
||||
} else {
|
||||
f, err = self.msg.FromFrontier()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -195,35 +213,35 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
|
||||
if err = self.preCheck(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
msg := self.msg
|
||||
sender, _ := self.from() // err checked in preCheck
|
||||
|
||||
homestead := params.IsHomestead(self.env.BlockNumber())
|
||||
contractCreation := MessageCreatesContract(msg)
|
||||
// Pay intrinsic gas
|
||||
if err = self.useGas(IntrinsicGas(self.data)); err != nil {
|
||||
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
|
||||
return nil, nil, InvalidTxError(err)
|
||||
}
|
||||
|
||||
vmenv := self.env
|
||||
var addr common.Address
|
||||
if MessageCreatesContract(msg) {
|
||||
ret, addr, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
|
||||
if err == nil {
|
||||
dataGas := big.NewInt(int64(len(ret)))
|
||||
dataGas.Mul(dataGas, params.CreateDataGas)
|
||||
if err := self.useGas(dataGas); err == nil {
|
||||
self.state.SetCode(addr, ret)
|
||||
} else {
|
||||
ret = nil // does not affect consensus but useful for StateTests validations
|
||||
glog.V(logger.Core).Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas)
|
||||
}
|
||||
//var addr common.Address
|
||||
if contractCreation {
|
||||
ret, _, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
|
||||
if homestead && err == vm.CodeStoreOutOfGasError {
|
||||
self.gas = Big0
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ret = nil
|
||||
glog.V(logger.Core).Infoln("VM create err:", err)
|
||||
}
|
||||
glog.V(logger.Core).Infoln("VM create err:", err)
|
||||
} else {
|
||||
// Increment the nonce for the next transaction
|
||||
self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
|
||||
ret, err = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.gasPrice, self.value)
|
||||
glog.V(logger.Core).Infoln("VM call err:", err)
|
||||
if err != nil {
|
||||
glog.V(logger.Core).Infoln("VM call err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil && IsValueTransferErr(err) {
|
||||
|
@ -1,263 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"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/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
)
|
||||
|
||||
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
|
||||
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(key)
|
||||
return tx
|
||||
}
|
||||
|
||||
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
|
||||
var m event.TypeMux
|
||||
key, _ := crypto.GenerateKey()
|
||||
newPool := NewTxPool(&m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
newPool.resetState()
|
||||
return newPool, key
|
||||
}
|
||||
|
||||
func TestInvalidTransactions(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
|
||||
tx := transaction(0, big.NewInt(100), key)
|
||||
if err := pool.Add(tx); err != ErrNonExistentAccount {
|
||||
t.Error("expected", ErrNonExistentAccount)
|
||||
}
|
||||
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
if err := pool.Add(tx); err != ErrInsufficientFunds {
|
||||
t.Error("expected", ErrInsufficientFunds)
|
||||
}
|
||||
|
||||
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice()))
|
||||
currentState.AddBalance(from, balance)
|
||||
if err := pool.Add(tx); err != ErrIntrinsicGas {
|
||||
t.Error("expected", ErrIntrinsicGas, "got", err)
|
||||
}
|
||||
|
||||
currentState.SetNonce(from, 1)
|
||||
currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
|
||||
tx = transaction(0, big.NewInt(100000), key)
|
||||
if err := pool.Add(tx); err != ErrNonce {
|
||||
t.Error("expected", ErrNonce)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionQueue(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
tx := transaction(0, big.NewInt(100), key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
|
||||
pool.checkQueue()
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected valid txs to be 1 is", len(pool.pending))
|
||||
}
|
||||
|
||||
tx = transaction(1, big.NewInt(100), key)
|
||||
from, _ = tx.From()
|
||||
currentState.SetNonce(from, 2)
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
pool.checkQueue()
|
||||
if _, ok := pool.pending[tx.Hash()]; ok {
|
||||
t.Error("expected transaction to be in tx pool")
|
||||
}
|
||||
|
||||
if len(pool.queue[from]) > 0 {
|
||||
t.Error("expected transaction queue to be empty. is", len(pool.queue[from]))
|
||||
}
|
||||
|
||||
pool, key = setupTxPool()
|
||||
tx1 := transaction(0, big.NewInt(100), key)
|
||||
tx2 := transaction(10, big.NewInt(100), key)
|
||||
tx3 := transaction(11, big.NewInt(100), key)
|
||||
pool.queueTx(tx1.Hash(), tx1)
|
||||
pool.queueTx(tx2.Hash(), tx2)
|
||||
pool.queueTx(tx3.Hash(), tx3)
|
||||
from, _ = tx1.From()
|
||||
|
||||
pool.checkQueue()
|
||||
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected tx pool to be 1 =")
|
||||
}
|
||||
if len(pool.queue[from]) != 2 {
|
||||
t.Error("expected len(queue) == 2, got", len(pool.queue[from]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveTx(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
tx := transaction(0, big.NewInt(100), key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
pool.addTx(tx.Hash(), from, tx)
|
||||
if len(pool.queue) != 1 {
|
||||
t.Error("expected queue to be 1, got", len(pool.queue))
|
||||
}
|
||||
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected txs to be 1, got", len(pool.pending))
|
||||
}
|
||||
|
||||
pool.RemoveTx(tx.Hash())
|
||||
|
||||
if len(pool.queue) > 0 {
|
||||
t.Error("expected queue to be 0, got", len(pool.queue))
|
||||
}
|
||||
|
||||
if len(pool.pending) > 0 {
|
||||
t.Error("expected txs to be 0, got", len(pool.pending))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeValue(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
|
||||
tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
if err := pool.Add(tx); err != ErrNegativeValue {
|
||||
t.Error("expected", ErrNegativeValue, "got", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionChainFork(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
resetState := func() {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
pool.resetState()
|
||||
}
|
||||
resetState()
|
||||
|
||||
tx := transaction(0, big.NewInt(100000), key)
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
pool.RemoveTransactions([]*types.Transaction{tx})
|
||||
|
||||
// reset the pool's internal state
|
||||
resetState()
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionDoubleNonce(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
resetState := func() {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
pool.resetState()
|
||||
}
|
||||
resetState()
|
||||
|
||||
tx := transaction(0, big.NewInt(100000), key)
|
||||
tx2 := transaction(0, big.NewInt(1000000), key)
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
if err := pool.add(tx2); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
|
||||
pool.checkQueue()
|
||||
if len(pool.pending) != 2 {
|
||||
t.Error("expected 2 pending txs. Got", len(pool.pending))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingNonce(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
tx := transaction(1, big.NewInt(100000), key)
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
if len(pool.pending) != 0 {
|
||||
t.Error("expected 0 pending transactions, got", len(pool.pending))
|
||||
}
|
||||
if len(pool.queue[addr]) != 1 {
|
||||
t.Error("expected 1 queued transaction, got", len(pool.queue[addr]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonceRecovery(t *testing.T) {
|
||||
const n = 10
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.SetNonce(addr, n)
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
pool.resetState()
|
||||
tx := transaction(n, big.NewInt(100000), key)
|
||||
if err := pool.Add(tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// simulate some weird re-order of transactions and missing nonce(s)
|
||||
currentState.SetNonce(addr, n-1)
|
||||
pool.resetState()
|
||||
if fn := pool.pendingState.GetNonce(addr); fn != n+1 {
|
||||
t.Errorf("expected nonce to be %d, got %d", n+1, fn)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovedTxEvent(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
tx := transaction(0, big.NewInt(1000000), key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1000000000000))
|
||||
pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}})
|
||||
pool.eventMux.Post(ChainHeadEvent{nil})
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected 1 pending tx, got", len(pool.pending))
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -65,10 +66,11 @@ type TxPool struct {
|
||||
minGasPrice *big.Int
|
||||
eventMux *event.TypeMux
|
||||
events event.Subscription
|
||||
mu sync.RWMutex
|
||||
pending map[common.Hash]*types.Transaction // processable transactions
|
||||
queue map[common.Address]map[common.Hash]*types.Transaction
|
||||
|
||||
mu sync.RWMutex
|
||||
pending map[common.Hash]*types.Transaction // processable transactions
|
||||
queue map[common.Address]map[common.Hash]*types.Transaction
|
||||
homestead bool
|
||||
}
|
||||
|
||||
func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
|
||||
@ -83,6 +85,7 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
|
||||
pendingState: nil,
|
||||
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
|
||||
}
|
||||
|
||||
go pool.eventLoop()
|
||||
|
||||
return pool
|
||||
@ -96,6 +99,10 @@ func (pool *TxPool) eventLoop() {
|
||||
switch ev := ev.Data.(type) {
|
||||
case ChainHeadEvent:
|
||||
pool.mu.Lock()
|
||||
if ev.Block != nil && params.IsHomestead(ev.Block.Number()) {
|
||||
pool.homestead = true
|
||||
}
|
||||
|
||||
pool.resetState()
|
||||
pool.mu.Unlock()
|
||||
case GasPriceChanged:
|
||||
@ -138,7 +145,6 @@ func (pool *TxPool) resetState() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the queue and move transactions over to the pending if possible
|
||||
// or remove those that have become invalid
|
||||
pool.checkQueue()
|
||||
@ -171,29 +177,23 @@ func (pool *TxPool) Stats() (pending int, queued int) {
|
||||
// validateTx checks whether a transaction is valid according
|
||||
// to the consensus rules.
|
||||
func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
||||
// Validate sender
|
||||
var (
|
||||
from common.Address
|
||||
err error
|
||||
)
|
||||
|
||||
// Drop transactions under our own minimal accepted gas price
|
||||
if pool.minGasPrice.Cmp(tx.GasPrice()) > 0 {
|
||||
return ErrCheap
|
||||
}
|
||||
|
||||
// Validate the transaction sender and it's sig. Throw
|
||||
// if the from fields is invalid.
|
||||
if from, err = tx.From(); err != nil {
|
||||
currentState, err := pool.currentState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
from, err := tx.From()
|
||||
if err != nil {
|
||||
return ErrInvalidSender
|
||||
}
|
||||
|
||||
// Make sure the account exist. Non existent accounts
|
||||
// haven't got funds and well therefor never pass.
|
||||
currentState, err := pool.currentState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !currentState.HasAccount(from) {
|
||||
return ErrNonExistentAccount
|
||||
}
|
||||
@ -222,8 +222,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
||||
return ErrInsufficientFunds
|
||||
}
|
||||
|
||||
// Should supply enough intrinsic gas
|
||||
if tx.Gas().Cmp(IntrinsicGas(tx.Data())) < 0 {
|
||||
intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead)
|
||||
if tx.Gas().Cmp(intrGas) < 0 {
|
||||
return ErrIntrinsicGas
|
||||
}
|
||||
|
||||
@ -290,17 +290,15 @@ func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Trans
|
||||
}
|
||||
|
||||
// Add queues a single transaction in the pool if it is valid.
|
||||
func (self *TxPool) Add(tx *types.Transaction) (err error) {
|
||||
func (self *TxPool) Add(tx *types.Transaction) error {
|
||||
self.mu.Lock()
|
||||
defer self.mu.Unlock()
|
||||
|
||||
err = self.add(tx)
|
||||
if err == nil {
|
||||
// check and validate the queueue
|
||||
self.checkQueue()
|
||||
if err := self.add(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
self.checkQueue()
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddTransactions attempts to queue all valid transactions in txs.
|
||||
@ -368,7 +366,7 @@ func (self *TxPool) GetQueuedTransactions() types.Transactions {
|
||||
ret = append(ret, tx)
|
||||
}
|
||||
}
|
||||
sort.Sort(types.TxByNonce{ret})
|
||||
sort.Sort(types.TxByNonce(ret))
|
||||
return ret
|
||||
}
|
||||
|
||||
@ -406,51 +404,55 @@ func (pool *TxPool) checkQueue() {
|
||||
pool.resetState()
|
||||
}
|
||||
|
||||
var addq txQueue
|
||||
var promote txQueue
|
||||
for address, txs := range pool.queue {
|
||||
// guessed nonce is the nonce currently kept by the tx pool (pending state)
|
||||
guessedNonce := pool.pendingState.GetNonce(address)
|
||||
// true nonce is the nonce known by the last state
|
||||
currentState, err := pool.currentState()
|
||||
if err != nil {
|
||||
glog.Errorf("could not get current state: %v", err)
|
||||
return
|
||||
}
|
||||
trueNonce := currentState.GetNonce(address)
|
||||
addq := addq[:0]
|
||||
balance := currentState.GetBalance(address)
|
||||
|
||||
var (
|
||||
guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state)
|
||||
trueNonce = currentState.GetNonce(address) // nonce known by the last state
|
||||
)
|
||||
promote = promote[:0]
|
||||
for hash, tx := range txs {
|
||||
if tx.Nonce() < trueNonce {
|
||||
// Drop queued transactions whose nonce is lower than
|
||||
// the account nonce because they have been processed.
|
||||
// Drop processed or out of fund transactions
|
||||
if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 {
|
||||
if glog.V(logger.Core) {
|
||||
glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx)
|
||||
}
|
||||
delete(txs, hash)
|
||||
} else {
|
||||
// Collect the remaining transactions for the next pass.
|
||||
addq = append(addq, txQueueEntry{hash, address, tx})
|
||||
}
|
||||
}
|
||||
// Find the next consecutive nonce range starting at the
|
||||
// current account nonce.
|
||||
sort.Sort(addq)
|
||||
for i, e := range addq {
|
||||
// start deleting the transactions from the queue if they exceed the limit
|
||||
if i > maxQueued {
|
||||
delete(pool.queue[address], e.hash)
|
||||
continue
|
||||
}
|
||||
|
||||
if e.Nonce() > guessedNonce {
|
||||
if len(addq)-i > maxQueued {
|
||||
// Collect the remaining transactions for the next pass.
|
||||
promote = append(promote, txQueueEntry{hash, address, tx})
|
||||
}
|
||||
// Find the next consecutive nonce range starting at the current account nonce,
|
||||
// pushing the guessed nonce forward if we add consecutive transactions.
|
||||
sort.Sort(promote)
|
||||
for i, entry := range promote {
|
||||
// If we reached a gap in the nonces, enforce transaction limit and stop
|
||||
if entry.Nonce() > guessedNonce {
|
||||
if len(promote)-i > maxQueued {
|
||||
if glog.V(logger.Debug) {
|
||||
glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:]))
|
||||
glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:]))
|
||||
}
|
||||
for j := i + maxQueued; j < len(addq); j++ {
|
||||
delete(txs, addq[j].hash)
|
||||
for _, drop := range promote[i+maxQueued:] {
|
||||
delete(txs, drop.hash)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
delete(txs, e.hash)
|
||||
pool.addTx(e.hash, address, e.Transaction)
|
||||
// Otherwise promote the transaction and move the guess nonce if needed
|
||||
pool.addTx(entry.hash, address, entry.Transaction)
|
||||
delete(txs, entry.hash)
|
||||
|
||||
if entry.Nonce() == guessedNonce {
|
||||
guessedNonce++
|
||||
}
|
||||
}
|
||||
// Delete the entire queue entry if it became empty.
|
||||
if len(txs) == 0 {
|
||||
@ -460,20 +462,56 @@ func (pool *TxPool) checkQueue() {
|
||||
}
|
||||
|
||||
// validatePool removes invalid and processed transactions from the main pool.
|
||||
// If a transaction is removed for being invalid (e.g. out of funds), all sub-
|
||||
// sequent (Still valid) transactions are moved back into the future queue. This
|
||||
// is important to prevent a drained account from DOSing the network with non
|
||||
// executable transactions.
|
||||
func (pool *TxPool) validatePool() {
|
||||
state, err := pool.currentState()
|
||||
if err != nil {
|
||||
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
|
||||
return
|
||||
}
|
||||
balanceCache := make(map[common.Address]*big.Int)
|
||||
|
||||
// Clean up the pending pool, accumulating invalid nonces
|
||||
gaps := make(map[common.Address]uint64)
|
||||
|
||||
for hash, tx := range pool.pending {
|
||||
from, _ := tx.From() // err already checked
|
||||
// perform light nonce validation
|
||||
if state.GetNonce(from) > tx.Nonce() {
|
||||
sender, _ := tx.From() // err already checked
|
||||
|
||||
// Perform light nonce and balance validation
|
||||
balance := balanceCache[sender]
|
||||
if balance == nil {
|
||||
balance = state.GetBalance(sender)
|
||||
balanceCache[sender] = balance
|
||||
}
|
||||
if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 {
|
||||
// Remove an already past it invalidated transaction
|
||||
if glog.V(logger.Core) {
|
||||
glog.Infof("removed tx (%x) from pool: low tx nonce\n", hash[:4])
|
||||
glog.Infof("removed tx (%v) from pool: low tx nonce or out of funds\n", tx)
|
||||
}
|
||||
delete(pool.pending, hash)
|
||||
|
||||
// Track the smallest invalid nonce to postpone subsequent transactions
|
||||
if !past {
|
||||
if prev, ok := gaps[sender]; !ok || tx.Nonce() < prev {
|
||||
gaps[sender] = tx.Nonce()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Move all transactions after a gap back to the future queue
|
||||
if len(gaps) > 0 {
|
||||
for hash, tx := range pool.pending {
|
||||
sender, _ := tx.From()
|
||||
if gap, ok := gaps[sender]; ok && tx.Nonce() >= gap {
|
||||
if glog.V(logger.Core) {
|
||||
glog.Infof("postponed tx (%v) due to introduced gap\n", tx)
|
||||
}
|
||||
pool.queueTx(hash, tx)
|
||||
delete(pool.pending, hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
526
core/tx_pool_test.go
Normal file
526
core/tx_pool_test.go
Normal file
@ -0,0 +1,526 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"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/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
)
|
||||
|
||||
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
|
||||
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(key)
|
||||
return tx
|
||||
}
|
||||
|
||||
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
|
||||
var m event.TypeMux
|
||||
key, _ := crypto.GenerateKey()
|
||||
newPool := NewTxPool(&m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
newPool.resetState()
|
||||
return newPool, key
|
||||
}
|
||||
|
||||
func TestInvalidTransactions(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
|
||||
tx := transaction(0, big.NewInt(100), key)
|
||||
if err := pool.Add(tx); err != ErrNonExistentAccount {
|
||||
t.Error("expected", ErrNonExistentAccount)
|
||||
}
|
||||
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
if err := pool.Add(tx); err != ErrInsufficientFunds {
|
||||
t.Error("expected", ErrInsufficientFunds)
|
||||
}
|
||||
|
||||
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice()))
|
||||
currentState.AddBalance(from, balance)
|
||||
if err := pool.Add(tx); err != ErrIntrinsicGas {
|
||||
t.Error("expected", ErrIntrinsicGas, "got", err)
|
||||
}
|
||||
|
||||
currentState.SetNonce(from, 1)
|
||||
currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
|
||||
tx = transaction(0, big.NewInt(100000), key)
|
||||
if err := pool.Add(tx); err != ErrNonce {
|
||||
t.Error("expected", ErrNonce)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionQueue(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
tx := transaction(0, big.NewInt(100), key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1000))
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
|
||||
pool.checkQueue()
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected valid txs to be 1 is", len(pool.pending))
|
||||
}
|
||||
|
||||
tx = transaction(1, big.NewInt(100), key)
|
||||
from, _ = tx.From()
|
||||
currentState.SetNonce(from, 2)
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
pool.checkQueue()
|
||||
if _, ok := pool.pending[tx.Hash()]; ok {
|
||||
t.Error("expected transaction to be in tx pool")
|
||||
}
|
||||
|
||||
if len(pool.queue[from]) > 0 {
|
||||
t.Error("expected transaction queue to be empty. is", len(pool.queue[from]))
|
||||
}
|
||||
|
||||
pool, key = setupTxPool()
|
||||
tx1 := transaction(0, big.NewInt(100), key)
|
||||
tx2 := transaction(10, big.NewInt(100), key)
|
||||
tx3 := transaction(11, big.NewInt(100), key)
|
||||
from, _ = tx1.From()
|
||||
currentState, _ = pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1000))
|
||||
pool.queueTx(tx1.Hash(), tx1)
|
||||
pool.queueTx(tx2.Hash(), tx2)
|
||||
pool.queueTx(tx3.Hash(), tx3)
|
||||
|
||||
pool.checkQueue()
|
||||
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected tx pool to be 1, got", len(pool.pending))
|
||||
}
|
||||
if len(pool.queue[from]) != 2 {
|
||||
t.Error("expected len(queue) == 2, got", len(pool.queue[from]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveTx(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
tx := transaction(0, big.NewInt(100), key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
pool.addTx(tx.Hash(), from, tx)
|
||||
if len(pool.queue) != 1 {
|
||||
t.Error("expected queue to be 1, got", len(pool.queue))
|
||||
}
|
||||
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected txs to be 1, got", len(pool.pending))
|
||||
}
|
||||
|
||||
pool.RemoveTx(tx.Hash())
|
||||
|
||||
if len(pool.queue) > 0 {
|
||||
t.Error("expected queue to be 0, got", len(pool.queue))
|
||||
}
|
||||
|
||||
if len(pool.pending) > 0 {
|
||||
t.Error("expected txs to be 0, got", len(pool.pending))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeValue(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
|
||||
tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1))
|
||||
if err := pool.Add(tx); err != ErrNegativeValue {
|
||||
t.Error("expected", ErrNegativeValue, "got", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionChainFork(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
resetState := func() {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
pool.resetState()
|
||||
}
|
||||
resetState()
|
||||
|
||||
tx := transaction(0, big.NewInt(100000), key)
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
pool.RemoveTransactions([]*types.Transaction{tx})
|
||||
|
||||
// reset the pool's internal state
|
||||
resetState()
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionDoubleNonce(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
resetState := func() {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
pool.resetState()
|
||||
}
|
||||
resetState()
|
||||
|
||||
tx := transaction(0, big.NewInt(100000), key)
|
||||
tx2 := transaction(0, big.NewInt(1000000), key)
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
if err := pool.add(tx2); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
|
||||
pool.checkQueue()
|
||||
if len(pool.pending) != 2 {
|
||||
t.Error("expected 2 pending txs. Got", len(pool.pending))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingNonce(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
tx := transaction(1, big.NewInt(100000), key)
|
||||
if err := pool.add(tx); err != nil {
|
||||
t.Error("didn't expect error", err)
|
||||
}
|
||||
if len(pool.pending) != 0 {
|
||||
t.Error("expected 0 pending transactions, got", len(pool.pending))
|
||||
}
|
||||
if len(pool.queue[addr]) != 1 {
|
||||
t.Error("expected 1 queued transaction, got", len(pool.queue[addr]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonceRecovery(t *testing.T) {
|
||||
const n = 10
|
||||
pool, key := setupTxPool()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.SetNonce(addr, n)
|
||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||
pool.resetState()
|
||||
tx := transaction(n, big.NewInt(100000), key)
|
||||
if err := pool.Add(tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// simulate some weird re-order of transactions and missing nonce(s)
|
||||
currentState.SetNonce(addr, n-1)
|
||||
pool.resetState()
|
||||
if fn := pool.pendingState.GetNonce(addr); fn != n+1 {
|
||||
t.Errorf("expected nonce to be %d, got %d", n+1, fn)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovedTxEvent(t *testing.T) {
|
||||
pool, key := setupTxPool()
|
||||
tx := transaction(0, big.NewInt(1000000), key)
|
||||
from, _ := tx.From()
|
||||
currentState, _ := pool.currentState()
|
||||
currentState.AddBalance(from, big.NewInt(1000000000000))
|
||||
pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}})
|
||||
pool.eventMux.Post(ChainHeadEvent{nil})
|
||||
if len(pool.pending) != 1 {
|
||||
t.Error("expected 1 pending tx, got", len(pool.pending))
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that if an account runs out of funds, any pending and queued transactions
|
||||
// are dropped.
|
||||
func TestTransactionDropping(t *testing.T) {
|
||||
// Create a test account and fund it
|
||||
pool, key := setupTxPool()
|
||||
account, _ := transaction(0, big.NewInt(0), key).From()
|
||||
|
||||
state, _ := pool.currentState()
|
||||
state.AddBalance(account, big.NewInt(1000))
|
||||
|
||||
// Add some pending and some queued transactions
|
||||
var (
|
||||
tx0 = transaction(0, big.NewInt(100), key)
|
||||
tx1 = transaction(1, big.NewInt(200), key)
|
||||
tx10 = transaction(10, big.NewInt(100), key)
|
||||
tx11 = transaction(11, big.NewInt(200), key)
|
||||
)
|
||||
pool.addTx(tx0.Hash(), account, tx0)
|
||||
pool.addTx(tx1.Hash(), account, tx1)
|
||||
pool.queueTx(tx10.Hash(), tx10)
|
||||
pool.queueTx(tx11.Hash(), tx11)
|
||||
|
||||
// Check that pre and post validations leave the pool as is
|
||||
if len(pool.pending) != 2 {
|
||||
t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), 2)
|
||||
}
|
||||
if len(pool.queue[account]) != 2 {
|
||||
t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 2)
|
||||
}
|
||||
pool.resetState()
|
||||
if len(pool.pending) != 2 {
|
||||
t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), 2)
|
||||
}
|
||||
if len(pool.queue[account]) != 2 {
|
||||
t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 2)
|
||||
}
|
||||
// Reduce the balance of the account, and check that invalidated transactions are dropped
|
||||
state.AddBalance(account, big.NewInt(-750))
|
||||
pool.resetState()
|
||||
|
||||
if _, ok := pool.pending[tx0.Hash()]; !ok {
|
||||
t.Errorf("funded pending transaction missing: %v", tx0)
|
||||
}
|
||||
if _, ok := pool.pending[tx1.Hash()]; ok {
|
||||
t.Errorf("out-of-fund pending transaction present: %v", tx1)
|
||||
}
|
||||
if _, ok := pool.queue[account][tx10.Hash()]; !ok {
|
||||
t.Errorf("funded queued transaction missing: %v", tx10)
|
||||
}
|
||||
if _, ok := pool.queue[account][tx11.Hash()]; ok {
|
||||
t.Errorf("out-of-fund queued transaction present: %v", tx11)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that if a transaction is dropped from the current pending pool (e.g. out
|
||||
// of fund), all consecutive (still valid, but not executable) transactions are
|
||||
// postponed back into the future queue to prevent broadcating them.
|
||||
func TestTransactionPostponing(t *testing.T) {
|
||||
// Create a test account and fund it
|
||||
pool, key := setupTxPool()
|
||||
account, _ := transaction(0, big.NewInt(0), key).From()
|
||||
|
||||
state, _ := pool.currentState()
|
||||
state.AddBalance(account, big.NewInt(1000))
|
||||
|
||||
// Add a batch consecutive pending transactions for validation
|
||||
txns := []*types.Transaction{}
|
||||
for i := 0; i < 100; i++ {
|
||||
var tx *types.Transaction
|
||||
if i%2 == 0 {
|
||||
tx = transaction(uint64(i), big.NewInt(100), key)
|
||||
} else {
|
||||
tx = transaction(uint64(i), big.NewInt(500), key)
|
||||
}
|
||||
pool.addTx(tx.Hash(), account, tx)
|
||||
txns = append(txns, tx)
|
||||
}
|
||||
// Check that pre and post validations leave the pool as is
|
||||
if len(pool.pending) != len(txns) {
|
||||
t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), len(txns))
|
||||
}
|
||||
if len(pool.queue[account]) != 0 {
|
||||
t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 0)
|
||||
}
|
||||
pool.resetState()
|
||||
if len(pool.pending) != len(txns) {
|
||||
t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), len(txns))
|
||||
}
|
||||
if len(pool.queue[account]) != 0 {
|
||||
t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 0)
|
||||
}
|
||||
// Reduce the balance of the account, and check that transactions are reorganized
|
||||
state.AddBalance(account, big.NewInt(-750))
|
||||
pool.resetState()
|
||||
|
||||
if _, ok := pool.pending[txns[0].Hash()]; !ok {
|
||||
t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0])
|
||||
}
|
||||
if _, ok := pool.queue[account][txns[0].Hash()]; ok {
|
||||
t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0])
|
||||
}
|
||||
for i, tx := range txns[1:] {
|
||||
if i%2 == 1 {
|
||||
if _, ok := pool.pending[tx.Hash()]; ok {
|
||||
t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx)
|
||||
}
|
||||
if _, ok := pool.queue[account][tx.Hash()]; !ok {
|
||||
t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx)
|
||||
}
|
||||
} else {
|
||||
if _, ok := pool.pending[tx.Hash()]; ok {
|
||||
t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx)
|
||||
}
|
||||
if _, ok := pool.queue[account][tx.Hash()]; ok {
|
||||
t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that if the transaction count belonging to a single account goes above
|
||||
// some threshold, the higher transactions are dropped to prevent DOS attacks.
|
||||
func TestTransactionQueueLimiting(t *testing.T) {
|
||||
// Create a test account and fund it
|
||||
pool, key := setupTxPool()
|
||||
account, _ := transaction(0, big.NewInt(0), key).From()
|
||||
|
||||
state, _ := pool.currentState()
|
||||
state.AddBalance(account, big.NewInt(1000000))
|
||||
|
||||
// Keep queuing up transactions and make sure all above a limit are dropped
|
||||
for i := uint64(1); i <= maxQueued+5; i++ {
|
||||
if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
|
||||
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
|
||||
}
|
||||
if len(pool.pending) != 0 {
|
||||
t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0)
|
||||
}
|
||||
if i <= maxQueued {
|
||||
if len(pool.queue[account]) != int(i) {
|
||||
t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, len(pool.queue[account]), i)
|
||||
}
|
||||
} else {
|
||||
if len(pool.queue[account]) != maxQueued {
|
||||
t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, len(pool.queue[account]), maxQueued)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that even if the transaction count belonging to a single account goes
|
||||
// above some threshold, as long as the transactions are executable, they are
|
||||
// accepted.
|
||||
func TestTransactionPendingLimiting(t *testing.T) {
|
||||
// Create a test account and fund it
|
||||
pool, key := setupTxPool()
|
||||
account, _ := transaction(0, big.NewInt(0), key).From()
|
||||
|
||||
state, _ := pool.currentState()
|
||||
state.AddBalance(account, big.NewInt(1000000))
|
||||
|
||||
// Keep queuing up transactions and make sure all above a limit are dropped
|
||||
for i := uint64(0); i < maxQueued+5; i++ {
|
||||
if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
|
||||
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
|
||||
}
|
||||
if len(pool.pending) != int(i)+1 {
|
||||
t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), i+1)
|
||||
}
|
||||
if len(pool.queue[account]) != 0 {
|
||||
t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, len(pool.queue[account]), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that the transaction limits are enforced the same way irrelevant whether
|
||||
// the transactions are added one by one or in batches.
|
||||
func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) }
|
||||
func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 0) }
|
||||
|
||||
func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
|
||||
// Add a batch of transactions to a pool one by one
|
||||
pool1, key1 := setupTxPool()
|
||||
account1, _ := transaction(0, big.NewInt(0), key1).From()
|
||||
state1, _ := pool1.currentState()
|
||||
state1.AddBalance(account1, big.NewInt(1000000))
|
||||
|
||||
for i := uint64(0); i < maxQueued+5; i++ {
|
||||
if err := pool1.Add(transaction(origin+i, big.NewInt(100000), key1)); err != nil {
|
||||
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
|
||||
}
|
||||
}
|
||||
// Add a batch of transactions to a pool in one bit batch
|
||||
pool2, key2 := setupTxPool()
|
||||
account2, _ := transaction(0, big.NewInt(0), key2).From()
|
||||
state2, _ := pool2.currentState()
|
||||
state2.AddBalance(account2, big.NewInt(1000000))
|
||||
|
||||
txns := []*types.Transaction{}
|
||||
for i := uint64(0); i < maxQueued+5; i++ {
|
||||
txns = append(txns, transaction(origin+i, big.NewInt(100000), key2))
|
||||
}
|
||||
pool2.AddTransactions(txns)
|
||||
|
||||
// Ensure the batch optimization honors the same pool mechanics
|
||||
if len(pool1.pending) != len(pool2.pending) {
|
||||
t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending))
|
||||
}
|
||||
if len(pool1.queue[account1]) != len(pool2.queue[account2]) {
|
||||
t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue[account1]), len(pool2.queue[account2]))
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmarks the speed of validating the contents of the pending queue of the
|
||||
// transaction pool.
|
||||
func BenchmarkValidatePool100(b *testing.B) { benchmarkValidatePool(b, 100) }
|
||||
func BenchmarkValidatePool1000(b *testing.B) { benchmarkValidatePool(b, 1000) }
|
||||
func BenchmarkValidatePool10000(b *testing.B) { benchmarkValidatePool(b, 10000) }
|
||||
|
||||
func benchmarkValidatePool(b *testing.B, size int) {
|
||||
// Add a batch of transactions to a pool one by one
|
||||
pool, key := setupTxPool()
|
||||
account, _ := transaction(0, big.NewInt(0), key).From()
|
||||
state, _ := pool.currentState()
|
||||
state.AddBalance(account, big.NewInt(1000000))
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
tx := transaction(uint64(i), big.NewInt(100000), key)
|
||||
pool.addTx(tx.Hash(), account, tx)
|
||||
}
|
||||
// Benchmark the speed of pool validation
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
pool.validatePool()
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmarks the speed of scheduling the contents of the future queue of the
|
||||
// transaction pool.
|
||||
func BenchmarkCheckQueue100(b *testing.B) { benchmarkCheckQueue(b, 100) }
|
||||
func BenchmarkCheckQueue1000(b *testing.B) { benchmarkCheckQueue(b, 1000) }
|
||||
func BenchmarkCheckQueue10000(b *testing.B) { benchmarkCheckQueue(b, 10000) }
|
||||
|
||||
func benchmarkCheckQueue(b *testing.B, size int) {
|
||||
// Add a batch of transactions to a pool one by one
|
||||
pool, key := setupTxPool()
|
||||
account, _ := transaction(0, big.NewInt(0), key).From()
|
||||
state, _ := pool.currentState()
|
||||
state.AddBalance(account, big.NewInt(1000000))
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
tx := transaction(uint64(1+i), big.NewInt(100000), key)
|
||||
pool.queueTx(tx.Hash(), tx)
|
||||
}
|
||||
// Benchmark the speed of pool validation
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
pool.checkQueue()
|
||||
}
|
||||
}
|
@ -17,11 +17,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -155,11 +157,47 @@ func (tx *Transaction) Size() common.StorageSize {
|
||||
return common.StorageSize(c)
|
||||
}
|
||||
|
||||
// From returns the address derived from the signature (V, R, S) using secp256k1
|
||||
// eliptic curve and an error if it failed deriving or upon an incorrect
|
||||
// signature.
|
||||
//
|
||||
// From Uses the homestead consensus rules to determine whether the signature is
|
||||
// valid.
|
||||
//
|
||||
// From caches the address, allowing it to be used regardless of
|
||||
// Frontier / Homestead. however, the first time called it runs
|
||||
// signature validations, so we need two versions. This makes it
|
||||
// easier to ensure backwards compatibility of things like package rpc
|
||||
// where eth_getblockbynumber uses tx.From() and needs to work for
|
||||
// both txs before and after the first homestead block. Signatures
|
||||
// valid in homestead are a subset of valid ones in Frontier)
|
||||
func (tx *Transaction) From() (common.Address, error) {
|
||||
return doFrom(tx, true)
|
||||
}
|
||||
|
||||
// FromFrontier returns the address derived from the signature (V, R, S) using
|
||||
// secp256k1 eliptic curve and an error if it failed deriving or upon an
|
||||
// incorrect signature.
|
||||
//
|
||||
// FromFrantier uses the frontier consensus rules to determine whether the
|
||||
// signature is valid.
|
||||
//
|
||||
// FromFrontier caches the address, allowing it to be used regardless of
|
||||
// Frontier / Homestead. however, the first time called it runs
|
||||
// signature validations, so we need two versions. This makes it
|
||||
// easier to ensure backwards compatibility of things like package rpc
|
||||
// where eth_getblockbynumber uses tx.From() and needs to work for
|
||||
// both txs before and after the first homestead block. Signatures
|
||||
// valid in homestead are a subset of valid ones in Frontier)
|
||||
func (tx *Transaction) FromFrontier() (common.Address, error) {
|
||||
return doFrom(tx, false)
|
||||
}
|
||||
|
||||
func doFrom(tx *Transaction, homestead bool) (common.Address, error) {
|
||||
if from := tx.from.Load(); from != nil {
|
||||
return from.(common.Address), nil
|
||||
}
|
||||
pubkey, err := tx.publicKey()
|
||||
pubkey, err := tx.publicKey(homestead)
|
||||
if err != nil {
|
||||
return common.Address{}, err
|
||||
}
|
||||
@ -180,8 +218,8 @@ func (tx *Transaction) SignatureValues() (v byte, r *big.Int, s *big.Int) {
|
||||
return tx.data.V, new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
|
||||
}
|
||||
|
||||
func (tx *Transaction) publicKey() ([]byte, error) {
|
||||
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S) {
|
||||
func (tx *Transaction) publicKey(homestead bool) ([]byte, error) {
|
||||
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S, homestead) {
|
||||
return nil, ErrInvalidSig
|
||||
}
|
||||
|
||||
@ -302,27 +340,78 @@ func TxDifference(a, b Transactions) (keep Transactions) {
|
||||
return keep
|
||||
}
|
||||
|
||||
type TxByNonce struct{ Transactions }
|
||||
// TxByNonce implements the sort interface to allow sorting a list of transactions
|
||||
// by their nonces. This is usually only useful for sorting transactions from a
|
||||
// single account, otherwise a nonce comparison doesn't make much sense.
|
||||
type TxByNonce Transactions
|
||||
|
||||
func (s TxByNonce) Less(i, j int) bool {
|
||||
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
|
||||
func (s TxByNonce) Len() int { return len(s) }
|
||||
func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce }
|
||||
func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// TxByPrice implements both the sort and the heap interface, making it useful
|
||||
// for all at once sorting as well as individually adding and removing elements.
|
||||
type TxByPrice Transactions
|
||||
|
||||
func (s TxByPrice) Len() int { return len(s) }
|
||||
func (s TxByPrice) Less(i, j int) bool { return s[i].data.Price.Cmp(s[j].data.Price) > 0 }
|
||||
func (s TxByPrice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
func (s *TxByPrice) Push(x interface{}) {
|
||||
*s = append(*s, x.(*Transaction))
|
||||
}
|
||||
|
||||
type TxByPrice struct{ Transactions }
|
||||
|
||||
func (s TxByPrice) Less(i, j int) bool {
|
||||
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
|
||||
func (s *TxByPrice) Pop() interface{} {
|
||||
old := *s
|
||||
n := len(old)
|
||||
x := old[n-1]
|
||||
*s = old[0 : n-1]
|
||||
return x
|
||||
}
|
||||
|
||||
type TxByPriceAndNonce struct{ Transactions }
|
||||
|
||||
func (s TxByPriceAndNonce) Less(i, j int) bool {
|
||||
// we can ignore the error here. Sorting shouldn't care about validness
|
||||
ifrom, _ := s.Transactions[i].From()
|
||||
jfrom, _ := s.Transactions[j].From()
|
||||
// favour nonce if they are from the same recipient
|
||||
if ifrom == jfrom {
|
||||
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
|
||||
// SortByPriceAndNonce sorts the transactions by price in such a way that the
|
||||
// nonce orderings within a single account are maintained.
|
||||
//
|
||||
// Note, this is not as trivial as it seems from the first look as there are three
|
||||
// different criteria that need to be taken into account (price, nonce, account
|
||||
// match), which cannot be done with any plain sorting method, as certain items
|
||||
// cannot be compared without context.
|
||||
//
|
||||
// This method first sorts the separates the list of transactions into individual
|
||||
// sender accounts and sorts them by nonce. After the account nonce ordering is
|
||||
// satisfied, the results are merged back together by price, always comparing only
|
||||
// the head transaction from each account. This is done via a heap to keep it fast.
|
||||
func SortByPriceAndNonce(txs []*Transaction) {
|
||||
// Separate the transactions by account and sort by nonce
|
||||
byNonce := make(map[common.Address][]*Transaction)
|
||||
for _, tx := range txs {
|
||||
acc, _ := tx.From() // we only sort valid txs so this cannot fail
|
||||
byNonce[acc] = append(byNonce[acc], tx)
|
||||
}
|
||||
for _, accTxs := range byNonce {
|
||||
sort.Sort(TxByNonce(accTxs))
|
||||
}
|
||||
// Initialize a price based heap with the head transactions
|
||||
byPrice := make(TxByPrice, 0, len(byNonce))
|
||||
for acc, accTxs := range byNonce {
|
||||
byPrice = append(byPrice, accTxs[0])
|
||||
byNonce[acc] = accTxs[1:]
|
||||
}
|
||||
heap.Init(&byPrice)
|
||||
|
||||
// Merge by replacing the best with the next from the same account
|
||||
txs = txs[:0]
|
||||
for len(byPrice) > 0 {
|
||||
// Retrieve the next best transaction by price
|
||||
best := heap.Pop(&byPrice).(*Transaction)
|
||||
|
||||
// Push in its place the next transaction from the same account
|
||||
acc, _ := best.From() // we only sort valid txs so this cannot fail
|
||||
if accTxs, ok := byNonce[acc]; ok && len(accTxs) > 0 {
|
||||
heap.Push(&byPrice, accTxs[0])
|
||||
byNonce[acc] = accTxs[1:]
|
||||
}
|
||||
// Accumulate the best priced transaction
|
||||
txs = append(txs, best)
|
||||
}
|
||||
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
|
||||
}
|
||||
|
@ -117,3 +117,60 @@ func TestRecipientNormal(t *testing.T) {
|
||||
t.Error("derived address doesn't match")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that transactions can be correctly sorted according to their price in
|
||||
// decreasing order, but at the same time with increasing nonces when issued by
|
||||
// the same account.
|
||||
func TestTransactionPriceNonceSort(t *testing.T) {
|
||||
// Generate a batch of accounts to start with
|
||||
keys := make([]*ecdsa.PrivateKey, 25)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
// Generate a batch of transactions with overlapping values, but shifted nonces
|
||||
txs := []*Transaction{}
|
||||
for start, key := range keys {
|
||||
for i := 0; i < 25; i++ {
|
||||
tx, _ := NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+i)), nil).SignECDSA(key)
|
||||
txs = append(txs, tx)
|
||||
}
|
||||
}
|
||||
// Sort the transactions and cross check the nonce ordering
|
||||
SortByPriceAndNonce(txs)
|
||||
for i, txi := range txs {
|
||||
fromi, _ := txi.From()
|
||||
|
||||
// Make sure the nonce order is valid
|
||||
for j, txj := range txs[i+1:] {
|
||||
fromj, _ := txj.From()
|
||||
|
||||
if fromi == fromj && txi.Nonce() > txj.Nonce() {
|
||||
t.Errorf("invalid nonce ordering: tx #%d (A=%x N=%v) < tx #%d (A=%x N=%v)", i, fromi[:4], txi.Nonce(), i+j, fromj[:4], txj.Nonce())
|
||||
}
|
||||
}
|
||||
// Find the previous and next nonce of this account
|
||||
prev, next := i-1, i+1
|
||||
for j := i - 1; j >= 0; j-- {
|
||||
if fromj, _ := txs[j].From(); fromi == fromj {
|
||||
prev = j
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := i + 1; j < len(txs); j++ {
|
||||
if fromj, _ := txs[j].From(); fromi == fromj {
|
||||
next = j
|
||||
break
|
||||
}
|
||||
}
|
||||
// Make sure that in between the neighbor nonces, the transaction is correctly positioned price wise
|
||||
for j := prev + 1; j < next; j++ {
|
||||
fromj, _ := txs[j].From()
|
||||
if j < i && txs[j].GasPrice().Cmp(txi.GasPrice()) < 0 {
|
||||
t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)", j, fromj[:4], txs[j].GasPrice(), i, fromi[:4], txi.GasPrice())
|
||||
}
|
||||
if j > i && txs[j].GasPrice().Cmp(txi.GasPrice()) > 0 {
|
||||
t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) > tx #%d (A=%x P=%v)", j, fromj[:4], txs[j].GasPrice(), i, fromi[:4], txi.GasPrice())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,14 +26,19 @@ import (
|
||||
type ContractRef interface {
|
||||
ReturnGas(*big.Int, *big.Int)
|
||||
Address() common.Address
|
||||
Value() *big.Int
|
||||
SetCode([]byte)
|
||||
}
|
||||
|
||||
// Contract represents an ethereum contract in the state database. It contains
|
||||
// the the contract code, calling arguments. Contract implements ContractReg
|
||||
// the the contract code, calling arguments. Contract implements ContractRef
|
||||
type Contract struct {
|
||||
caller ContractRef
|
||||
self ContractRef
|
||||
// CallerAddress is the result of the caller which initialised this
|
||||
// contract. However when the "call method" is delegated this value
|
||||
// needs to be initialised to that of the caller's caller.
|
||||
CallerAddress common.Address
|
||||
caller ContractRef
|
||||
self ContractRef
|
||||
|
||||
jumpdests destinations // result of JUMPDEST analysis.
|
||||
|
||||
@ -44,11 +49,13 @@ type Contract struct {
|
||||
value, Gas, UsedGas, Price *big.Int
|
||||
|
||||
Args []byte
|
||||
|
||||
DelegateCall bool
|
||||
}
|
||||
|
||||
// Create a new context for the given data items.
|
||||
// NewContract returns a new contract environment for the execution of EVM.
|
||||
func NewContract(caller ContractRef, object ContractRef, value, gas, price *big.Int) *Contract {
|
||||
c := &Contract{caller: caller, self: object, Args: nil}
|
||||
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
|
||||
|
||||
if parent, ok := caller.(*Contract); ok {
|
||||
// Reuse JUMPDEST analysis from parent context if available.
|
||||
@ -69,6 +76,16 @@ func NewContract(caller ContractRef, object ContractRef, value, gas, price *big.
|
||||
return c
|
||||
}
|
||||
|
||||
// AsDelegate sets the contract to be a delegate call and returns the current
|
||||
// contract (for chaining calls)
|
||||
func (c *Contract) AsDelegate() *Contract {
|
||||
c.DelegateCall = true
|
||||
// NOTE: caller must, at all times be a contract. It should never happen
|
||||
// that caller is something other than a Contract.
|
||||
c.CallerAddress = c.caller.(*Contract).CallerAddress
|
||||
return c
|
||||
}
|
||||
|
||||
// GetOp returns the n'th element in the contract's byte array
|
||||
func (c *Contract) GetOp(n uint64) OpCode {
|
||||
return OpCode(c.GetByte(n))
|
||||
@ -83,13 +100,19 @@ func (c *Contract) GetByte(n uint64) byte {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Return returns the given ret argument and returns any remaining gas to the
|
||||
// caller
|
||||
func (c *Contract) Return(ret []byte) []byte {
|
||||
// Caller returns the caller of the contract.
|
||||
//
|
||||
// Caller will recursively call caller when the contract is a delegate
|
||||
// call, including that of caller's caller.
|
||||
func (c *Contract) Caller() common.Address {
|
||||
return c.CallerAddress
|
||||
}
|
||||
|
||||
// Finalise finalises the contract and returning any remaining gas to the original
|
||||
// caller.
|
||||
func (c *Contract) Finalise() {
|
||||
// Return the remaining gas to the caller
|
||||
c.caller.ReturnGas(c.Gas, c.Price)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// UseGas attempts the use gas and subtracts it and returns true on success
|
||||
@ -113,6 +136,11 @@ func (c *Contract) Address() common.Address {
|
||||
return c.self.Address()
|
||||
}
|
||||
|
||||
// Value returns the contracts value (sent to it from it's caller)
|
||||
func (c *Contract) Value() *big.Int {
|
||||
return c.value
|
||||
}
|
||||
|
||||
// SetCode sets the code to the contract
|
||||
func (self *Contract) SetCode(code []byte) {
|
||||
self.Code = code
|
||||
|
@ -93,7 +93,8 @@ func ecrecoverFunc(in []byte) []byte {
|
||||
vbig := common.Bytes2Big(in[32:64])
|
||||
v := byte(vbig.Uint64())
|
||||
|
||||
if !crypto.ValidateSignatureValues(v, r, s) {
|
||||
// tighter sig s values in homestead only apply to tx sigs
|
||||
if !crypto.ValidateSignatureValues(v, r, s, false) {
|
||||
glog.V(logger.Debug).Infof("EC RECOVER FAIL: v, r or s value invalid")
|
||||
return nil
|
||||
}
|
||||
|
@ -70,6 +70,8 @@ type Environment interface {
|
||||
Call(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
||||
// Take another's contract code and execute within our own context
|
||||
CallCode(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
||||
// Same as CallCode except sender and value is propagated from parent to child scope
|
||||
DelegateCall(me ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error)
|
||||
// Create a new contract
|
||||
Create(me ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error)
|
||||
}
|
||||
@ -121,4 +123,6 @@ type Account interface {
|
||||
Address() common.Address
|
||||
ReturnGas(*big.Int, *big.Int)
|
||||
SetCode([]byte)
|
||||
EachStorage(cb func(key, value []byte))
|
||||
Value() *big.Int
|
||||
}
|
||||
|
@ -24,4 +24,5 @@ import (
|
||||
)
|
||||
|
||||
var OutOfGasError = errors.New("Out of gas")
|
||||
var CodeStoreOutOfGasError = errors.New("Contract creation code storage out of gas")
|
||||
var DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth)
|
||||
|
@ -136,6 +136,7 @@ var _baseCheck = map[OpCode]req{
|
||||
CREATE: {3, params.CreateGas, 1},
|
||||
CALL: {7, params.CallGas, 1},
|
||||
CALLCODE: {7, params.CallGas, 1},
|
||||
DELEGATECALL: {6, params.CallGas, 1},
|
||||
JUMPDEST: {0, params.JumpdestGas, 0},
|
||||
SUICIDE: {1, Zero, 0},
|
||||
RETURN: {2, Zero, 0},
|
||||
|
@ -337,7 +337,7 @@ func opOrigin(instr instruction, pc *uint64, env Environment, contract *Contract
|
||||
}
|
||||
|
||||
func opCaller(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||
stack.push(common.Bytes2Big(contract.caller.Address().Bytes()))
|
||||
stack.push(contract.Caller().Big())
|
||||
}
|
||||
|
||||
func opCallValue(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||
@ -485,7 +485,6 @@ func opSload(instr instruction, pc *uint64, env Environment, contract *Contract,
|
||||
func opSstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||
loc := common.BigToHash(stack.pop())
|
||||
val := stack.pop()
|
||||
|
||||
env.Db().SetState(contract.Address(), loc, common.BigToHash(val))
|
||||
}
|
||||
|
||||
@ -514,25 +513,19 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
|
||||
offset, size = stack.pop(), stack.pop()
|
||||
input = memory.Get(offset.Int64(), size.Int64())
|
||||
gas = new(big.Int).Set(contract.Gas)
|
||||
addr common.Address
|
||||
ret []byte
|
||||
suberr error
|
||||
)
|
||||
|
||||
contract.UseGas(contract.Gas)
|
||||
ret, addr, suberr = env.Create(contract, input, gas, contract.Price, value)
|
||||
if suberr != nil {
|
||||
_, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
|
||||
// Push item on the stack based on the returned error. If the ruleset is
|
||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||
// rule) and treat as an error, if the ruleset is frontier we must
|
||||
// ignore this error and pretend the operation was successful.
|
||||
if params.IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
|
||||
stack.push(new(big.Int))
|
||||
} else if suberr != nil && suberr != CodeStoreOutOfGasError {
|
||||
stack.push(new(big.Int))
|
||||
} else {
|
||||
// gas < len(ret) * Createinstr.dataGas == NO_CODE
|
||||
dataGas := big.NewInt(int64(len(ret)))
|
||||
dataGas.Mul(dataGas, params.CreateDataGas)
|
||||
if contract.UseGas(dataGas) {
|
||||
env.Db().SetCode(addr, ret)
|
||||
}
|
||||
|
||||
stack.push(addr.Big())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,6 +591,21 @@ func opCallCode(instr instruction, pc *uint64, env Environment, contract *Contra
|
||||
}
|
||||
}
|
||||
|
||||
func opDelegateCall(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||
gas, to, inOffset, inSize, outOffset, outSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||
|
||||
toAddr := common.BigToAddress(to)
|
||||
args := memory.Get(inOffset.Int64(), inSize.Int64())
|
||||
ret, err := env.DelegateCall(contract, toAddr, args, gas, contract.Price)
|
||||
|
||||
if err != nil {
|
||||
stack.push(new(big.Int))
|
||||
} else {
|
||||
stack.push(big.NewInt(1))
|
||||
memory.Set(outOffset.Uint64(), outSize.Uint64(), ret)
|
||||
}
|
||||
}
|
||||
|
||||
func opReturn(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||
}
|
||||
func opStop(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||
|
@ -275,6 +275,11 @@ func CompileProgram(program *Program) (err error) {
|
||||
program.addInstr(op, pc, opGas, nil)
|
||||
case CREATE:
|
||||
program.addInstr(op, pc, opCreate, nil)
|
||||
case DELEGATECALL:
|
||||
// Instruction added regardless of homestead phase.
|
||||
// Homestead (and execution of the opcode) is checked during
|
||||
// runtime.
|
||||
program.addInstr(op, pc, opDelegateCall, nil)
|
||||
case CALL:
|
||||
program.addInstr(op, pc, opCall, nil)
|
||||
case CALLCODE:
|
||||
@ -317,10 +322,14 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
|
||||
}()
|
||||
}
|
||||
|
||||
homestead := params.IsHomestead(env.BlockNumber())
|
||||
for pc < uint64(len(program.instructions)) {
|
||||
instrCount++
|
||||
|
||||
instr := program.instructions[pc]
|
||||
if instr.Op() == DELEGATECALL && !homestead {
|
||||
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
|
||||
}
|
||||
|
||||
ret, err := instr.do(program, &pc, env, contract, mem, stack)
|
||||
if err != nil {
|
||||
@ -328,13 +337,13 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
|
||||
}
|
||||
|
||||
if instr.halts() {
|
||||
return contract.Return(ret), nil
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
contract.Input = nil
|
||||
|
||||
return contract.Return(nil), nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// validDest checks if the given distination is a valid one given the
|
||||
@ -457,7 +466,6 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
|
||||
gas.Add(gas, stack.data[stack.len()-1])
|
||||
|
||||
if op == CALL {
|
||||
//if env.Db().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
|
||||
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
@ -470,6 +478,13 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
|
||||
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
case DELEGATECALL:
|
||||
gas.Add(gas, stack.data[stack.len()-1])
|
||||
|
||||
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
|
||||
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
}
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
|
@ -125,14 +125,17 @@ type vmBench struct {
|
||||
|
||||
type account struct{}
|
||||
|
||||
func (account) SubBalance(amount *big.Int) {}
|
||||
func (account) AddBalance(amount *big.Int) {}
|
||||
func (account) SetBalance(*big.Int) {}
|
||||
func (account) SetNonce(uint64) {}
|
||||
func (account) Balance() *big.Int { return nil }
|
||||
func (account) Address() common.Address { return common.Address{} }
|
||||
func (account) ReturnGas(*big.Int, *big.Int) {}
|
||||
func (account) SetCode([]byte) {}
|
||||
func (account) SubBalance(amount *big.Int) {}
|
||||
func (account) AddBalance(amount *big.Int) {}
|
||||
func (account) SetAddress(common.Address) {}
|
||||
func (account) Value() *big.Int { return nil }
|
||||
func (account) SetBalance(*big.Int) {}
|
||||
func (account) SetNonce(uint64) {}
|
||||
func (account) Balance() *big.Int { return nil }
|
||||
func (account) Address() common.Address { return common.Address{} }
|
||||
func (account) ReturnGas(*big.Int, *big.Int) {}
|
||||
func (account) SetCode([]byte) {}
|
||||
func (account) EachStorage(cb func(key, value []byte)) {}
|
||||
|
||||
func runVmBench(test vmBench, b *testing.B) {
|
||||
var sender account
|
||||
@ -205,3 +208,6 @@ func (self *Env) CallCode(caller ContractRef, addr common.Address, data []byte,
|
||||
func (self *Env) Create(caller ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
|
||||
return nil, common.Address{}, nil
|
||||
}
|
||||
func (self *Env) DelegateCall(me ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -1,13 +1,29 @@
|
||||
package vm
|
||||
|
||||
import "math/big"
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
type jumpPtr struct {
|
||||
fn instrFn
|
||||
valid bool
|
||||
}
|
||||
|
||||
var jumpTable [256]jumpPtr
|
||||
type vmJumpTable [256]jumpPtr
|
||||
|
||||
func (jt vmJumpTable) init(blockNumber *big.Int) {
|
||||
// when initialising a new VM execution we must first check the homestead
|
||||
// changes.
|
||||
if params.IsHomestead(blockNumber) {
|
||||
jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
|
||||
} else {
|
||||
jumpTable[DELEGATECALL] = jumpPtr{nil, false}
|
||||
}
|
||||
}
|
||||
|
||||
var jumpTable vmJumpTable
|
||||
|
||||
func init() {
|
||||
jumpTable[ADD] = jumpPtr{opAdd, true}
|
||||
|
24
core/vm/jump_table_test.go
Normal file
24
core/vm/jump_table_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1)
|
||||
|
||||
jumpTable.init(big.NewInt(0))
|
||||
if jumpTable[DELEGATECALL].valid {
|
||||
t.Error("Expected DELEGATECALL not to be present")
|
||||
}
|
||||
|
||||
for _, n := range []int64{1, 2, 100} {
|
||||
jumpTable.init(big.NewInt(n))
|
||||
if !jumpTable[DELEGATECALL].valid {
|
||||
t.Error("Expected DELEGATECALL to be present for block", n)
|
||||
}
|
||||
}
|
||||
}
|
@ -200,6 +200,7 @@ const (
|
||||
CALL
|
||||
CALLCODE
|
||||
RETURN
|
||||
DELEGATECALL
|
||||
|
||||
SUICIDE = 0xff
|
||||
)
|
||||
@ -349,11 +350,12 @@ var opCodeToString = map[OpCode]string{
|
||||
LOG4: "LOG4",
|
||||
|
||||
// 0xf0 range
|
||||
CREATE: "CREATE",
|
||||
CALL: "CALL",
|
||||
RETURN: "RETURN",
|
||||
CALLCODE: "CALLCODE",
|
||||
SUICIDE: "SUICIDE",
|
||||
CREATE: "CREATE",
|
||||
CALL: "CALL",
|
||||
RETURN: "RETURN",
|
||||
CALLCODE: "CALLCODE",
|
||||
DELEGATECALL: "DELEGATECALL",
|
||||
SUICIDE: "SUICIDE",
|
||||
|
||||
PUSH: "PUSH",
|
||||
DUP: "DUP",
|
||||
@ -402,6 +404,7 @@ var stringToOp = map[string]OpCode{
|
||||
"CALLDATALOAD": CALLDATALOAD,
|
||||
"CALLDATASIZE": CALLDATASIZE,
|
||||
"CALLDATACOPY": CALLDATACOPY,
|
||||
"DELEGATECALL": DELEGATECALL,
|
||||
"CODESIZE": CODESIZE,
|
||||
"CODECOPY": CODECOPY,
|
||||
"GASPRICE": GASPRICE,
|
||||
|
@ -101,6 +101,10 @@ func (self *Env) CallCode(caller vm.ContractRef, addr common.Address, data []byt
|
||||
return core.CallCode(self, caller, addr, data, gas, price, value)
|
||||
}
|
||||
|
||||
func (self *Env) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
|
||||
return core.DelegateCall(self, me, addr, data, gas, price)
|
||||
}
|
||||
|
||||
func (self *Env) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
|
||||
return core.Create(self, caller, data, gas, price, value)
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ type Vm struct {
|
||||
|
||||
// New returns a new Vm
|
||||
func New(env Environment) *Vm {
|
||||
// init the jump table. Also prepares the homestead changes
|
||||
jumpTable.init(env.BlockNumber())
|
||||
|
||||
return &Vm{env: env}
|
||||
}
|
||||
|
||||
@ -43,16 +46,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
self.env.SetDepth(self.env.Depth() + 1)
|
||||
defer self.env.SetDepth(self.env.Depth() - 1)
|
||||
|
||||
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
|
||||
contract.UseGas(contract.Gas)
|
||||
|
||||
ret = contract.Return(nil)
|
||||
}
|
||||
}()
|
||||
|
||||
if contract.CodeAddr != nil {
|
||||
if p := Precompiled[contract.CodeAddr.Str()]; p != nil {
|
||||
return self.RunPrecompiled(p, input, contract)
|
||||
@ -61,7 +54,7 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
|
||||
// Don't bother with the execution if there's no code.
|
||||
if len(contract.Code) == 0 {
|
||||
return contract.Return(nil), nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
@ -160,7 +153,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
|
||||
// Get the memory location of pc
|
||||
op = contract.GetOp(pc)
|
||||
|
||||
// calculate the new memory size and gas price for the current executing opcode
|
||||
newMemSize, cost, err = calculateGasAndSize(self.env, contract, caller, op, statedb, mem, stack)
|
||||
if err != nil {
|
||||
@ -177,7 +169,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
mem.Resize(newMemSize.Uint64())
|
||||
// Add a log message
|
||||
self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil)
|
||||
|
||||
if opPtr := jumpTable[op]; opPtr.valid {
|
||||
if opPtr.fn != nil {
|
||||
opPtr.fn(instruction{}, &pc, self.env, contract, mem, stack)
|
||||
@ -205,13 +196,13 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
offset, size := stack.pop(), stack.pop()
|
||||
ret := mem.GetPtr(offset.Int64(), size.Int64())
|
||||
|
||||
return contract.Return(ret), nil
|
||||
return ret, nil
|
||||
case SUICIDE:
|
||||
opSuicide(instruction{}, nil, self.env, contract, mem, stack)
|
||||
|
||||
fallthrough
|
||||
case STOP: // Stop the contract
|
||||
return contract.Return(nil), nil
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -332,7 +323,6 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
|
||||
gas.Add(gas, stack.data[stack.len()-1])
|
||||
|
||||
if op == CALL {
|
||||
//if env.Db().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
|
||||
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
@ -345,6 +335,13 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
|
||||
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
case DELEGATECALL:
|
||||
gas.Add(gas, stack.data[stack.len()-1])
|
||||
|
||||
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
|
||||
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
}
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
@ -358,7 +355,7 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Co
|
||||
if contract.UseGas(gas) {
|
||||
ret = p.Call(input)
|
||||
|
||||
return contract.Return(ret), nil
|
||||
return ret, nil
|
||||
} else {
|
||||
return nil, OutOfGasError
|
||||
}
|
||||
|
@ -94,6 +94,10 @@ func (self *VMEnv) CallCode(me vm.ContractRef, addr common.Address, data []byte,
|
||||
return CallCode(self, me, addr, data, gas, price, value)
|
||||
}
|
||||
|
||||
func (self *VMEnv) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
|
||||
return DelegateCall(self, me, addr, data, gas, price)
|
||||
}
|
||||
|
||||
func (self *VMEnv) Create(me vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
|
||||
return Create(self, me, data, gas, price, value)
|
||||
}
|
||||
|
@ -171,12 +171,21 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
|
||||
return ecdsa.GenerateKey(S256(), rand.Reader)
|
||||
}
|
||||
|
||||
func ValidateSignatureValues(v byte, r, s *big.Int) bool {
|
||||
func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
|
||||
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
|
||||
return false
|
||||
}
|
||||
vint := uint32(v)
|
||||
if r.Cmp(secp256k1n) < 0 && s.Cmp(secp256k1n) < 0 && (vint == 27 || vint == 28) {
|
||||
// reject upper range of s values (ECDSA malleability)
|
||||
// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
|
||||
if homestead && s.Cmp(secp256k1.HalfN) > 0 {
|
||||
return false
|
||||
}
|
||||
// Frontier: allow s to be in full N range
|
||||
if s.Cmp(secp256k1.N) >= 0 {
|
||||
return false
|
||||
}
|
||||
if r.Cmp(secp256k1.N) < 0 && (vint == 27 || vint == 28) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
@ -174,7 +174,7 @@ func TestLoadECDSAFile(t *testing.T) {
|
||||
|
||||
func TestValidateSignatureValues(t *testing.T) {
|
||||
check := func(expected bool, v byte, r, s *big.Int) {
|
||||
if ValidateSignatureValues(v, r, s) != expected {
|
||||
if ValidateSignatureValues(v, r, s, false) != expected {
|
||||
t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected)
|
||||
}
|
||||
}
|
||||
|
@ -191,11 +191,9 @@ func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
|
||||
// messageTag computes the MAC of a message (called the tag) as per
|
||||
// SEC 1, 3.5.
|
||||
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
|
||||
if shared == nil {
|
||||
shared = make([]byte, 0)
|
||||
}
|
||||
mac := hmac.New(hash, km)
|
||||
mac.Write(msg)
|
||||
mac.Write(shared)
|
||||
tag := mac.Sum(nil)
|
||||
return tag
|
||||
}
|
||||
@ -242,9 +240,11 @@ func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte,
|
||||
return
|
||||
}
|
||||
|
||||
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
|
||||
// the shared information parameters aren't being used, they should be
|
||||
// nil.
|
||||
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1.
|
||||
//
|
||||
// s1 and s2 contain shared information that is not part of the resulting
|
||||
// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the
|
||||
// shared information parameters aren't being used, they should be nil.
|
||||
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
|
||||
params := pub.Params
|
||||
if params == nil {
|
||||
|
@ -353,6 +353,36 @@ func TestEncryptDecrypt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptShared2(t *testing.T) {
|
||||
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
message := []byte("Hello, world.")
|
||||
shared2 := []byte("shared data 2")
|
||||
ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Check that decrypting with correct shared data works.
|
||||
pt, err := prv.Decrypt(rand.Reader, ct, nil, shared2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(pt, message) {
|
||||
t.Fatal("ecies: plaintext doesn't match message")
|
||||
}
|
||||
|
||||
// Decrypting without shared data or incorrect shared data fails.
|
||||
if _, err = prv.Decrypt(rand.Reader, ct, nil, nil); err == nil {
|
||||
t.Fatal("ecies: decrypting without shared data didn't fail")
|
||||
}
|
||||
if _, err = prv.Decrypt(rand.Reader, ct, nil, []byte("garbage")); err == nil {
|
||||
t.Fatal("ecies: decrypting with incorrect shared data didn't fail")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMarshalEncryption validates the encode/decode produces a valid
|
||||
// ECIES encryption key.
|
||||
func TestMarshalEncryption(t *testing.T) {
|
||||
|
@ -1,25 +0,0 @@
|
||||
secp256k1-go
|
||||
=======
|
||||
|
||||
golang secp256k1 library
|
||||
|
||||
Implements cryptographic operations for the secp256k1 ECDSA curve used by Bitcoin.
|
||||
|
||||
Installing
|
||||
===
|
||||
|
||||
GMP library headers are required to build. On Debian-based systems, the package is called `libgmp-dev`.
|
||||
|
||||
```
|
||||
sudo apt-get install libgmp-dev
|
||||
```
|
||||
|
||||
Now compiles with cgo!
|
||||
|
||||
Test
|
||||
===
|
||||
|
||||
To run tests do
|
||||
```
|
||||
go tests
|
||||
```
|
@ -20,14 +20,8 @@ package secp256k1
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -I./libsecp256k1
|
||||
#cgo darwin CFLAGS: -I/usr/local/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/include
|
||||
#cgo linux,arm CFLAGS: -I/usr/local/arm/include
|
||||
#cgo LDFLAGS: -lgmp
|
||||
#cgo darwin LDFLAGS: -L/usr/local/lib
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/lib
|
||||
#cgo linux,arm LDFLAGS: -L/usr/local/arm/lib
|
||||
#define USE_NUM_GMP
|
||||
#cgo CFLAGS: -I./libsecp256k1/src/
|
||||
#define USE_NUM_NONE
|
||||
#define USE_FIELD_10X26
|
||||
#define USE_FIELD_INV_BUILTIN
|
||||
#define USE_SCALAR_8X32
|
||||
@ -44,6 +38,7 @@ import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
||||
@ -60,9 +55,17 @@ import (
|
||||
*/
|
||||
|
||||
// holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
|
||||
var context *C.secp256k1_context
|
||||
var (
|
||||
context *C.secp256k1_context
|
||||
N *big.Int
|
||||
HalfN *big.Int
|
||||
)
|
||||
|
||||
func init() {
|
||||
N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
|
||||
// N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168
|
||||
HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16)
|
||||
|
||||
// around 20 ms on a modern CPU.
|
||||
context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
|
||||
C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
|
||||
|
@ -112,20 +112,20 @@ type Downloader struct {
|
||||
syncStatsLock sync.RWMutex // Lock protecting the sync stats fields
|
||||
|
||||
// Callbacks
|
||||
hasHeader headerCheckFn // Checks if a header is present in the chain
|
||||
hasBlock blockCheckFn // Checks if a block is present in the chain
|
||||
getHeader headerRetrievalFn // Retrieves a header from the chain
|
||||
getBlock blockRetrievalFn // Retrieves a block from the chain
|
||||
headHeader headHeaderRetrievalFn // Retrieves the head header from the chain
|
||||
headBlock headBlockRetrievalFn // Retrieves the head block from the chain
|
||||
headFastBlock headFastBlockRetrievalFn // Retrieves the head fast-sync block from the chain
|
||||
commitHeadBlock headBlockCommitterFn // Commits a manually assembled block as the chain head
|
||||
getTd tdRetrievalFn // Retrieves the TD of a block from the chain
|
||||
insertHeaders headerChainInsertFn // Injects a batch of headers into the chain
|
||||
insertBlocks blockChainInsertFn // Injects a batch of blocks into the chain
|
||||
insertReceipts receiptChainInsertFn // Injects a batch of blocks and their receipts into the chain
|
||||
rollback chainRollbackFn // Removes a batch of recently added chain links
|
||||
dropPeer peerDropFn // Drops a peer for misbehaving
|
||||
hasHeader headerCheckFn // Checks if a header is present in the chain
|
||||
hasBlockAndState blockAndStateCheckFn // Checks if a block and associated state is present in the chain
|
||||
getHeader headerRetrievalFn // Retrieves a header from the chain
|
||||
getBlock blockRetrievalFn // Retrieves a block from the chain
|
||||
headHeader headHeaderRetrievalFn // Retrieves the head header from the chain
|
||||
headBlock headBlockRetrievalFn // Retrieves the head block from the chain
|
||||
headFastBlock headFastBlockRetrievalFn // Retrieves the head fast-sync block from the chain
|
||||
commitHeadBlock headBlockCommitterFn // Commits a manually assembled block as the chain head
|
||||
getTd tdRetrievalFn // Retrieves the TD of a block from the chain
|
||||
insertHeaders headerChainInsertFn // Injects a batch of headers into the chain
|
||||
insertBlocks blockChainInsertFn // Injects a batch of blocks into the chain
|
||||
insertReceipts receiptChainInsertFn // Injects a batch of blocks and their receipts into the chain
|
||||
rollback chainRollbackFn // Removes a batch of recently added chain links
|
||||
dropPeer peerDropFn // Drops a peer for misbehaving
|
||||
|
||||
// Status
|
||||
synchroniseMock func(id string, hash common.Hash) error // Replacement for synchronise during testing
|
||||
@ -156,41 +156,41 @@ type Downloader struct {
|
||||
}
|
||||
|
||||
// New creates a new downloader to fetch hashes and blocks from remote peers.
|
||||
func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, hasBlock blockCheckFn, getHeader headerRetrievalFn,
|
||||
getBlock blockRetrievalFn, headHeader headHeaderRetrievalFn, headBlock headBlockRetrievalFn, headFastBlock headFastBlockRetrievalFn,
|
||||
commitHeadBlock headBlockCommitterFn, getTd tdRetrievalFn, insertHeaders headerChainInsertFn, insertBlocks blockChainInsertFn,
|
||||
insertReceipts receiptChainInsertFn, rollback chainRollbackFn, dropPeer peerDropFn) *Downloader {
|
||||
func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, hasBlockAndState blockAndStateCheckFn,
|
||||
getHeader headerRetrievalFn, getBlock blockRetrievalFn, headHeader headHeaderRetrievalFn, headBlock headBlockRetrievalFn,
|
||||
headFastBlock headFastBlockRetrievalFn, commitHeadBlock headBlockCommitterFn, getTd tdRetrievalFn, insertHeaders headerChainInsertFn,
|
||||
insertBlocks blockChainInsertFn, insertReceipts receiptChainInsertFn, rollback chainRollbackFn, dropPeer peerDropFn) *Downloader {
|
||||
|
||||
return &Downloader{
|
||||
mode: FullSync,
|
||||
mux: mux,
|
||||
queue: newQueue(stateDb),
|
||||
peers: newPeerSet(),
|
||||
hasHeader: hasHeader,
|
||||
hasBlock: hasBlock,
|
||||
getHeader: getHeader,
|
||||
getBlock: getBlock,
|
||||
headHeader: headHeader,
|
||||
headBlock: headBlock,
|
||||
headFastBlock: headFastBlock,
|
||||
commitHeadBlock: commitHeadBlock,
|
||||
getTd: getTd,
|
||||
insertHeaders: insertHeaders,
|
||||
insertBlocks: insertBlocks,
|
||||
insertReceipts: insertReceipts,
|
||||
rollback: rollback,
|
||||
dropPeer: dropPeer,
|
||||
newPeerCh: make(chan *peer, 1),
|
||||
hashCh: make(chan dataPack, 1),
|
||||
blockCh: make(chan dataPack, 1),
|
||||
headerCh: make(chan dataPack, 1),
|
||||
bodyCh: make(chan dataPack, 1),
|
||||
receiptCh: make(chan dataPack, 1),
|
||||
stateCh: make(chan dataPack, 1),
|
||||
blockWakeCh: make(chan bool, 1),
|
||||
bodyWakeCh: make(chan bool, 1),
|
||||
receiptWakeCh: make(chan bool, 1),
|
||||
stateWakeCh: make(chan bool, 1),
|
||||
mode: FullSync,
|
||||
mux: mux,
|
||||
queue: newQueue(stateDb),
|
||||
peers: newPeerSet(),
|
||||
hasHeader: hasHeader,
|
||||
hasBlockAndState: hasBlockAndState,
|
||||
getHeader: getHeader,
|
||||
getBlock: getBlock,
|
||||
headHeader: headHeader,
|
||||
headBlock: headBlock,
|
||||
headFastBlock: headFastBlock,
|
||||
commitHeadBlock: commitHeadBlock,
|
||||
getTd: getTd,
|
||||
insertHeaders: insertHeaders,
|
||||
insertBlocks: insertBlocks,
|
||||
insertReceipts: insertReceipts,
|
||||
rollback: rollback,
|
||||
dropPeer: dropPeer,
|
||||
newPeerCh: make(chan *peer, 1),
|
||||
hashCh: make(chan dataPack, 1),
|
||||
blockCh: make(chan dataPack, 1),
|
||||
headerCh: make(chan dataPack, 1),
|
||||
bodyCh: make(chan dataPack, 1),
|
||||
receiptCh: make(chan dataPack, 1),
|
||||
stateCh: make(chan dataPack, 1),
|
||||
blockWakeCh: make(chan bool, 1),
|
||||
bodyWakeCh: make(chan bool, 1),
|
||||
receiptWakeCh: make(chan bool, 1),
|
||||
stateWakeCh: make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,7 +564,7 @@ func (d *Downloader) findAncestor61(p *peer) (uint64, error) {
|
||||
// Check if a common ancestor was found
|
||||
finished = true
|
||||
for i := len(hashes) - 1; i >= 0; i-- {
|
||||
if d.hasBlock(hashes[i]) {
|
||||
if d.hasBlockAndState(hashes[i]) {
|
||||
number, hash = uint64(from)+uint64(i), hashes[i]
|
||||
break
|
||||
}
|
||||
@ -620,11 +620,11 @@ func (d *Downloader) findAncestor61(p *peer) (uint64, error) {
|
||||
arrived = true
|
||||
|
||||
// Modify the search interval based on the response
|
||||
block := d.getBlock(hashes[0])
|
||||
if block == nil {
|
||||
if !d.hasBlockAndState(hashes[0]) {
|
||||
end = check
|
||||
break
|
||||
}
|
||||
block := d.getBlock(hashes[0]) // this doesn't check state, hence the above explicit check
|
||||
if block.NumberU64() != check {
|
||||
glog.V(logger.Debug).Infof("%v: non requested hash #%d [%x…], instead of #%d", p, block.NumberU64(), block.Hash().Bytes()[:4], check)
|
||||
return 0, errBadPeer
|
||||
@ -989,7 +989,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
|
||||
// Check if a common ancestor was found
|
||||
finished = true
|
||||
for i := len(headers) - 1; i >= 0; i-- {
|
||||
if (d.mode != LightSync && d.hasBlock(headers[i].Hash())) || (d.mode == LightSync && d.hasHeader(headers[i].Hash())) {
|
||||
if (d.mode != LightSync && d.hasBlockAndState(headers[i].Hash())) || (d.mode == LightSync && d.hasHeader(headers[i].Hash())) {
|
||||
number, hash = headers[i].Number.Uint64(), headers[i].Hash()
|
||||
break
|
||||
}
|
||||
@ -1045,7 +1045,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
|
||||
arrived = true
|
||||
|
||||
// Modify the search interval based on the response
|
||||
if (d.mode == FullSync && !d.hasBlock(headers[0].Hash())) || (d.mode != FullSync && !d.hasHeader(headers[0].Hash())) {
|
||||
if (d.mode == FullSync && !d.hasBlockAndState(headers[0].Hash())) || (d.mode != FullSync && !d.hasHeader(headers[0].Hash())) {
|
||||
end = check
|
||||
break
|
||||
}
|
||||
@ -1216,7 +1216,7 @@ func (d *Downloader) fetchHeaders(p *peer, td *big.Int, from uint64) error {
|
||||
}
|
||||
}
|
||||
// Notify the content fetchers of new headers, but stop if queue is full
|
||||
cont := d.queue.PendingBlocks() < maxQueuedHeaders || d.queue.PendingReceipts() < maxQueuedHeaders
|
||||
cont := d.queue.PendingBlocks() < maxQueuedHeaders && d.queue.PendingReceipts() < maxQueuedHeaders
|
||||
for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh, d.stateWakeCh} {
|
||||
if cont {
|
||||
// We still have headers to fetch, send continuation wake signal (potential)
|
||||
@ -1230,9 +1230,11 @@ func (d *Downloader) fetchHeaders(p *peer, td *big.Int, from uint64) error {
|
||||
case ch <- false:
|
||||
case <-d.cancelCh:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if !cont {
|
||||
return nil
|
||||
}
|
||||
// Queue not yet full, fetch the next batch
|
||||
from += uint64(len(headers))
|
||||
getHeaders(from)
|
||||
|
@ -150,6 +150,8 @@ func newTester() *downloadTester {
|
||||
peerChainTds: make(map[string]map[common.Hash]*big.Int),
|
||||
}
|
||||
tester.stateDb, _ = ethdb.NewMemDatabase()
|
||||
tester.stateDb.Put(genesis.Root().Bytes(), []byte{0x00})
|
||||
|
||||
tester.downloader = New(tester.stateDb, new(event.TypeMux), tester.hasHeader, tester.hasBlock, tester.getHeader,
|
||||
tester.getBlock, tester.headHeader, tester.headBlock, tester.headFastBlock, tester.commitHeadBlock, tester.getTd,
|
||||
tester.insertHeaders, tester.insertBlocks, tester.insertReceipts, tester.rollback, tester.dropPeer)
|
||||
@ -177,9 +179,14 @@ func (dl *downloadTester) hasHeader(hash common.Hash) bool {
|
||||
return dl.getHeader(hash) != nil
|
||||
}
|
||||
|
||||
// hasBlock checks if a block is present in the testers canonical chain.
|
||||
// hasBlock checks if a block and associated state is present in the testers canonical chain.
|
||||
func (dl *downloadTester) hasBlock(hash common.Hash) bool {
|
||||
return dl.getBlock(hash) != nil
|
||||
block := dl.getBlock(hash)
|
||||
if block == nil {
|
||||
return false
|
||||
}
|
||||
_, err := dl.stateDb.Get(block.Root().Bytes())
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// getHeader retrieves a header from the testers canonical chain.
|
||||
@ -292,8 +299,10 @@ func (dl *downloadTester) insertBlocks(blocks types.Blocks) (int, error) {
|
||||
defer dl.lock.Unlock()
|
||||
|
||||
for i, block := range blocks {
|
||||
if _, ok := dl.ownBlocks[block.ParentHash()]; !ok {
|
||||
if parent, ok := dl.ownBlocks[block.ParentHash()]; !ok {
|
||||
return i, errors.New("unknown parent")
|
||||
} else if _, err := dl.stateDb.Get(parent.Root().Bytes()); err != nil {
|
||||
return i, fmt.Errorf("unknown parent state %x: %v", parent.Root(), err)
|
||||
}
|
||||
if _, ok := dl.ownHeaders[block.Hash()]; !ok {
|
||||
dl.ownHashes = append(dl.ownHashes, block.Hash())
|
||||
@ -1102,6 +1111,8 @@ func testShiftedHeaderAttack(t *testing.T, protocol int, mode SyncMode) {
|
||||
}
|
||||
|
||||
// Tests that upon detecting an invalid header, the recent ones are rolled back
|
||||
// for various failure scenarios. Afterwards a full sync is attempted to make
|
||||
// sure no state was corrupted.
|
||||
func TestInvalidHeaderRollback63Fast(t *testing.T) { testInvalidHeaderRollback(t, 63, FastSync) }
|
||||
func TestInvalidHeaderRollback64Fast(t *testing.T) { testInvalidHeaderRollback(t, 64, FastSync) }
|
||||
func TestInvalidHeaderRollback64Light(t *testing.T) { testInvalidHeaderRollback(t, 64, LightSync) }
|
||||
|
@ -27,8 +27,8 @@ import (
|
||||
// headerCheckFn is a callback type for verifying a header's presence in the local chain.
|
||||
type headerCheckFn func(common.Hash) bool
|
||||
|
||||
// blockCheckFn is a callback type for verifying a block's presence in the local chain.
|
||||
type blockCheckFn func(common.Hash) bool
|
||||
// blockAndStateCheckFn is a callback type for verifying block and associated states' presence in the local chain.
|
||||
type blockAndStateCheckFn func(common.Hash) bool
|
||||
|
||||
// headerRetrievalFn is a callback type for retrieving a header from the local chain.
|
||||
type headerRetrievalFn func(common.Hash) *types.Header
|
||||
|
@ -138,9 +138,10 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
|
||||
return nil, errIncompatibleConfig
|
||||
}
|
||||
// Construct the different synchronisation mechanisms
|
||||
manager.downloader = downloader.New(chaindb, manager.eventMux, blockchain.HasHeader, blockchain.HasBlock, blockchain.GetHeader, blockchain.GetBlock,
|
||||
blockchain.CurrentHeader, blockchain.CurrentBlock, blockchain.CurrentFastBlock, blockchain.FastSyncCommitHead, blockchain.GetTd,
|
||||
blockchain.InsertHeaderChain, blockchain.InsertChain, blockchain.InsertReceiptChain, blockchain.Rollback, manager.removePeer)
|
||||
manager.downloader = downloader.New(chaindb, manager.eventMux, blockchain.HasHeader, blockchain.HasBlockAndState, blockchain.GetHeader,
|
||||
blockchain.GetBlock, blockchain.CurrentHeader, blockchain.CurrentBlock, blockchain.CurrentFastBlock, blockchain.FastSyncCommitHead,
|
||||
blockchain.GetTd, blockchain.InsertHeaderChain, blockchain.InsertChain, blockchain.InsertReceiptChain, blockchain.Rollback,
|
||||
manager.removePeer)
|
||||
|
||||
validator := func(block *types.Block, parent *types.Block) error {
|
||||
return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false)
|
||||
@ -490,7 +491,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||
uncles[i] = body.Uncles
|
||||
}
|
||||
// Filter out any explicitly requested bodies, deliver the rest to the downloader
|
||||
if trasactions, uncles := pm.fetcher.FilterBodies(trasactions, uncles, time.Now()); len(trasactions) > 0 || len(uncles) > 0 {
|
||||
filter := len(trasactions) > 0 || len(uncles) > 0
|
||||
if filter {
|
||||
trasactions, uncles = pm.fetcher.FilterBodies(trasactions, uncles, time.Now())
|
||||
}
|
||||
if len(trasactions) > 0 || len(uncles) > 0 || !filter {
|
||||
err := pm.downloader.DeliverBodies(p.id, trasactions, uncles)
|
||||
if err != nil {
|
||||
glog.V(logger.Debug).Infoln(err)
|
||||
|
@ -19,7 +19,6 @@ package miner
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@ -495,12 +494,12 @@ func (self *worker) commitNewWork() {
|
||||
|
||||
/* //approach 1
|
||||
transactions := self.eth.TxPool().GetTransactions()
|
||||
sort.Sort(types.TxByNonce{transactions})
|
||||
sort.Sort(types.TxByNonce(transactions))
|
||||
*/
|
||||
|
||||
//approach 2
|
||||
transactions := self.eth.TxPool().GetTransactions()
|
||||
sort.Sort(types.TxByPriceAndNonce{transactions})
|
||||
types.SortByPriceAndNonce(transactions)
|
||||
|
||||
/* // approach 3
|
||||
// commit transactions for this run.
|
||||
@ -524,8 +523,8 @@ func (self *worker) commitNewWork() {
|
||||
multiTxOwner = append(multiTxOwner, txs...)
|
||||
}
|
||||
}
|
||||
sort.Sort(types.TxByPrice{singleTxOwner})
|
||||
sort.Sort(types.TxByNonce{multiTxOwner})
|
||||
sort.Sort(types.TxByPrice(singleTxOwner))
|
||||
sort.Sort(types.TxByNonce(multiTxOwner))
|
||||
transactions := append(singleTxOwner, multiTxOwner...)
|
||||
*/
|
||||
|
||||
@ -591,7 +590,8 @@ func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
|
||||
func (env *Work) commitTransactions(transactions types.Transactions, gasPrice *big.Int, bc *core.BlockChain) {
|
||||
gp := new(core.GasPool).AddGas(env.header.GasLimit)
|
||||
for _, tx := range transactions {
|
||||
// We can skip err. It has already been validated in the tx pool
|
||||
// Error may be ignored here. The error has already been checked
|
||||
// during transaction acceptance is the transaction pool.
|
||||
from, _ := tx.From()
|
||||
|
||||
// Check if it falls within margin. Txs from owned accounts are always processed.
|
||||
|
@ -67,6 +67,8 @@ type (
|
||||
Version uint
|
||||
From, To rpcEndpoint
|
||||
Expiration uint64
|
||||
// Ignore additional fields (for forward compatibility).
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
// pong is the reply to ping.
|
||||
@ -78,18 +80,24 @@ type (
|
||||
|
||||
ReplyTok []byte // This contains the hash of the ping packet.
|
||||
Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
|
||||
// Ignore additional fields (for forward compatibility).
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
// findnode is a query for nodes close to the given target.
|
||||
findnode struct {
|
||||
Target NodeID // doesn't need to be an actual public key
|
||||
Expiration uint64
|
||||
// Ignore additional fields (for forward compatibility).
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
// reply to findnode
|
||||
neighbors struct {
|
||||
Nodes []rpcNode
|
||||
Expiration uint64
|
||||
// Ignore additional fields (for forward compatibility).
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
rpcNode struct {
|
||||
@ -447,8 +455,11 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte,
|
||||
return packet, nil
|
||||
}
|
||||
|
||||
type tempError interface {
|
||||
Temporary() bool
|
||||
func isTemporaryError(err error) bool {
|
||||
tempErr, ok := err.(interface {
|
||||
Temporary() bool
|
||||
})
|
||||
return ok && tempErr.Temporary() || isPacketTooBig(err)
|
||||
}
|
||||
|
||||
// readLoop runs in its own goroutine. it handles incoming UDP packets.
|
||||
@ -460,7 +471,7 @@ func (t *udp) readLoop() {
|
||||
buf := make([]byte, 1280)
|
||||
for {
|
||||
nbytes, from, err := t.conn.ReadFromUDP(buf)
|
||||
if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
|
||||
if isTemporaryError(err) {
|
||||
// Ignore temporary read errors.
|
||||
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
|
||||
continue
|
||||
@ -513,7 +524,8 @@ func decodePacket(buf []byte) (packet, NodeID, []byte, error) {
|
||||
default:
|
||||
return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype)
|
||||
}
|
||||
err = rlp.DecodeBytes(sigdata[1:], req)
|
||||
s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0)
|
||||
err = s.Decode(req)
|
||||
return req, fromID, hash, err
|
||||
}
|
||||
|
||||
|
26
p2p/discover/udp_notwindows.go
Normal file
26
p2p/discover/udp_notwindows.go
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//+build !windows
|
||||
|
||||
package discover
|
||||
|
||||
// reports whether err indicates that a UDP packet didn't
|
||||
// fit the receive buffer. There is no such error on
|
||||
// non-Windows platforms.
|
||||
func isPacketTooBig(err error) bool {
|
||||
return false
|
||||
}
|
@ -20,13 +20,12 @@ import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
logpkg "log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
@ -34,12 +33,64 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel))
|
||||
spew.Config.DisableMethods = true
|
||||
}
|
||||
|
||||
// This test checks that isPacketTooBig correctly identifies
|
||||
// errors that result from receiving a UDP packet larger
|
||||
// than the supplied receive buffer.
|
||||
func TestIsPacketTooBig(t *testing.T) {
|
||||
listener, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
sender, err := net.Dial("udp", listener.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer sender.Close()
|
||||
|
||||
sendN := 1800
|
||||
recvN := 300
|
||||
for i := 0; i < 20; i++ {
|
||||
go func() {
|
||||
buf := make([]byte, sendN)
|
||||
for i := range buf {
|
||||
buf[i] = byte(i)
|
||||
}
|
||||
sender.Write(buf)
|
||||
}()
|
||||
|
||||
buf := make([]byte, recvN)
|
||||
listener.SetDeadline(time.Now().Add(1 * time.Second))
|
||||
n, _, err := listener.ReadFrom(buf)
|
||||
if err != nil {
|
||||
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
|
||||
continue
|
||||
}
|
||||
if !isPacketTooBig(err) {
|
||||
t.Fatal("unexpected read error:", spew.Sdump(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if n != recvN {
|
||||
t.Fatalf("short read: %d, want %d", n, recvN)
|
||||
}
|
||||
for i := range buf {
|
||||
if buf[i] != byte(i) {
|
||||
t.Fatalf("error in pattern")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shared test variables
|
||||
@ -385,6 +436,115 @@ func TestUDP_successfulPing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
var testPackets = []struct {
|
||||
input string
|
||||
wantPacket interface{}
|
||||
}{
|
||||
{
|
||||
input: "71dbda3a79554728d4f94411e42ee1f8b0d561c10e1e5f5893367948c6a7d70bb87b235fa28a77070271b6c164a2dce8c7e13a5739b53b5e96f2e5acb0e458a02902f5965d55ecbeb2ebb6cabb8b2b232896a36b737666c55265ad0a68412f250001ea04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a355",
|
||||
wantPacket: &ping{
|
||||
Version: 4,
|
||||
From: rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
|
||||
To: rpcEndpoint{net.ParseIP("::1"), 2222, 3333},
|
||||
Expiration: 1136239445,
|
||||
Rest: []rlp.RawValue{},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663aaa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a3550102",
|
||||
wantPacket: &ping{
|
||||
Version: 4,
|
||||
From: rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
|
||||
To: rpcEndpoint{net.ParseIP("::1"), 2222, 3333},
|
||||
Expiration: 1136239445,
|
||||
Rest: []rlp.RawValue{{0x01}, {0x02}},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3",
|
||||
wantPacket: &ping{
|
||||
Version: 555,
|
||||
From: rpcEndpoint{net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 3322, 5544},
|
||||
To: rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
|
||||
Expiration: 1136239445,
|
||||
Rest: []rlp.RawValue{{0xC5, 0x01, 0x02, 0x03, 0x04, 0x05}},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b2069869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e",
|
||||
wantPacket: &pong{
|
||||
To: rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
|
||||
ReplyTok: common.Hex2Bytes("fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954"),
|
||||
Expiration: 1136239445,
|
||||
Rest: []rlp.RawValue{{0xC6, 0x01, 0x02, 0x03, 0xC2, 0x04, 0x05}, {0x06}},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396",
|
||||
wantPacket: &findnode{
|
||||
Target: MustHexID("ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f"),
|
||||
Expiration: 1136239445,
|
||||
Rest: []rlp.RawValue{{0x82, 0x99, 0x99}, {0x83, 0x99, 0x99, 0x99}},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df738443b9a355010203b525a138aa34383fec3d2719a0",
|
||||
wantPacket: &neighbors{
|
||||
Nodes: []rpcNode{
|
||||
{
|
||||
ID: MustHexID("3155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32"),
|
||||
IP: net.ParseIP("99.33.22.55").To4(),
|
||||
UDP: 4444,
|
||||
TCP: 4445,
|
||||
},
|
||||
{
|
||||
ID: MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069db"),
|
||||
IP: net.ParseIP("1.2.3.4").To4(),
|
||||
UDP: 1,
|
||||
TCP: 1,
|
||||
},
|
||||
{
|
||||
ID: MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aac"),
|
||||
IP: net.ParseIP("2001:db8:3c4d:15::abcd:ef12"),
|
||||
UDP: 3333,
|
||||
TCP: 3333,
|
||||
},
|
||||
{
|
||||
ID: MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73"),
|
||||
IP: net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"),
|
||||
UDP: 999,
|
||||
TCP: 1000,
|
||||
},
|
||||
},
|
||||
Expiration: 1136239445,
|
||||
Rest: []rlp.RawValue{{0x01}, {0x02}, {0x03}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestForwardCompatibility(t *testing.T) {
|
||||
testkey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
wantNodeID := PubkeyID(&testkey.PublicKey)
|
||||
|
||||
for _, test := range testPackets {
|
||||
input, err := hex.DecodeString(test.input)
|
||||
if err != nil {
|
||||
t.Fatalf("invalid hex: %s", test.input)
|
||||
}
|
||||
packet, nodeid, _, err := decodePacket(input)
|
||||
if err != nil {
|
||||
t.Errorf("did not accept packet %s\n%v", test.input, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(packet, test.wantPacket) {
|
||||
t.Errorf("got %s\nwant %s", spew.Sdump(packet), spew.Sdump(test.wantPacket))
|
||||
}
|
||||
if nodeid != wantNodeID {
|
||||
t.Errorf("got id %v\nwant id %v", nodeid, wantNodeID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dgramPipe is a fake UDP socket. It queues all sent datagrams.
|
||||
type dgramPipe struct {
|
||||
mu *sync.Mutex
|
||||
|
40
p2p/discover/udp_windows.go
Normal file
40
p2p/discover/udp_windows.go
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2016 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//+build windows
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const _WSAEMSGSIZE = syscall.Errno(10040)
|
||||
|
||||
// reports whether err indicates that a UDP packet didn't
|
||||
// fit the receive buffer. On Windows, WSARecvFrom returns
|
||||
// code WSAEMSGSIZE and no data if this happens.
|
||||
func isPacketTooBig(err error) bool {
|
||||
if opErr, ok := err.(*net.OpError); ok {
|
||||
if scErr, ok := opErr.Err.(*os.SyscallError); ok {
|
||||
return scErr.Err == _WSAEMSGSIZE
|
||||
}
|
||||
return opErr.Err == _WSAEMSGSIZE
|
||||
}
|
||||
return false
|
||||
}
|
@ -143,7 +143,8 @@ func TestEOFSignal(t *testing.T) {
|
||||
}
|
||||
|
||||
func unhex(str string) []byte {
|
||||
b, err := hex.DecodeString(strings.Replace(str, "\n", "", -1))
|
||||
r := strings.NewReplacer("\t", "", " ", "", "\n", "")
|
||||
b, err := hex.DecodeString(r.Replace(str))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid hex string: %q", str))
|
||||
}
|
||||
|
@ -56,6 +56,9 @@ type protoHandshake struct {
|
||||
Caps []Cap
|
||||
ListenPort uint64
|
||||
ID discover.NodeID
|
||||
|
||||
// Ignore additional fields (for forward compatibility).
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
// Peer represents a connected remote node.
|
||||
|
363
p2p/rlpx.go
363
p2p/rlpx.go
@ -24,11 +24,14 @@ import (
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
mrand "math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -51,9 +54,10 @@ const (
|
||||
authMsgLen = sigLen + shaLen + pubLen + shaLen + 1
|
||||
authRespLen = pubLen + shaLen + 1
|
||||
|
||||
eciesBytes = 65 + 16 + 32
|
||||
encAuthMsgLen = authMsgLen + eciesBytes // size of the final ECIES payload sent as initiator's handshake
|
||||
encAuthRespLen = authRespLen + eciesBytes // size of the final ECIES payload sent as receiver's handshake
|
||||
eciesOverhead = 65 /* pubkey */ + 16 /* IV */ + 32 /* MAC */
|
||||
|
||||
encAuthMsgLen = authMsgLen + eciesOverhead // size of encrypted pre-EIP-8 initiator handshake
|
||||
encAuthRespLen = authRespLen + eciesOverhead // size of encrypted pre-EIP-8 handshake reply
|
||||
|
||||
// total timeout for encryption handshake and protocol
|
||||
// handshake in both directions.
|
||||
@ -151,10 +155,6 @@ func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake,
|
||||
if err := msg.Decode(&hs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// validate handshake info
|
||||
if hs.Version != our.Version {
|
||||
return nil, DiscIncompatibleVersion
|
||||
}
|
||||
if (hs.ID == discover.NodeID{}) {
|
||||
return nil, DiscInvalidIdentity
|
||||
}
|
||||
@ -200,6 +200,29 @@ type secrets struct {
|
||||
Token []byte
|
||||
}
|
||||
|
||||
// RLPx v4 handshake auth (defined in EIP-8).
|
||||
type authMsgV4 struct {
|
||||
gotPlain bool // whether read packet had plain format.
|
||||
|
||||
Signature [sigLen]byte
|
||||
InitiatorPubkey [pubLen]byte
|
||||
Nonce [shaLen]byte
|
||||
Version uint
|
||||
|
||||
// Ignore additional fields (forward-compatibility)
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
// RLPx v4 handshake response (defined in EIP-8).
|
||||
type authRespV4 struct {
|
||||
RandomPubkey [pubLen]byte
|
||||
Nonce [shaLen]byte
|
||||
Version uint
|
||||
|
||||
// Ignore additional fields (forward-compatibility)
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
// secrets is called after the handshake is completed.
|
||||
// It extracts the connection secrets from the handshake values.
|
||||
func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
|
||||
@ -215,7 +238,6 @@ func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
|
||||
RemoteID: h.remoteID,
|
||||
AES: aesSecret,
|
||||
MAC: crypto.Sha3(ecdheSecret, aesSecret),
|
||||
Token: crypto.Sha3(sharedSecret),
|
||||
}
|
||||
|
||||
// setup sha3 instances for the MACs
|
||||
@ -234,114 +256,89 @@ func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (h *encHandshake) ecdhShared(prv *ecdsa.PrivateKey) ([]byte, error) {
|
||||
// staticSharedSecret returns the static shared secret, the result
|
||||
// of key agreement between the local and remote static node key.
|
||||
func (h *encHandshake) staticSharedSecret(prv *ecdsa.PrivateKey) ([]byte, error) {
|
||||
return ecies.ImportECDSA(prv).GenerateShared(h.remotePub, sskLen, sskLen)
|
||||
}
|
||||
|
||||
var configSendEIP = os.Getenv("RLPX_EIP8") != ""
|
||||
|
||||
// initiatorEncHandshake negotiates a session token on conn.
|
||||
// it should be called on the dialing side of the connection.
|
||||
//
|
||||
// prv is the local client's private key.
|
||||
// token is the token from a previous session with this node.
|
||||
func initiatorEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, remoteID discover.NodeID, token []byte) (s secrets, err error) {
|
||||
h, err := newInitiatorHandshake(remoteID)
|
||||
h := &encHandshake{initiator: true, remoteID: remoteID}
|
||||
authMsg, err := h.makeAuthMsg(prv, token)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
auth, err := h.authMsg(prv, token)
|
||||
var authPacket []byte
|
||||
if configSendEIP {
|
||||
authPacket, err = sealEIP8(authMsg, h)
|
||||
} else {
|
||||
authPacket, err = authMsg.sealPlain(h)
|
||||
}
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
if _, err = conn.Write(auth); err != nil {
|
||||
if _, err = conn.Write(authPacket); err != nil {
|
||||
return s, err
|
||||
}
|
||||
|
||||
response := make([]byte, encAuthRespLen)
|
||||
if _, err = io.ReadFull(conn, response); err != nil {
|
||||
authRespMsg := new(authRespV4)
|
||||
authRespPacket, err := readHandshakeMsg(authRespMsg, encAuthRespLen, prv, conn)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
if err := h.decodeAuthResp(response, prv); err != nil {
|
||||
if err := h.handleAuthResp(authRespMsg); err != nil {
|
||||
return s, err
|
||||
}
|
||||
return h.secrets(auth, response)
|
||||
return h.secrets(authPacket, authRespPacket)
|
||||
}
|
||||
|
||||
func newInitiatorHandshake(remoteID discover.NodeID) (*encHandshake, error) {
|
||||
rpub, err := remoteID.Pubkey()
|
||||
// makeAuthMsg creates the initiator handshake message.
|
||||
func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey, token []byte) (*authMsgV4, error) {
|
||||
rpub, err := h.remoteID.Pubkey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad remoteID: %v", err)
|
||||
}
|
||||
// generate random initiator nonce
|
||||
n := make([]byte, shaLen)
|
||||
if _, err := rand.Read(n); err != nil {
|
||||
h.remotePub = ecies.ImportECDSAPublic(rpub)
|
||||
// Generate random initiator nonce.
|
||||
h.initNonce = make([]byte, shaLen)
|
||||
if _, err := rand.Read(h.initNonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// generate random keypair to use for signing
|
||||
randpriv, err := ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||
// Generate random keypair to for ECDH.
|
||||
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h := &encHandshake{
|
||||
initiator: true,
|
||||
remoteID: remoteID,
|
||||
remotePub: ecies.ImportECDSAPublic(rpub),
|
||||
initNonce: n,
|
||||
randomPrivKey: randpriv,
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// authMsg creates an encrypted initiator handshake message.
|
||||
func (h *encHandshake) authMsg(prv *ecdsa.PrivateKey, token []byte) ([]byte, error) {
|
||||
var tokenFlag byte
|
||||
if token == nil {
|
||||
// no session token found means we need to generate shared secret.
|
||||
// ecies shared secret is used as initial session token for new peers
|
||||
// generate shared key from prv and remote pubkey
|
||||
var err error
|
||||
if token, err = h.ecdhShared(prv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// for known peers, we use stored token from the previous session
|
||||
tokenFlag = 0x01
|
||||
// Sign known message: static-shared-secret ^ nonce
|
||||
token, err = h.staticSharedSecret(prv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sign known message:
|
||||
// ecdh-shared-secret^nonce for new peers
|
||||
// token^nonce for old peers
|
||||
signed := xor(token, h.initNonce)
|
||||
signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// encode auth message
|
||||
// signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag
|
||||
msg := make([]byte, authMsgLen)
|
||||
n := copy(msg, signature)
|
||||
n += copy(msg[n:], crypto.Sha3(exportPubkey(&h.randomPrivKey.PublicKey)))
|
||||
n += copy(msg[n:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
|
||||
n += copy(msg[n:], h.initNonce)
|
||||
msg[n] = tokenFlag
|
||||
|
||||
// encrypt auth message using remote-pubk
|
||||
return ecies.Encrypt(rand.Reader, h.remotePub, msg, nil, nil)
|
||||
msg := new(authMsgV4)
|
||||
copy(msg.Signature[:], signature)
|
||||
copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
|
||||
copy(msg.Nonce[:], h.initNonce)
|
||||
msg.Version = 4
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// decodeAuthResp decode an encrypted authentication response message.
|
||||
func (h *encHandshake) decodeAuthResp(auth []byte, prv *ecdsa.PrivateKey) error {
|
||||
msg, err := crypto.Decrypt(prv, auth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not decrypt auth response (%v)", err)
|
||||
}
|
||||
h.respNonce = msg[pubLen : pubLen+shaLen]
|
||||
h.remoteRandomPub, err = importPublicKey(msg[:pubLen])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// ignore token flag for now
|
||||
return nil
|
||||
func (h *encHandshake) handleAuthResp(msg *authRespV4) (err error) {
|
||||
h.respNonce = msg.Nonce[:]
|
||||
h.remoteRandomPub, err = importPublicKey(msg.RandomPubkey[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// receiverEncHandshake negotiates a session token on conn.
|
||||
@ -350,99 +347,165 @@ func (h *encHandshake) decodeAuthResp(auth []byte, prv *ecdsa.PrivateKey) error
|
||||
// prv is the local client's private key.
|
||||
// token is the token from a previous session with this node.
|
||||
func receiverEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, token []byte) (s secrets, err error) {
|
||||
// read remote auth sent by initiator.
|
||||
auth := make([]byte, encAuthMsgLen)
|
||||
if _, err := io.ReadFull(conn, auth); err != nil {
|
||||
return s, err
|
||||
}
|
||||
h, err := decodeAuthMsg(prv, token, auth)
|
||||
authMsg := new(authMsgV4)
|
||||
authPacket, err := readHandshakeMsg(authMsg, encAuthMsgLen, prv, conn)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
h := new(encHandshake)
|
||||
if err := h.handleAuthMsg(authMsg, prv); err != nil {
|
||||
return s, err
|
||||
}
|
||||
|
||||
// send auth response
|
||||
resp, err := h.authResp(prv, token)
|
||||
authRespMsg, err := h.makeAuthResp()
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
if _, err = conn.Write(resp); err != nil {
|
||||
var authRespPacket []byte
|
||||
if authMsg.gotPlain {
|
||||
authRespPacket, err = authRespMsg.sealPlain(h)
|
||||
} else {
|
||||
authRespPacket, err = sealEIP8(authRespMsg, h)
|
||||
}
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
|
||||
return h.secrets(auth, resp)
|
||||
if _, err = conn.Write(authRespPacket); err != nil {
|
||||
return s, err
|
||||
}
|
||||
return h.secrets(authPacket, authRespPacket)
|
||||
}
|
||||
|
||||
func decodeAuthMsg(prv *ecdsa.PrivateKey, token []byte, auth []byte) (*encHandshake, error) {
|
||||
var err error
|
||||
h := new(encHandshake)
|
||||
// generate random keypair for session
|
||||
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||
func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error {
|
||||
// Import the remote identity.
|
||||
h.initNonce = msg.Nonce[:]
|
||||
h.remoteID = msg.InitiatorPubkey
|
||||
rpub, err := h.remoteID.Pubkey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return fmt.Errorf("bad remoteID: %#v", err)
|
||||
}
|
||||
// generate random nonce
|
||||
h.remotePub = ecies.ImportECDSAPublic(rpub)
|
||||
|
||||
// Generate random keypair for ECDH.
|
||||
// If a private key is already set, use it instead of generating one (for testing).
|
||||
if h.randomPrivKey == nil {
|
||||
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Check the signature.
|
||||
token, err := h.staticSharedSecret(prv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signedMsg := xor(token, h.initNonce)
|
||||
remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg.Signature[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *encHandshake) makeAuthResp() (msg *authRespV4, err error) {
|
||||
// Generate random nonce.
|
||||
h.respNonce = make([]byte, shaLen)
|
||||
if _, err = rand.Read(h.respNonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg, err := crypto.Decrypt(prv, auth)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not decrypt auth message (%v)", err)
|
||||
}
|
||||
|
||||
// decode message parameters
|
||||
// signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag
|
||||
h.initNonce = msg[authMsgLen-shaLen-1 : authMsgLen-1]
|
||||
copy(h.remoteID[:], msg[sigLen+shaLen:sigLen+shaLen+pubLen])
|
||||
rpub, err := h.remoteID.Pubkey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad remoteID: %#v", err)
|
||||
}
|
||||
h.remotePub = ecies.ImportECDSAPublic(rpub)
|
||||
|
||||
// recover remote random pubkey from signed message.
|
||||
if token == nil {
|
||||
// TODO: it is an error if the initiator has a token and we don't. check that.
|
||||
|
||||
// no session token means we need to generate shared secret.
|
||||
// ecies shared secret is used as initial session token for new peers.
|
||||
// generate shared key from prv and remote pubkey.
|
||||
if token, err = h.ecdhShared(prv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
signedMsg := xor(token, h.initNonce)
|
||||
remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg[:sigLen])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// validate the sha3 of recovered pubkey
|
||||
remoteRandomPubMAC := msg[sigLen : sigLen+shaLen]
|
||||
shaRemoteRandomPub := crypto.Sha3(remoteRandomPub[1:])
|
||||
if !bytes.Equal(remoteRandomPubMAC, shaRemoteRandomPub) {
|
||||
return nil, fmt.Errorf("sha3 of recovered ephemeral pubkey does not match checksum in auth message")
|
||||
}
|
||||
|
||||
h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
|
||||
return h, nil
|
||||
msg = new(authRespV4)
|
||||
copy(msg.Nonce[:], h.respNonce)
|
||||
copy(msg.RandomPubkey[:], exportPubkey(&h.randomPrivKey.PublicKey))
|
||||
msg.Version = 4
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// authResp generates the encrypted authentication response message.
|
||||
func (h *encHandshake) authResp(prv *ecdsa.PrivateKey, token []byte) ([]byte, error) {
|
||||
// responder auth message
|
||||
// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
|
||||
resp := make([]byte, authRespLen)
|
||||
n := copy(resp, exportPubkey(&h.randomPrivKey.PublicKey))
|
||||
n += copy(resp[n:], h.respNonce)
|
||||
if token == nil {
|
||||
resp[n] = 0
|
||||
} else {
|
||||
resp[n] = 1
|
||||
func (msg *authMsgV4) sealPlain(h *encHandshake) ([]byte, error) {
|
||||
buf := make([]byte, authMsgLen)
|
||||
n := copy(buf, msg.Signature[:])
|
||||
n += copy(buf[n:], crypto.Sha3(exportPubkey(&h.randomPrivKey.PublicKey)))
|
||||
n += copy(buf[n:], msg.InitiatorPubkey[:])
|
||||
n += copy(buf[n:], msg.Nonce[:])
|
||||
buf[n] = 0 // token-flag
|
||||
return ecies.Encrypt(rand.Reader, h.remotePub, buf, nil, nil)
|
||||
}
|
||||
|
||||
func (msg *authMsgV4) decodePlain(input []byte) {
|
||||
n := copy(msg.Signature[:], input)
|
||||
n += shaLen // skip sha3(initiator-ephemeral-pubk)
|
||||
n += copy(msg.InitiatorPubkey[:], input[n:])
|
||||
n += copy(msg.Nonce[:], input[n:])
|
||||
msg.Version = 4
|
||||
msg.gotPlain = true
|
||||
}
|
||||
|
||||
func (msg *authRespV4) sealPlain(hs *encHandshake) ([]byte, error) {
|
||||
buf := make([]byte, authRespLen)
|
||||
n := copy(buf, msg.RandomPubkey[:])
|
||||
n += copy(buf[n:], msg.Nonce[:])
|
||||
return ecies.Encrypt(rand.Reader, hs.remotePub, buf, nil, nil)
|
||||
}
|
||||
|
||||
func (msg *authRespV4) decodePlain(input []byte) {
|
||||
n := copy(msg.RandomPubkey[:], input)
|
||||
n += copy(msg.Nonce[:], input[n:])
|
||||
msg.Version = 4
|
||||
}
|
||||
|
||||
var padSpace = make([]byte, 300)
|
||||
|
||||
func sealEIP8(msg interface{}, h *encHandshake) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := rlp.Encode(buf, msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// encrypt using remote-pubk
|
||||
return ecies.Encrypt(rand.Reader, h.remotePub, resp, nil, nil)
|
||||
// pad with random amount of data. the amount needs to be at least 100 bytes to make
|
||||
// the message distinguishable from pre-EIP-8 handshakes.
|
||||
pad := padSpace[:mrand.Intn(len(padSpace)-100)+100]
|
||||
buf.Write(pad)
|
||||
prefix := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(prefix, uint16(buf.Len()+eciesOverhead))
|
||||
|
||||
enc, err := ecies.Encrypt(rand.Reader, h.remotePub, buf.Bytes(), nil, prefix)
|
||||
return append(prefix, enc...), err
|
||||
}
|
||||
|
||||
type plainDecoder interface {
|
||||
decodePlain([]byte)
|
||||
}
|
||||
|
||||
func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r io.Reader) ([]byte, error) {
|
||||
buf := make([]byte, plainSize)
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return buf, err
|
||||
}
|
||||
// Attempt decoding pre-EIP-8 "plain" format.
|
||||
key := ecies.ImportECDSA(prv)
|
||||
if dec, err := key.Decrypt(rand.Reader, buf, nil, nil); err == nil {
|
||||
msg.decodePlain(dec)
|
||||
return buf, nil
|
||||
}
|
||||
// Could be EIP-8 format, try that.
|
||||
prefix := buf[:2]
|
||||
size := binary.BigEndian.Uint16(prefix)
|
||||
if size < uint16(plainSize) {
|
||||
return buf, fmt.Errorf("size underflow, need at least %d bytes", plainSize)
|
||||
}
|
||||
buf = append(buf, make([]byte, size-uint16(plainSize)+2)...)
|
||||
if _, err := io.ReadFull(r, buf[plainSize:]); err != nil {
|
||||
return buf, err
|
||||
}
|
||||
dec, err := key.Decrypt(rand.Reader, buf[2:], nil, prefix)
|
||||
if err != nil {
|
||||
return buf, err
|
||||
}
|
||||
// Can't use rlp.DecodeBytes here because it rejects
|
||||
// trailing data (forward-compatibility).
|
||||
s := rlp.NewStream(bytes.NewReader(dec), 0)
|
||||
return buf, s.Decode(msg)
|
||||
}
|
||||
|
||||
// importPublicKey unmarshals 512 bit public keys.
|
||||
@ -458,7 +521,11 @@ func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) {
|
||||
return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey))
|
||||
}
|
||||
// TODO: fewer pointless conversions
|
||||
return ecies.ImportECDSAPublic(crypto.ToECDSAPub(pubKey65)), nil
|
||||
pub := crypto.ToECDSAPub(pubKey65)
|
||||
if pub.X == nil {
|
||||
return nil, fmt.Errorf("invalid public key")
|
||||
}
|
||||
return ecies.ImportECDSAPublic(pub), nil
|
||||
}
|
||||
|
||||
func exportPubkey(pub *ecies.PublicKey) []byte {
|
||||
|
235
p2p/rlpx_test.go
235
p2p/rlpx_test.go
@ -21,6 +21,7 @@ import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"reflect"
|
||||
@ -160,6 +161,7 @@ func TestProtocolHandshake(t *testing.T) {
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer fd1.Close()
|
||||
rlpx := newRLPX(fd0)
|
||||
remid, err := rlpx.doEncHandshake(prv0, node1)
|
||||
if err != nil {
|
||||
@ -176,6 +178,7 @@ func TestProtocolHandshake(t *testing.T) {
|
||||
t.Errorf("dial side proto handshake error: %v", err)
|
||||
return
|
||||
}
|
||||
phs.Rest = nil
|
||||
if !reflect.DeepEqual(phs, hs1) {
|
||||
t.Errorf("dial side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs1))
|
||||
return
|
||||
@ -184,6 +187,7 @@ func TestProtocolHandshake(t *testing.T) {
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer fd1.Close()
|
||||
rlpx := newRLPX(fd1)
|
||||
remid, err := rlpx.doEncHandshake(prv1, nil)
|
||||
if err != nil {
|
||||
@ -200,6 +204,7 @@ func TestProtocolHandshake(t *testing.T) {
|
||||
t.Errorf("listen side proto handshake error: %v", err)
|
||||
return
|
||||
}
|
||||
phs.Rest = nil
|
||||
if !reflect.DeepEqual(phs, hs0) {
|
||||
t.Errorf("listen side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs0))
|
||||
return
|
||||
@ -214,7 +219,6 @@ func TestProtocolHandshake(t *testing.T) {
|
||||
|
||||
func TestProtocolHandshakeErrors(t *testing.T) {
|
||||
our := &protoHandshake{Version: 3, Caps: []Cap{{"foo", 2}, {"bar", 3}}, Name: "quux"}
|
||||
id := randomID()
|
||||
tests := []struct {
|
||||
code uint64
|
||||
msg interface{}
|
||||
@ -240,11 +244,6 @@ func TestProtocolHandshakeErrors(t *testing.T) {
|
||||
msg: []byte{1, 2, 3},
|
||||
err: newPeerError(errInvalidMsg, "(code 0) (size 4) rlp: expected input list for p2p.protoHandshake"),
|
||||
},
|
||||
{
|
||||
code: handshakeMsg,
|
||||
msg: &protoHandshake{Version: 9944, ID: id},
|
||||
err: DiscIncompatibleVersion,
|
||||
},
|
||||
{
|
||||
code: handshakeMsg,
|
||||
msg: &protoHandshake{Version: 3},
|
||||
@ -372,3 +371,227 @@ func TestRLPXFrameRW(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type handshakeAuthTest struct {
|
||||
input string
|
||||
isPlain bool
|
||||
wantVersion uint
|
||||
wantRest []rlp.RawValue
|
||||
}
|
||||
|
||||
var eip8HandshakeAuthTests = []handshakeAuthTest{
|
||||
// (Auth₁) RLPx v4 plain encoding
|
||||
{
|
||||
input: `
|
||||
048ca79ad18e4b0659fab4853fe5bc58eb83992980f4c9cc147d2aa31532efd29a3d3dc6a3d89eaf
|
||||
913150cfc777ce0ce4af2758bf4810235f6e6ceccfee1acc6b22c005e9e3a49d6448610a58e98744
|
||||
ba3ac0399e82692d67c1f58849050b3024e21a52c9d3b01d871ff5f210817912773e610443a9ef14
|
||||
2e91cdba0bd77b5fdf0769b05671fc35f83d83e4d3b0b000c6b2a1b1bba89e0fc51bf4e460df3105
|
||||
c444f14be226458940d6061c296350937ffd5e3acaceeaaefd3c6f74be8e23e0f45163cc7ebd7622
|
||||
0f0128410fd05250273156d548a414444ae2f7dea4dfca2d43c057adb701a715bf59f6fb66b2d1d2
|
||||
0f2c703f851cbf5ac47396d9ca65b6260bd141ac4d53e2de585a73d1750780db4c9ee4cd4d225173
|
||||
a4592ee77e2bd94d0be3691f3b406f9bba9b591fc63facc016bfa8
|
||||
`,
|
||||
isPlain: true,
|
||||
wantVersion: 4,
|
||||
},
|
||||
// (Auth₂) EIP-8 encoding
|
||||
{
|
||||
input: `
|
||||
01b304ab7578555167be8154d5cc456f567d5ba302662433674222360f08d5f1534499d3678b513b
|
||||
0fca474f3a514b18e75683032eb63fccb16c156dc6eb2c0b1593f0d84ac74f6e475f1b8d56116b84
|
||||
9634a8c458705bf83a626ea0384d4d7341aae591fae42ce6bd5c850bfe0b999a694a49bbbaf3ef6c
|
||||
da61110601d3b4c02ab6c30437257a6e0117792631a4b47c1d52fc0f8f89caadeb7d02770bf999cc
|
||||
147d2df3b62e1ffb2c9d8c125a3984865356266bca11ce7d3a688663a51d82defaa8aad69da39ab6
|
||||
d5470e81ec5f2a7a47fb865ff7cca21516f9299a07b1bc63ba56c7a1a892112841ca44b6e0034dee
|
||||
70c9adabc15d76a54f443593fafdc3b27af8059703f88928e199cb122362a4b35f62386da7caad09
|
||||
c001edaeb5f8a06d2b26fb6cb93c52a9fca51853b68193916982358fe1e5369e249875bb8d0d0ec3
|
||||
6f917bc5e1eafd5896d46bd61ff23f1a863a8a8dcd54c7b109b771c8e61ec9c8908c733c0263440e
|
||||
2aa067241aaa433f0bb053c7b31a838504b148f570c0ad62837129e547678c5190341e4f1693956c
|
||||
3bf7678318e2d5b5340c9e488eefea198576344afbdf66db5f51204a6961a63ce072c8926c
|
||||
`,
|
||||
wantVersion: 4,
|
||||
wantRest: []rlp.RawValue{},
|
||||
},
|
||||
// (Auth₃) RLPx v4 EIP-8 encoding with version 56, additional list elements
|
||||
{
|
||||
input: `
|
||||
01b8044c6c312173685d1edd268aa95e1d495474c6959bcdd10067ba4c9013df9e40ff45f5bfd6f7
|
||||
2471f93a91b493f8e00abc4b80f682973de715d77ba3a005a242eb859f9a211d93a347fa64b597bf
|
||||
280a6b88e26299cf263b01b8dfdb712278464fd1c25840b995e84d367d743f66c0e54a586725b7bb
|
||||
f12acca27170ae3283c1073adda4b6d79f27656993aefccf16e0d0409fe07db2dc398a1b7e8ee93b
|
||||
cd181485fd332f381d6a050fba4c7641a5112ac1b0b61168d20f01b479e19adf7fdbfa0905f63352
|
||||
bfc7e23cf3357657455119d879c78d3cf8c8c06375f3f7d4861aa02a122467e069acaf513025ff19
|
||||
6641f6d2810ce493f51bee9c966b15c5043505350392b57645385a18c78f14669cc4d960446c1757
|
||||
1b7c5d725021babbcd786957f3d17089c084907bda22c2b2675b4378b114c601d858802a55345a15
|
||||
116bc61da4193996187ed70d16730e9ae6b3bb8787ebcaea1871d850997ddc08b4f4ea668fbf3740
|
||||
7ac044b55be0908ecb94d4ed172ece66fd31bfdadf2b97a8bc690163ee11f5b575a4b44e36e2bfb2
|
||||
f0fce91676fd64c7773bac6a003f481fddd0bae0a1f31aa27504e2a533af4cef3b623f4791b2cca6
|
||||
d490
|
||||
`,
|
||||
wantVersion: 56,
|
||||
wantRest: []rlp.RawValue{{0x01}, {0x02}, {0xC2, 0x04, 0x05}},
|
||||
},
|
||||
}
|
||||
|
||||
type handshakeAckTest struct {
|
||||
input string
|
||||
wantVersion uint
|
||||
wantRest []rlp.RawValue
|
||||
}
|
||||
|
||||
var eip8HandshakeRespTests = []handshakeAckTest{
|
||||
// (Ack₁) RLPx v4 plain encoding
|
||||
{
|
||||
input: `
|
||||
049f8abcfa9c0dc65b982e98af921bc0ba6e4243169348a236abe9df5f93aa69d99cadddaa387662
|
||||
b0ff2c08e9006d5a11a278b1b3331e5aaabf0a32f01281b6f4ede0e09a2d5f585b26513cb794d963
|
||||
5a57563921c04a9090b4f14ee42be1a5461049af4ea7a7f49bf4c97a352d39c8d02ee4acc416388c
|
||||
1c66cec761d2bc1c72da6ba143477f049c9d2dde846c252c111b904f630ac98e51609b3b1f58168d
|
||||
dca6505b7196532e5f85b259a20c45e1979491683fee108e9660edbf38f3add489ae73e3dda2c71b
|
||||
d1497113d5c755e942d1
|
||||
`,
|
||||
wantVersion: 4,
|
||||
},
|
||||
// (Ack₂) EIP-8 encoding
|
||||
{
|
||||
input: `
|
||||
01ea0451958701280a56482929d3b0757da8f7fbe5286784beead59d95089c217c9b917788989470
|
||||
b0e330cc6e4fb383c0340ed85fab836ec9fb8a49672712aeabbdfd1e837c1ff4cace34311cd7f4de
|
||||
05d59279e3524ab26ef753a0095637ac88f2b499b9914b5f64e143eae548a1066e14cd2f4bd7f814
|
||||
c4652f11b254f8a2d0191e2f5546fae6055694aed14d906df79ad3b407d94692694e259191cde171
|
||||
ad542fc588fa2b7333313d82a9f887332f1dfc36cea03f831cb9a23fea05b33deb999e85489e645f
|
||||
6aab1872475d488d7bd6c7c120caf28dbfc5d6833888155ed69d34dbdc39c1f299be1057810f34fb
|
||||
e754d021bfca14dc989753d61c413d261934e1a9c67ee060a25eefb54e81a4d14baff922180c395d
|
||||
3f998d70f46f6b58306f969627ae364497e73fc27f6d17ae45a413d322cb8814276be6ddd13b885b
|
||||
201b943213656cde498fa0e9ddc8e0b8f8a53824fbd82254f3e2c17e8eaea009c38b4aa0a3f306e8
|
||||
797db43c25d68e86f262e564086f59a2fc60511c42abfb3057c247a8a8fe4fb3ccbadde17514b7ac
|
||||
8000cdb6a912778426260c47f38919a91f25f4b5ffb455d6aaaf150f7e5529c100ce62d6d92826a7
|
||||
1778d809bdf60232ae21ce8a437eca8223f45ac37f6487452ce626f549b3b5fdee26afd2072e4bc7
|
||||
5833c2464c805246155289f4
|
||||
`,
|
||||
wantVersion: 4,
|
||||
wantRest: []rlp.RawValue{},
|
||||
},
|
||||
// (Ack₃) EIP-8 encoding with version 57, additional list elements
|
||||
{
|
||||
input: `
|
||||
01f004076e58aae772bb101ab1a8e64e01ee96e64857ce82b1113817c6cdd52c09d26f7b90981cd7
|
||||
ae835aeac72e1573b8a0225dd56d157a010846d888dac7464baf53f2ad4e3d584531fa203658fab0
|
||||
3a06c9fd5e35737e417bc28c1cbf5e5dfc666de7090f69c3b29754725f84f75382891c561040ea1d
|
||||
dc0d8f381ed1b9d0d4ad2a0ec021421d847820d6fa0ba66eaf58175f1b235e851c7e2124069fbc20
|
||||
2888ddb3ac4d56bcbd1b9b7eab59e78f2e2d400905050f4a92dec1c4bdf797b3fc9b2f8e84a482f3
|
||||
d800386186712dae00d5c386ec9387a5e9c9a1aca5a573ca91082c7d68421f388e79127a5177d4f8
|
||||
590237364fd348c9611fa39f78dcdceee3f390f07991b7b47e1daa3ebcb6ccc9607811cb17ce51f1
|
||||
c8c2c5098dbdd28fca547b3f58c01a424ac05f869f49c6a34672ea2cbbc558428aa1fe48bbfd6115
|
||||
8b1b735a65d99f21e70dbc020bfdface9f724a0d1fb5895db971cc81aa7608baa0920abb0a565c9c
|
||||
436e2fd13323428296c86385f2384e408a31e104670df0791d93e743a3a5194ee6b076fb6323ca59
|
||||
3011b7348c16cf58f66b9633906ba54a2ee803187344b394f75dd2e663a57b956cb830dd7a908d4f
|
||||
39a2336a61ef9fda549180d4ccde21514d117b6c6fd07a9102b5efe710a32af4eeacae2cb3b1dec0
|
||||
35b9593b48b9d3ca4c13d245d5f04169b0b1
|
||||
`,
|
||||
wantVersion: 57,
|
||||
wantRest: []rlp.RawValue{{0x06}, {0xC2, 0x07, 0x08}, {0x81, 0xFA}},
|
||||
},
|
||||
}
|
||||
|
||||
func TestHandshakeForwardCompatibility(t *testing.T) {
|
||||
var (
|
||||
keyA, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||
keyB, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
pubA = crypto.FromECDSAPub(&keyA.PublicKey)[1:]
|
||||
pubB = crypto.FromECDSAPub(&keyB.PublicKey)[1:]
|
||||
ephA, _ = crypto.HexToECDSA("869d6ecf5211f1cc60418a13b9d870b22959d0c16f02bec714c960dd2298a32d")
|
||||
ephB, _ = crypto.HexToECDSA("e238eb8e04fee6511ab04c6dd3c89ce097b11f25d584863ac2b6d5b35b1847e4")
|
||||
ephPubA = crypto.FromECDSAPub(&ephA.PublicKey)[1:]
|
||||
ephPubB = crypto.FromECDSAPub(&ephB.PublicKey)[1:]
|
||||
nonceA = unhex("7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6")
|
||||
nonceB = unhex("559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd")
|
||||
_, _, _, _ = pubA, pubB, ephPubA, ephPubB
|
||||
authSignature = unhex("299ca6acfd35e3d72d8ba3d1e2b60b5561d5af5218eb5bc182045769eb4226910a301acae3b369fffc4a4899d6b02531e89fd4fe36a2cf0d93607ba470b50f7800")
|
||||
_ = authSignature
|
||||
)
|
||||
makeAuth := func(test handshakeAuthTest) *authMsgV4 {
|
||||
msg := &authMsgV4{Version: test.wantVersion, Rest: test.wantRest, gotPlain: test.isPlain}
|
||||
copy(msg.Signature[:], authSignature)
|
||||
copy(msg.InitiatorPubkey[:], pubA)
|
||||
copy(msg.Nonce[:], nonceA)
|
||||
return msg
|
||||
}
|
||||
makeAck := func(test handshakeAckTest) *authRespV4 {
|
||||
msg := &authRespV4{Version: test.wantVersion, Rest: test.wantRest}
|
||||
copy(msg.RandomPubkey[:], ephPubB)
|
||||
copy(msg.Nonce[:], nonceB)
|
||||
return msg
|
||||
}
|
||||
|
||||
// check auth msg parsing
|
||||
for _, test := range eip8HandshakeAuthTests {
|
||||
r := bytes.NewReader(unhex(test.input))
|
||||
msg := new(authMsgV4)
|
||||
ciphertext, err := readHandshakeMsg(msg, encAuthMsgLen, keyB, r)
|
||||
if err != nil {
|
||||
t.Errorf("error for input %x:\n %v", unhex(test.input), err)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(ciphertext, unhex(test.input)) {
|
||||
t.Errorf("wrong ciphertext for input %x:\n %x", unhex(test.input), ciphertext)
|
||||
}
|
||||
want := makeAuth(test)
|
||||
if !reflect.DeepEqual(msg, want) {
|
||||
t.Errorf("wrong msg for input %x:\ngot %s\nwant %s", unhex(test.input), spew.Sdump(msg), spew.Sdump(want))
|
||||
}
|
||||
}
|
||||
|
||||
// check auth resp parsing
|
||||
for _, test := range eip8HandshakeRespTests {
|
||||
input := unhex(test.input)
|
||||
r := bytes.NewReader(input)
|
||||
msg := new(authRespV4)
|
||||
ciphertext, err := readHandshakeMsg(msg, encAuthRespLen, keyA, r)
|
||||
if err != nil {
|
||||
t.Errorf("error for input %x:\n %v", input, err)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(ciphertext, input) {
|
||||
t.Errorf("wrong ciphertext for input %x:\n %x", input, err)
|
||||
}
|
||||
want := makeAck(test)
|
||||
if !reflect.DeepEqual(msg, want) {
|
||||
t.Errorf("wrong msg for input %x:\ngot %s\nwant %s", input, spew.Sdump(msg), spew.Sdump(want))
|
||||
}
|
||||
}
|
||||
|
||||
// check derivation for (Auth₂, Ack₂) on recipient side
|
||||
var (
|
||||
hs = &encHandshake{
|
||||
initiator: false,
|
||||
respNonce: nonceB,
|
||||
randomPrivKey: ecies.ImportECDSA(ephB),
|
||||
}
|
||||
authCiphertext = unhex(eip8HandshakeAuthTests[1].input)
|
||||
authRespCiphertext = unhex(eip8HandshakeRespTests[1].input)
|
||||
authMsg = makeAuth(eip8HandshakeAuthTests[1])
|
||||
wantAES = unhex("80e8632c05fed6fc2a13b0f8d31a3cf645366239170ea067065aba8e28bac487")
|
||||
wantMAC = unhex("2ea74ec5dae199227dff1af715362700e989d889d7a493cb0639691efb8e5f98")
|
||||
wantFooIngressHash = unhex("0c7ec6340062cc46f5e9f1e3cf86f8c8c403c5a0964f5df0ebd34a75ddc86db5")
|
||||
)
|
||||
if err := hs.handleAuthMsg(authMsg, keyB); err != nil {
|
||||
t.Fatalf("handleAuthMsg: %v", err)
|
||||
}
|
||||
derived, err := hs.secrets(authCiphertext, authRespCiphertext)
|
||||
if err != nil {
|
||||
t.Fatalf("secrets: %v", err)
|
||||
}
|
||||
if !bytes.Equal(derived.AES, wantAES) {
|
||||
t.Errorf("aes-secret mismatch:\ngot %x\nwant %x", derived.AES, wantAES)
|
||||
}
|
||||
if !bytes.Equal(derived.MAC, wantMAC) {
|
||||
t.Errorf("mac-secret mismatch:\ngot %x\nwant %x", derived.MAC, wantMAC)
|
||||
}
|
||||
io.WriteString(derived.IngressMAC, "foo")
|
||||
fooIngressHash := derived.IngressMAC.Sum(nil)
|
||||
if !bytes.Equal(fooIngressHash, wantFooIngressHash) {
|
||||
t.Errorf("ingress-mac('foo') mismatch:\ngot %x\nwant %x", fooIngressHash, wantFooIngressHash)
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,10 @@ var (
|
||||
MaximumExtraDataSize = big.NewInt(32) // 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.
|
||||
CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfer 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.
|
||||
TxGas = big.NewInt(21000) // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
|
||||
TxGasContractCreation = big.NewInt(53000) // Per transaction that creates a contract. 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.
|
||||
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.
|
||||
@ -40,7 +41,7 @@ var (
|
||||
Sha256WordGas = big.NewInt(12) //
|
||||
|
||||
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
|
||||
GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
|
||||
GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block.
|
||||
|
||||
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
|
||||
Sha256Gas = big.NewInt(60) //
|
||||
|
33
params/util.go
Normal file
33
params/util.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package params
|
||||
|
||||
import "math/big"
|
||||
|
||||
var (
|
||||
TestNetHomesteadBlock = big.NewInt(494000) // testnet homestead block
|
||||
MainNetHomesteadBlock = big.NewInt(1150000) // mainnet homestead block
|
||||
HomesteadBlock = MainNetHomesteadBlock // homestead block used to check against
|
||||
)
|
||||
|
||||
func IsHomestead(blockNumber *big.Int) bool {
|
||||
// for unit tests TODO: flip to true after homestead is live
|
||||
if blockNumber == nil {
|
||||
return false
|
||||
}
|
||||
return blockNumber.Cmp(HomesteadBlock) >= 0
|
||||
}
|
@ -63,11 +63,12 @@ type Decoder interface {
|
||||
// must contain an element for each decoded field. Decode returns an
|
||||
// error if there are too few or too many elements.
|
||||
//
|
||||
// The decoding of struct fields honours one particular struct tag,
|
||||
// "nil". This tag applies to pointer-typed fields and changes the
|
||||
// The decoding of struct fields honours two struct tags, "tail" and
|
||||
// "nil". For an explanation of "tail", see the example.
|
||||
// The "nil" tag applies to pointer-typed fields and changes the
|
||||
// decoding rules for the field such that input values of size zero
|
||||
// decode as a nil pointer. This tag can be useful when decoding recursive
|
||||
// types.
|
||||
// decode as a nil pointer. This tag can be useful when decoding
|
||||
// recursive types.
|
||||
//
|
||||
// type StructWithEmptyOK struct {
|
||||
// Foo *[20]byte `rlp:"nil"`
|
||||
@ -190,7 +191,7 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
|
||||
case kind == reflect.String:
|
||||
return decodeString, nil
|
||||
case kind == reflect.Slice || kind == reflect.Array:
|
||||
return makeListDecoder(typ)
|
||||
return makeListDecoder(typ, tags)
|
||||
case kind == reflect.Struct:
|
||||
return makeStructDecoder(typ)
|
||||
case kind == reflect.Ptr:
|
||||
@ -264,7 +265,7 @@ func decodeBigInt(s *Stream, val reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeListDecoder(typ reflect.Type) (decoder, error) {
|
||||
func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) {
|
||||
etype := typ.Elem()
|
||||
if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) {
|
||||
if typ.Kind() == reflect.Array {
|
||||
@ -277,15 +278,26 @@ func makeListDecoder(typ reflect.Type) (decoder, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isArray := typ.Kind() == reflect.Array
|
||||
return func(s *Stream, val reflect.Value) error {
|
||||
if isArray {
|
||||
var dec decoder
|
||||
switch {
|
||||
case typ.Kind() == reflect.Array:
|
||||
dec = func(s *Stream, val reflect.Value) error {
|
||||
return decodeListArray(s, val, etypeinfo.decoder)
|
||||
} else {
|
||||
}
|
||||
case tag.tail:
|
||||
// A slice with "tail" tag can occur as the last field
|
||||
// of a struct and is upposed to swallow all remaining
|
||||
// list elements. The struct decoder already called s.List,
|
||||
// proceed directly to decoding the elements.
|
||||
dec = func(s *Stream, val reflect.Value) error {
|
||||
return decodeSliceElems(s, val, etypeinfo.decoder)
|
||||
}
|
||||
default:
|
||||
dec = func(s *Stream, val reflect.Value) error {
|
||||
return decodeListSlice(s, val, etypeinfo.decoder)
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
return dec, nil
|
||||
}
|
||||
|
||||
func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
|
||||
@ -297,7 +309,13 @@ func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
|
||||
val.Set(reflect.MakeSlice(val.Type(), 0, 0))
|
||||
return s.ListEnd()
|
||||
}
|
||||
if err := decodeSliceElems(s, val, elemdec); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.ListEnd()
|
||||
}
|
||||
|
||||
func decodeSliceElems(s *Stream, val reflect.Value, elemdec decoder) error {
|
||||
i := 0
|
||||
for ; ; i++ {
|
||||
// grow slice if necessary
|
||||
@ -323,12 +341,11 @@ func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
|
||||
if i < val.Len() {
|
||||
val.SetLen(i)
|
||||
}
|
||||
return s.ListEnd()
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error {
|
||||
_, err := s.List()
|
||||
if err != nil {
|
||||
if _, err := s.List(); err != nil {
|
||||
return wrapStreamError(err, val.Type())
|
||||
}
|
||||
vlen := val.Len()
|
||||
@ -398,11 +415,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) {
|
||||
return nil, err
|
||||
}
|
||||
dec := func(s *Stream, val reflect.Value) (err error) {
|
||||
if _, err = s.List(); err != nil {
|
||||
if _, err := s.List(); err != nil {
|
||||
return wrapStreamError(err, typ)
|
||||
}
|
||||
for _, f := range fields {
|
||||
err = f.info.decoder(s, val.Field(f.index))
|
||||
err := f.info.decoder(s, val.Field(f.index))
|
||||
if err == EOL {
|
||||
return &decodeError{msg: "too few elements", typ: typ}
|
||||
} else if err != nil {
|
||||
|
33
rlp/decode_tail_test.go
Normal file
33
rlp/decode_tail_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package rlp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type structWithTail struct {
|
||||
A, B uint
|
||||
C []uint `rlp:"tail"`
|
||||
}
|
||||
|
||||
func ExampleDecode_structTagTail() {
|
||||
// In this example, the "tail" struct tag is used to decode lists of
|
||||
// differing length into a struct.
|
||||
var val structWithTail
|
||||
|
||||
err := Decode(bytes.NewReader([]byte{0xC4, 0x01, 0x02, 0x03, 0x04}), &val)
|
||||
fmt.Printf("with 4 elements: err=%v val=%v\n", err, val)
|
||||
|
||||
err = Decode(bytes.NewReader([]byte{0xC6, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), &val)
|
||||
fmt.Printf("with 6 elements: err=%v val=%v\n", err, val)
|
||||
|
||||
// Note that at least two list elements must be present to
|
||||
// fill fields A and B:
|
||||
err = Decode(bytes.NewReader([]byte{0xC1, 0x01}), &val)
|
||||
fmt.Printf("with 1 element: err=%q\n", err)
|
||||
|
||||
// Output:
|
||||
// with 4 elements: err=<nil> val={1 2 [3 4]}
|
||||
// with 6 elements: err=<nil> val={1 2 [3 4 5 6]}
|
||||
// with 1 element: err="rlp: too few elements for rlp.structWithTail"
|
||||
}
|
@ -312,6 +312,26 @@ type recstruct struct {
|
||||
Child *recstruct `rlp:"nil"`
|
||||
}
|
||||
|
||||
type invalidTail1 struct {
|
||||
A uint `rlp:"tail"`
|
||||
B string
|
||||
}
|
||||
|
||||
type invalidTail2 struct {
|
||||
A uint
|
||||
B string `rlp:"tail"`
|
||||
}
|
||||
|
||||
type tailRaw struct {
|
||||
A uint
|
||||
Tail []RawValue `rlp:"tail"`
|
||||
}
|
||||
|
||||
type tailUint struct {
|
||||
A uint
|
||||
Tail []uint `rlp:"tail"`
|
||||
}
|
||||
|
||||
var (
|
||||
veryBigInt = big.NewInt(0).Add(
|
||||
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
|
||||
@ -437,6 +457,38 @@ var decodeTests = []decodeTest{
|
||||
ptr: new(recstruct),
|
||||
error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I",
|
||||
},
|
||||
{
|
||||
input: "C0",
|
||||
ptr: new(invalidTail1),
|
||||
error: "rlp: invalid struct tag \"tail\" for rlp.invalidTail1.A (must be on last field)",
|
||||
},
|
||||
{
|
||||
input: "C0",
|
||||
ptr: new(invalidTail2),
|
||||
error: "rlp: invalid struct tag \"tail\" for rlp.invalidTail2.B (field type is not slice)",
|
||||
},
|
||||
{
|
||||
input: "C50102C20102",
|
||||
ptr: new(tailUint),
|
||||
error: "rlp: expected input string or byte for uint, decoding into (rlp.tailUint).Tail[1]",
|
||||
},
|
||||
|
||||
// struct tag "tail"
|
||||
{
|
||||
input: "C3010203",
|
||||
ptr: new(tailRaw),
|
||||
value: tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}},
|
||||
},
|
||||
{
|
||||
input: "C20102",
|
||||
ptr: new(tailRaw),
|
||||
value: tailRaw{A: 1, Tail: []RawValue{unhex("02")}},
|
||||
},
|
||||
{
|
||||
input: "C101",
|
||||
ptr: new(tailRaw),
|
||||
value: tailRaw{A: 1, Tail: []RawValue{}},
|
||||
},
|
||||
|
||||
// RawValue
|
||||
{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
|
||||
|
@ -345,7 +345,7 @@ var (
|
||||
)
|
||||
|
||||
// makeWriter creates a writer function for the given type.
|
||||
func makeWriter(typ reflect.Type) (writer, error) {
|
||||
func makeWriter(typ reflect.Type, ts tags) (writer, error) {
|
||||
kind := typ.Kind()
|
||||
switch {
|
||||
case typ == rawValueType:
|
||||
@ -371,7 +371,7 @@ func makeWriter(typ reflect.Type) (writer, error) {
|
||||
case kind == reflect.Array && isByte(typ.Elem()):
|
||||
return writeByteArray, nil
|
||||
case kind == reflect.Slice || kind == reflect.Array:
|
||||
return makeSliceWriter(typ)
|
||||
return makeSliceWriter(typ, ts)
|
||||
case kind == reflect.Struct:
|
||||
return makeStructWriter(typ)
|
||||
case kind == reflect.Ptr:
|
||||
@ -507,20 +507,21 @@ func writeInterface(val reflect.Value, w *encbuf) error {
|
||||
return ti.writer(eval, w)
|
||||
}
|
||||
|
||||
func makeSliceWriter(typ reflect.Type) (writer, error) {
|
||||
func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) {
|
||||
etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writer := func(val reflect.Value, w *encbuf) error {
|
||||
lh := w.list()
|
||||
if !ts.tail {
|
||||
defer w.listEnd(w.list())
|
||||
}
|
||||
vlen := val.Len()
|
||||
for i := 0; i < vlen; i++ {
|
||||
if err := etypeinfo.writer(val.Index(i), w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
w.listEnd(lh)
|
||||
return nil
|
||||
}
|
||||
return writer, nil
|
||||
|
@ -214,6 +214,10 @@ var encTests = []encTest{
|
||||
{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
|
||||
{val: &recstruct{5, nil}, output: "C205C0"},
|
||||
{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
|
||||
{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"},
|
||||
{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
|
||||
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
|
||||
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
|
||||
|
||||
// nil
|
||||
{val: (*uint)(nil), output: "80"},
|
||||
|
@ -17,7 +17,9 @@
|
||||
package rlp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -33,7 +35,13 @@ type typeinfo struct {
|
||||
|
||||
// represents struct tags
|
||||
type tags struct {
|
||||
// rlp:"nil" controls whether empty input results in a nil pointer.
|
||||
nilOK bool
|
||||
|
||||
// rlp:"tail" controls whether this field swallows additional list
|
||||
// elements. It can only be set for the last field, which must be
|
||||
// of slice type.
|
||||
tail bool
|
||||
}
|
||||
|
||||
type typekey struct {
|
||||
@ -89,7 +97,10 @@ type field struct {
|
||||
func structFields(typ reflect.Type) (fields []field, err error) {
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
if f := typ.Field(i); f.PkgPath == "" { // exported
|
||||
tags := parseStructTag(f.Tag.Get("rlp"))
|
||||
tags, err := parseStructTag(typ, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := cachedTypeInfo1(f.Type, tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -100,8 +111,27 @@ func structFields(typ reflect.Type) (fields []field, err error) {
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
func parseStructTag(tag string) tags {
|
||||
return tags{nilOK: tag == "nil"}
|
||||
func parseStructTag(typ reflect.Type, fi int) (tags, error) {
|
||||
f := typ.Field(fi)
|
||||
var ts tags
|
||||
for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
|
||||
switch t = strings.TrimSpace(t); t {
|
||||
case "":
|
||||
case "nil":
|
||||
ts.nilOK = true
|
||||
case "tail":
|
||||
ts.tail = true
|
||||
if fi != typ.NumField()-1 {
|
||||
return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name)
|
||||
}
|
||||
if f.Type.Kind() != reflect.Slice {
|
||||
return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name)
|
||||
}
|
||||
default:
|
||||
return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name)
|
||||
}
|
||||
}
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) {
|
||||
@ -109,7 +139,7 @@ func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) {
|
||||
if info.decoder, err = makeDecoder(typ, tags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.writer, err = makeWriter(typ); err != nil {
|
||||
if info.writer, err = makeWriter(typ, tags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return info, nil
|
||||
|
@ -661,7 +661,7 @@ func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
|
||||
|
||||
pending := self.ethereum.TxPool().GetTransactions()
|
||||
for _, p := range pending {
|
||||
if pFrom, err := p.From(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
|
||||
if pFrom, err := p.FromFrontier(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
|
||||
self.ethereum.TxPool().RemoveTx(common.HexToHash(args.Tx.Hash))
|
||||
return self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data)
|
||||
}
|
||||
@ -688,7 +688,7 @@ func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error
|
||||
|
||||
var ltxs []*tx
|
||||
for _, tx := range txs {
|
||||
if from, _ := tx.From(); accountSet.Has(from) {
|
||||
if from, _ := tx.FromFrontier(); accountSet.Has(from) {
|
||||
ltxs = append(ltxs, newTx(tx))
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes {
|
||||
// v.BlockHash =
|
||||
// v.BlockNumber =
|
||||
// v.TxIndex =
|
||||
from, _ := tx.From()
|
||||
from, _ := tx.FromFrontier()
|
||||
v.From = newHexData(from)
|
||||
v.To = newHexData(tx.To())
|
||||
v.Value = newHexNum(tx.Value())
|
||||
|
@ -17,11 +17,15 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func TestBcValidBlockTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -29,6 +33,7 @@ func TestBcValidBlockTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcUncleHeaderValidityTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -36,6 +41,7 @@ func TestBcUncleHeaderValidityTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcUncleTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -43,6 +49,7 @@ func TestBcUncleTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcForkUncleTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -50,6 +57,7 @@ func TestBcForkUncleTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcInvalidHeaderTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -57,6 +65,7 @@ func TestBcInvalidHeaderTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcInvalidRLPTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -64,6 +73,7 @@ func TestBcInvalidRLPTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcRPCAPITests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -71,6 +81,7 @@ func TestBcRPCAPITests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcForkBlockTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -78,6 +89,7 @@ func TestBcForkBlockTests(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcForkStress(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -85,6 +97,10 @@ func TestBcForkStress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcTotalDifficulty(t *testing.T) {
|
||||
// skip because these will fail due to selfish mining fix
|
||||
t.Skip()
|
||||
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -92,6 +108,7 @@ func TestBcTotalDifficulty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcWallet(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -99,6 +116,7 @@ func TestBcWallet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcGasPricer(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -107,6 +125,7 @@ func TestBcGasPricer(t *testing.T) {
|
||||
|
||||
// TODO: iterate over files once we got more than a few
|
||||
func TestBcRandom(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -114,6 +133,10 @@ func TestBcRandom(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcMultiChain(t *testing.T) {
|
||||
// skip due to selfish mining
|
||||
t.Skip()
|
||||
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -121,8 +144,98 @@ func TestBcMultiChain(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBcState(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(1000000)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Homestead tests
|
||||
func TestHomesteadBcValidBlockTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcUncleTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcRPCAPITests(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcForkStress(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcTotalDifficulty(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcWallet(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcGasPricer(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcMultiChain(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomesteadBcState(t *testing.T) {
|
||||
params.HomesteadBlock = big.NewInt(0)
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,6 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
|
||||
}
|
||||
|
||||
for name, test := range bt {
|
||||
// if the test should be skipped, return
|
||||
if skipTest[name] {
|
||||
glog.Infoln("Skipping block test", name)
|
||||
continue
|
||||
@ -192,6 +191,7 @@ func runBlockTest(test *BlockTest) error {
|
||||
}
|
||||
|
||||
cm := ethereum.BlockChain()
|
||||
//vm.Debug = true
|
||||
validBlocks, err := test.TryBlocksInsert(cm)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -292,12 +292,13 @@ func (t *BlockTest) TryBlocksInsert(blockchain *core.BlockChain) ([]btBlock, err
|
||||
}
|
||||
}
|
||||
// RLP decoding worked, try to insert into chain:
|
||||
_, err = blockchain.InsertChain(types.Blocks{cb})
|
||||
blocks := types.Blocks{cb}
|
||||
i, err := blockchain.InsertChain(blocks)
|
||||
if err != nil {
|
||||
if b.BlockHeader == nil {
|
||||
continue // OK - block is supposed to be invalid, continue with next block
|
||||
} else {
|
||||
return nil, fmt.Errorf("Block insertion into chain failed: %v", err)
|
||||
return nil, fmt.Errorf("Block #%v insertion into chain failed: %v", blocks[i].Number(), err)
|
||||
}
|
||||
}
|
||||
if b.BlockHeader == nil {
|
||||
|
0
tests/files/ABITests/basic_abi_tests.json
Normal file → Executable file
0
tests/files/ABITests/basic_abi_tests.json
Normal file → Executable file
0
tests/files/BasicTests/blockgenesistest.json
Normal file → Executable file
0
tests/files/BasicTests/blockgenesistest.json
Normal file → Executable file
0
tests/files/BasicTests/crypto.json
Normal file → Executable file
0
tests/files/BasicTests/crypto.json
Normal file → Executable file
0
tests/files/BasicTests/difficulty.json
Normal file → Executable file
0
tests/files/BasicTests/difficulty.json
Normal file → Executable file
962
tests/files/BasicTests/difficultyCustomHomestead.json
Executable file
962
tests/files/BasicTests/difficultyCustomHomestead.json
Executable file
@ -0,0 +1,962 @@
|
||||
{
|
||||
|
||||
"DifficultyTest1" : {
|
||||
"parentTimestamp" : "0xee40991aa21f6b57",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xee40991aa21f6b57",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest2" : {
|
||||
"parentTimestamp" : "0x66310f5204ce2b93",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x66310f5204ce2b94",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest3" : {
|
||||
"parentTimestamp" : "0x199df37d87ff9ad7",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x199df37d87ff9adf",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest4" : {
|
||||
"parentTimestamp" : "0x25e4b93baa94a077",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x25e4b93baa94a081",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest5" : {
|
||||
"parentTimestamp" : "0xcea8c90445416d88",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xcea8c90445416d95",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest6" : {
|
||||
"parentTimestamp" : "0x9b170d8482bde0f6",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x9b170d8482bde10a",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest7" : {
|
||||
"parentTimestamp" : "0x87b1246b422355d5",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x87b1246b42235639",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest8" : {
|
||||
"parentTimestamp" : "0x1655548b78f23268",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x1655548b78f23588",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest9" : {
|
||||
"parentTimestamp" : "0x41d9b13ec91950ae",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x41d9b13ec9195496",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest10" : {
|
||||
"parentTimestamp" : "0x7de5d8e22525e7c8",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x7de5d8e22525eda4",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest11" : {
|
||||
"parentTimestamp" : "0x3b1de7aea59e6e41",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x3b1de7aea59e6e41",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest12" : {
|
||||
"parentTimestamp" : "0xebae4c023b268eb8",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xebae4c023b268eb9",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest13" : {
|
||||
"parentTimestamp" : "0x6b1d9e56b1854d24",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x6b1d9e56b1854d2c",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest14" : {
|
||||
"parentTimestamp" : "0x88d70a4db7560c69",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x88d70a4db7560c73",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest15" : {
|
||||
"parentTimestamp" : "0x94e34e3d5b9cc7ec",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x94e34e3d5b9cc7f9",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest16" : {
|
||||
"parentTimestamp" : "0xd3f7663e99d3b21b",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xd3f7663e99d3b22f",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest17" : {
|
||||
"parentTimestamp" : "0xde591862869bd30f",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xde591862869bd373",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest18" : {
|
||||
"parentTimestamp" : "0x1c43de429ae5b61f",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x1c43de429ae5b93f",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest19" : {
|
||||
"parentTimestamp" : "0x8c83c6e3d2f2ac94",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x8c83c6e3d2f2b07c",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest20" : {
|
||||
"parentTimestamp" : "0x9d3cc38a451e79e5",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x9d3cc38a451e7fc1",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest21" : {
|
||||
"parentTimestamp" : "0xf7a9ef72fde9cc1f",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xf7a9ef72fde9cc1f",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest22" : {
|
||||
"parentTimestamp" : "0x44e20ccddb30611e",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x44e20ccddb30611f",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest23" : {
|
||||
"parentTimestamp" : "0x739ecb4d84ba8a25",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x739ecb4d84ba8a2d",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest24" : {
|
||||
"parentTimestamp" : "0x089dd4a875b85cda",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x089dd4a875b85ce4",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest25" : {
|
||||
"parentTimestamp" : "0x970ba9071e7a45c9",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x970ba9071e7a45d6",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest26" : {
|
||||
"parentTimestamp" : "0xc6c123177817e71c",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xc6c123177817e730",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest27" : {
|
||||
"parentTimestamp" : "0x154dca49fddd7b77",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x154dca49fddd7bdb",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest28" : {
|
||||
"parentTimestamp" : "0x8cc16de57854fb0a",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x8cc16de57854fe2a",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest29" : {
|
||||
"parentTimestamp" : "0x2eada97a291b2ac2",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x2eada97a291b2eaa",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest30" : {
|
||||
"parentTimestamp" : "0xd22e5ee61d61d3bb",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xd22e5ee61d61d997",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest31" : {
|
||||
"parentTimestamp" : "0xb442249aad3789a5",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xb442249aad3789a5",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f44a8"
|
||||
},
|
||||
|
||||
"DifficultyTest32" : {
|
||||
"parentTimestamp" : "0xee4b860370b53319",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xee4b860370b5331a",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f44a8"
|
||||
},
|
||||
|
||||
"DifficultyTest33" : {
|
||||
"parentTimestamp" : "0x623a8d1212be3800",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x623a8d1212be3808",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f44a8"
|
||||
},
|
||||
|
||||
"DifficultyTest34" : {
|
||||
"parentTimestamp" : "0xbb3ffdca61a49093",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xbb3ffdca61a4909d",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f42c0"
|
||||
},
|
||||
|
||||
"DifficultyTest35" : {
|
||||
"parentTimestamp" : "0xa831fe16c2d344c8",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xa831fe16c2d344d5",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f42c0"
|
||||
},
|
||||
|
||||
"DifficultyTest36" : {
|
||||
"parentTimestamp" : "0x32ec3a141f56813a",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x32ec3a141f56814e",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f40d8"
|
||||
},
|
||||
|
||||
"DifficultyTest37" : {
|
||||
"parentTimestamp" : "0x6c05294540ae4b35",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x6c05294540ae4b99",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0f3198"
|
||||
},
|
||||
|
||||
"DifficultyTest38" : {
|
||||
"parentTimestamp" : "0x08e9fd7d2dd77bbd",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x08e9fd7d2dd77edd",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0eac28"
|
||||
},
|
||||
|
||||
"DifficultyTest39" : {
|
||||
"parentTimestamp" : "0xf79bd3b21abebf91",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xf79bd3b21abec379",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0e8608"
|
||||
},
|
||||
|
||||
"DifficultyTest40" : {
|
||||
"parentTimestamp" : "0x7794b52548070cdb",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x7794b525480712b7",
|
||||
"currentBlockNumber" : "0x0dbba0",
|
||||
"currentDifficulty" : "0x0e8608"
|
||||
},
|
||||
|
||||
"DifficultyTest41" : {
|
||||
"parentTimestamp" : "0x7b57b9e7b5e34f01",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x7b57b9e7b5e34f01",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest42" : {
|
||||
"parentTimestamp" : "0xf05c5d9cb6ce7beb",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xf05c5d9cb6ce7bec",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest43" : {
|
||||
"parentTimestamp" : "0x65fe8a169d514c4c",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x65fe8a169d514c54",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest44" : {
|
||||
"parentTimestamp" : "0xa8577c668ca207fd",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xa8577c668ca20807",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest45" : {
|
||||
"parentTimestamp" : "0xdff431603054c09e",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xdff431603054c0ab",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest46" : {
|
||||
"parentTimestamp" : "0x9896b7e21ea3d7a7",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x9896b7e21ea3d7bb",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest47" : {
|
||||
"parentTimestamp" : "0x67a9d4a2e57e96a1",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x67a9d4a2e57e9705",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest48" : {
|
||||
"parentTimestamp" : "0xbeddc0c871ca1e21",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xbeddc0c871ca2141",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest49" : {
|
||||
"parentTimestamp" : "0x3dd5813f9478fe17",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x3dd5813f947901ff",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest50" : {
|
||||
"parentTimestamp" : "0x24303b775ea3b45e",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x24303b775ea3ba3a",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest51" : {
|
||||
"parentTimestamp" : "0xe3184e2924a51f82",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xe3184e2924a51f82",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest52" : {
|
||||
"parentTimestamp" : "0xfa404e621b51a08c",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xfa404e621b51a08d",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest53" : {
|
||||
"parentTimestamp" : "0xeae4b4602f79c03d",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xeae4b4602f79c045",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest54" : {
|
||||
"parentTimestamp" : "0xd870ec733f5657f9",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xd870ec733f565803",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest55" : {
|
||||
"parentTimestamp" : "0x0f6b6bc872ae69a7",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x0f6b6bc872ae69b4",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest56" : {
|
||||
"parentTimestamp" : "0x93670186032867da",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x93670186032867ee",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest57" : {
|
||||
"parentTimestamp" : "0xb143f70700cfacd9",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xb143f70700cfad3d",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest58" : {
|
||||
"parentTimestamp" : "0x05d735b53a5b1a3d",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x05d735b53a5b1d5d",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest59" : {
|
||||
"parentTimestamp" : "0xc1dbd8afdbd91240",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xc1dbd8afdbd91628",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest60" : {
|
||||
"parentTimestamp" : "0x4bba4a57e86edacc",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x4bba4a57e86ee0a8",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest61" : {
|
||||
"parentTimestamp" : "0xfaa7def06d866e91",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xfaa7def06d866e91",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest62" : {
|
||||
"parentTimestamp" : "0x362425d0b9b5016d",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x362425d0b9b5016e",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest63" : {
|
||||
"parentTimestamp" : "0xaa2227cc2c52ca35",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xaa2227cc2c52ca3d",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest64" : {
|
||||
"parentTimestamp" : "0xa7d36b345279544c",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xa7d36b3452795456",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest65" : {
|
||||
"parentTimestamp" : "0x8247af59c8cdf2a3",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x8247af59c8cdf2b0",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest66" : {
|
||||
"parentTimestamp" : "0xaa3eafba8cdf5552",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xaa3eafba8cdf5566",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest67" : {
|
||||
"parentTimestamp" : "0x0875c185efe29a88",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x0875c185efe29aec",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest68" : {
|
||||
"parentTimestamp" : "0x70f32a514e76c739",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x70f32a514e76ca59",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest69" : {
|
||||
"parentTimestamp" : "0x985221922099d6fb",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x985221922099dae3",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest70" : {
|
||||
"parentTimestamp" : "0xf64eaef9e1a97ed7",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xf64eaef9e1a984b3",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest71" : {
|
||||
"parentTimestamp" : "0xe74027b58f677106",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xe74027b58f677106",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f4528"
|
||||
},
|
||||
|
||||
"DifficultyTest72" : {
|
||||
"parentTimestamp" : "0xcffc2a77fa379335",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xcffc2a77fa379336",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f4528"
|
||||
},
|
||||
|
||||
"DifficultyTest73" : {
|
||||
"parentTimestamp" : "0x2bb6159976679a4f",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x2bb6159976679a57",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f4528"
|
||||
},
|
||||
|
||||
"DifficultyTest74" : {
|
||||
"parentTimestamp" : "0x47e56f02876427ae",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x47e56f02876427b8",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f4340"
|
||||
},
|
||||
|
||||
"DifficultyTest75" : {
|
||||
"parentTimestamp" : "0x891285ed051f7f3f",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x891285ed051f7f4c",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f4340"
|
||||
},
|
||||
|
||||
"DifficultyTest76" : {
|
||||
"parentTimestamp" : "0xfa8fdea7c944b6bb",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xfa8fdea7c944b6cf",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f4158"
|
||||
},
|
||||
|
||||
"DifficultyTest77" : {
|
||||
"parentTimestamp" : "0xe4111ffe1a221e13",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xe4111ffe1a221e77",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0f3218"
|
||||
},
|
||||
|
||||
"DifficultyTest78" : {
|
||||
"parentTimestamp" : "0x58fbdde9cf69e932",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x58fbdde9cf69ec52",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0eaca8"
|
||||
},
|
||||
|
||||
"DifficultyTest79" : {
|
||||
"parentTimestamp" : "0x31df0c8434db6c39",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x31df0c8434db7021",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0e8688"
|
||||
},
|
||||
|
||||
"DifficultyTest80" : {
|
||||
"parentTimestamp" : "0x378ecfe1c5bb3e82",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x378ecfe1c5bb445e",
|
||||
"currentBlockNumber" : "0x0f4240",
|
||||
"currentDifficulty" : "0x0e8688"
|
||||
},
|
||||
|
||||
"DifficultyTest81" : {
|
||||
"parentTimestamp" : "0x2ffe0da1f356a9f2",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x2ffe0da1f356a9f2",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest82" : {
|
||||
"parentTimestamp" : "0x8b255a942b2ef7f2",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x8b255a942b2ef7f3",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest83" : {
|
||||
"parentTimestamp" : "0x5fa3cf513178591e",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x5fa3cf5131785926",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest84" : {
|
||||
"parentTimestamp" : "0x2efcbca1fd264218",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x2efcbca1fd264222",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest85" : {
|
||||
"parentTimestamp" : "0xda668a1ee9194d4f",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xda668a1ee9194d5c",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest86" : {
|
||||
"parentTimestamp" : "0x06254f4f5554e77d",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x06254f4f5554e791",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest87" : {
|
||||
"parentTimestamp" : "0xe497d437638d7c7b",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0xe497d437638d7cdf",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest88" : {
|
||||
"parentTimestamp" : "0x067b7c8e7cb92467",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x067b7c8e7cb92787",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest89" : {
|
||||
"parentTimestamp" : "0x7719ef4597b0d081",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x7719ef4597b0d469",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest90" : {
|
||||
"parentTimestamp" : "0x77241079da1dcc38",
|
||||
"parentDifficulty" : "0x03e8",
|
||||
"currentTimestamp" : "0x77241079da1dd214",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest91" : {
|
||||
"parentTimestamp" : "0xf2319e01ecab7717",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xf2319e01ecab7717",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest92" : {
|
||||
"parentTimestamp" : "0x1e30bb05c1b97f2c",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x1e30bb05c1b97f2d",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest93" : {
|
||||
"parentTimestamp" : "0x27b8e4db713b828f",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x27b8e4db713b8297",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest94" : {
|
||||
"parentTimestamp" : "0x4fc798e466e7ed3f",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x4fc798e466e7ed49",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest95" : {
|
||||
"parentTimestamp" : "0xa4549ebb868d3b06",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xa4549ebb868d3b13",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest96" : {
|
||||
"parentTimestamp" : "0x96efc49bdc26a9d0",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x96efc49bdc26a9e4",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest97" : {
|
||||
"parentTimestamp" : "0xb5eba7cc46014a8b",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xb5eba7cc46014aef",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest98" : {
|
||||
"parentTimestamp" : "0x34f494405673b322",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0x34f494405673b642",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest99" : {
|
||||
"parentTimestamp" : "0xde7b74262fa64d3f",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xde7b74262fa65127",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest100" : {
|
||||
"parentTimestamp" : "0xa1d20fa3112d7edd",
|
||||
"parentDifficulty" : "0x0800",
|
||||
"currentTimestamp" : "0xa1d20fa3112d84b9",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest101" : {
|
||||
"parentTimestamp" : "0x4ef980793d8b9747",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x4ef980793d8b9747",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest102" : {
|
||||
"parentTimestamp" : "0x0267bcb943169ce6",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x0267bcb943169ce7",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest103" : {
|
||||
"parentTimestamp" : "0x2d7ddedf42efe8a1",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x2d7ddedf42efe8a9",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest104" : {
|
||||
"parentTimestamp" : "0x86ace6fa7dfedc9d",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x86ace6fa7dfedca7",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest105" : {
|
||||
"parentTimestamp" : "0x53a46fa1750decb5",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x53a46fa1750decc2",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest106" : {
|
||||
"parentTimestamp" : "0x6fdf95341726d89f",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x6fdf95341726d8b3",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest107" : {
|
||||
"parentTimestamp" : "0xbb0abfeece58e443",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0xbb0abfeece58e4a7",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest108" : {
|
||||
"parentTimestamp" : "0x0a61ffa297b5ded1",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x0a61ffa297b5e1f1",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest109" : {
|
||||
"parentTimestamp" : "0x4dc725c80fb387d3",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x4dc725c80fb38bbb",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest110" : {
|
||||
"parentTimestamp" : "0x6982ae8ca8945976",
|
||||
"parentDifficulty" : "0x0fa0",
|
||||
"currentTimestamp" : "0x6982ae8ca8945f52",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x020000"
|
||||
},
|
||||
|
||||
"DifficultyTest111" : {
|
||||
"parentTimestamp" : "0x4099dc794e078540",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x4099dc794e078540",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f4628"
|
||||
},
|
||||
|
||||
"DifficultyTest112" : {
|
||||
"parentTimestamp" : "0xc3010eddb53604e7",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xc3010eddb53604e8",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f4628"
|
||||
},
|
||||
|
||||
"DifficultyTest113" : {
|
||||
"parentTimestamp" : "0xed079411411d68ac",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xed079411411d68b4",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f4628"
|
||||
},
|
||||
|
||||
"DifficultyTest114" : {
|
||||
"parentTimestamp" : "0xa0d681826e315aff",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xa0d681826e315b09",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f4440"
|
||||
},
|
||||
|
||||
"DifficultyTest115" : {
|
||||
"parentTimestamp" : "0x3322a1f1f5a3e615",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x3322a1f1f5a3e622",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f4440"
|
||||
},
|
||||
|
||||
"DifficultyTest116" : {
|
||||
"parentTimestamp" : "0x2eedd06f3ab0cb07",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x2eedd06f3ab0cb1b",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f4258"
|
||||
},
|
||||
|
||||
"DifficultyTest117" : {
|
||||
"parentTimestamp" : "0xc4f3e41afadf23ee",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xc4f3e41afadf2452",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0f3318"
|
||||
},
|
||||
|
||||
"DifficultyTest118" : {
|
||||
"parentTimestamp" : "0x1c3e8f5a09d09943",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x1c3e8f5a09d09c63",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0eada8"
|
||||
},
|
||||
|
||||
"DifficultyTest119" : {
|
||||
"parentTimestamp" : "0xc2edac6a92df3deb",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0xc2edac6a92df41d3",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0e8788"
|
||||
},
|
||||
|
||||
"DifficultyTest120" : {
|
||||
"parentTimestamp" : "0x14602c2b947c815f",
|
||||
"parentDifficulty" : "0x0f4240",
|
||||
"currentTimestamp" : "0x14602c2b947c873b",
|
||||
"currentBlockNumber" : "0x10c8e0",
|
||||
"currentDifficulty" : "0x0e8788"
|
||||
}
|
||||
}
|
11042
tests/files/BasicTests/difficultyFrontier.json
Executable file
11042
tests/files/BasicTests/difficultyFrontier.json
Executable file
File diff suppressed because it is too large
Load Diff
11042
tests/files/BasicTests/difficultyHomestead.json
Executable file
11042
tests/files/BasicTests/difficultyHomestead.json
Executable file
File diff suppressed because it is too large
Load Diff
11042
tests/files/BasicTests/difficultyMorden.json
Executable file
11042
tests/files/BasicTests/difficultyMorden.json
Executable file
File diff suppressed because it is too large
Load Diff
11042
tests/files/BasicTests/difficultyOlimpic.json
Executable file
11042
tests/files/BasicTests/difficultyOlimpic.json
Executable file
File diff suppressed because it is too large
Load Diff
0
tests/files/BasicTests/genesishashestest.json
Normal file → Executable file
0
tests/files/BasicTests/genesishashestest.json
Normal file → Executable file
0
tests/files/BasicTests/hexencodetest.json
Normal file → Executable file
0
tests/files/BasicTests/hexencodetest.json
Normal file → Executable file
0
tests/files/BasicTests/keyaddrtest.json
Normal file → Executable file
0
tests/files/BasicTests/keyaddrtest.json
Normal file → Executable file
0
tests/files/BasicTests/txtest.json
Normal file → Executable file
0
tests/files/BasicTests/txtest.json
Normal file → Executable file
318
tests/files/BlockchainTests/Homestead/bcBlockGasLimitTest.json
Executable file
318
tests/files/BlockchainTests/Homestead/bcBlockGasLimitTest.json
Executable file
@ -0,0 +1,318 @@
|
||||
{
|
||||
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideFirst" : {
|
||||
"blocks" : [
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x023ec6",
|
||||
"gasUsed" : "0x021536",
|
||||
"hash" : "83d832062a63a53c9b03e6953f4a5b0443cda569ab86850d275c0bc33be769e5",
|
||||
"mixHash" : "9025d06bb52bb4078d4d8b51589b52fb8021c61efecd75f61110bf2de499139d",
|
||||
"nonce" : "05d99e914ab5efe0",
|
||||
"number" : "0x01",
|
||||
"parentHash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||
"receiptTrie" : "5c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7",
|
||||
"stateRoot" : "a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4",
|
||||
"timestamp" : "0x5694d183",
|
||||
"transactionsTrie" : "70616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"rlp" : "0xf904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec683021536845694d18380a09025d06bb52bb4078d4d8b51589b52fb8021c61efecd75f61110bf2de499139d8805d99e914ab5efe0f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x55f0",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x00",
|
||||
"r" : "0x575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecd",
|
||||
"s" : "0x6baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188",
|
||||
"to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1c",
|
||||
"value" : "0x0a"
|
||||
},
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x5208",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x01",
|
||||
"r" : "0x4fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5b",
|
||||
"s" : "0x17bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192e",
|
||||
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
},
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x5208",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x02",
|
||||
"r" : "0x04377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458ada",
|
||||
"s" : "0x53a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5",
|
||||
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1c",
|
||||
"value" : "0x0a"
|
||||
},
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x5208",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x03",
|
||||
"r" : "0x4fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615",
|
||||
"s" : "0x651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668",
|
||||
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1c",
|
||||
"value" : "0x0a"
|
||||
},
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x5208",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x04",
|
||||
"r" : "0x78e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567d",
|
||||
"s" : "0x13254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198dd",
|
||||
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
},
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x5208",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x05",
|
||||
"r" : "0xa7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54",
|
||||
"s" : "0x534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506",
|
||||
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
},
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x5208",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x06",
|
||||
"r" : "0x34bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59",
|
||||
"s" : "0x78807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616",
|
||||
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
}
|
||||
],
|
||||
"genesisBlockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x42",
|
||||
"gasLimit" : "0x023e38",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"nonce" : "0102030405060708",
|
||||
"number" : "0x00",
|
||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
|
||||
"timestamp" : "0x54c98c81",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||
"lastblockhash" : "83d832062a63a53c9b03e6953f4a5b0443cda569ab86850d275c0bc33be769e5",
|
||||
"postState" : {
|
||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||
"balance" : "0x456391824508d41c",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x4a723dc6b40b8cedf70fa8",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x07",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x3c",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
},
|
||||
"pre" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x4a723dc6b40b8a9a000000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x02540be400",
|
||||
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideLast" : {
|
||||
"blocks" : [
|
||||
{
|
||||
"rlp" : "0xf904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a039b55901ee38a65fa27c7d60137fd431afcf6a7615746ae9501e7cf0ca68bd11a0b19fdedc6b45294e091f08780e0e51b746e43897ab98eaf872d180e0cb157cceb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023dd483021536845694d18580a0494e75b2764c62d62580f1aa75282b7793b9239e93c4912cd960afb3d048391d880725414aab32b4f9f902a7f85f800a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba01117bd549fe17f8383012bf168dabd9e70851fdf2f332e5bfea89318dddd6c77a001364d3a0e23f462052127c53a5473c428e2211806c927601562f840eb6b899cf85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0c40c1300a7cc64b842c9421a6c6e985b5531020d1a26c82f9c6a5200154e91dfa052c28fc6dc0dad9ea23fcce6510a9dc23b9903b1b19a126ac25f77a195b50f83c0"
|
||||
}
|
||||
],
|
||||
"genesisBlockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x42",
|
||||
"gasLimit" : "0x023e38",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"nonce" : "0102030405060708",
|
||||
"number" : "0x00",
|
||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
|
||||
"timestamp" : "0x54c98c81",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||
"lastblockhash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||
"postState" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x4a723dc6b40b8a9a000000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x02540be400",
|
||||
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
},
|
||||
"pre" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x4a723dc6b40b8a9a000000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x02540be400",
|
||||
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"SuicideTransaction" : {
|
||||
"blocks" : [
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x01e8c1",
|
||||
"gasUsed" : "0x2906",
|
||||
"hash" : "3778e5dba074dbf5bb03c680e348d8eb9e7de3e19435fd8fa7a817a153ca2441",
|
||||
"mixHash" : "06dbf306d40cf97ec7236ae195c471428b637e6b797563f0878c4d12cc04f5d3",
|
||||
"nonce" : "0589f996ab61591d",
|
||||
"number" : "0x01",
|
||||
"parentHash" : "926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921d",
|
||||
"receiptTrie" : "bc1ca7335ccb32ac45ecd0ef287eb7f2323801a695f23a3d241e6a2cf0b4a9af",
|
||||
"stateRoot" : "00a62f7cedb73f6ce84dc4e27a983adf20bb45553b11d1bb11b5f18fe450542d",
|
||||
"timestamp" : "0x5694d186",
|
||||
"transactionsTrie" : "f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"rlp" : "0xf90261f901f9a0926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a000a62f7cedb73f6ce84dc4e27a983adf20bb45553b11d1bb11b5f18fe450542da0f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5a0bc1ca7335ccb32ac45ecd0ef287eb7f2323801a695f23a3d241e6a2cf0b4a9afb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018301e8c1822906845694d18680a006dbf306d40cf97ec7236ae195c471428b637e6b797563f0878c4d12cc04f5d3880589f996ab61591df862f860800a830186a094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0444ed2cb67c1cce2c37add4bef48d3dda9ef05e28eaf023006036a4c5f7c96b0a00c56b07bfc50471d458e67923c91108b90cb7bba23f4d373f0a75632a413bd84c0",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x0186a0",
|
||||
"gasPrice" : "0x0a",
|
||||
"nonce" : "0x00",
|
||||
"r" : "0x444ed2cb67c1cce2c37add4bef48d3dda9ef05e28eaf023006036a4c5f7c96b0",
|
||||
"s" : "0x0c56b07bfc50471d458e67923c91108b90cb7bba23f4d373f0a75632a413bd84",
|
||||
"to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
}
|
||||
],
|
||||
"genesisBlockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x42",
|
||||
"gasLimit" : "0x01e848",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921d",
|
||||
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"nonce" : "0102030405060708",
|
||||
"number" : "0x00",
|
||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
|
||||
"timestamp" : "0x54c98c81",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808301e848808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||
"lastblockhash" : "3778e5dba074dbf5bb03c680e348d8eb9e7de3e19435fd8fa7a817a153ca2441",
|
||||
"postState" : {
|
||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||
"balance" : "0x4563918244f59a3c",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x4a723dc6b40b8cee0a49c4",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x01",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
},
|
||||
"pre" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x4a723dc6b40b8a9a000000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x02540be400",
|
||||
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11573
tests/files/BlockchainTests/Homestead/bcForkStressTest.json
Executable file
11573
tests/files/BlockchainTests/Homestead/bcForkStressTest.json
Executable file
File diff suppressed because it is too large
Load Diff
1117
tests/files/BlockchainTests/Homestead/bcGasPricerTest.json
Executable file
1117
tests/files/BlockchainTests/Homestead/bcGasPricerTest.json
Executable file
File diff suppressed because it is too large
Load Diff
1241
tests/files/BlockchainTests/Homestead/bcInvalidHeaderTest.json
Executable file
1241
tests/files/BlockchainTests/Homestead/bcInvalidHeaderTest.json
Executable file
File diff suppressed because it is too large
Load Diff
6077
tests/files/BlockchainTests/Homestead/bcInvalidRLPTest.json
Executable file
6077
tests/files/BlockchainTests/Homestead/bcInvalidRLPTest.json
Executable file
File diff suppressed because it is too large
Load Diff
3528
tests/files/BlockchainTests/Homestead/bcMultiChainTest.json
Executable file
3528
tests/files/BlockchainTests/Homestead/bcMultiChainTest.json
Executable file
File diff suppressed because it is too large
Load Diff
980
tests/files/BlockchainTests/Homestead/bcRPC_API_Test.json
Executable file
980
tests/files/BlockchainTests/Homestead/bcRPC_API_Test.json
Executable file
@ -0,0 +1,980 @@
|
||||
{
|
||||
"RPC_API_Test" : {
|
||||
"blocks" : [
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849",
|
||||
"mixHash" : "0a5fdc6a9fa8bd450e8fbefedc547bf8320d72a0126a1c9d69aaa607dc388164",
|
||||
"nonce" : "026305381c63ddb2",
|
||||
"number" : "0x01",
|
||||
"parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3",
|
||||
"timestamp" : "0x5694cec7",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "1",
|
||||
"rlp" : "0xf901fcf901f7a05a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba80845694cec780a00a5fdc6a9fa8bd450e8fbefedc547bf8320d72a0126a1c9d69aaa607dc38816488026305381c63ddb2c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020040",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "3b990c1ef1649c679cb04fb4d6bfa62ee4e6f7e624213b830c7f0c8b5d015d95",
|
||||
"mixHash" : "62c3c222d88098426c0679e3c799752781e0747d70fe946962bfd328c4b26d42",
|
||||
"nonce" : "10a935fd433b24e0",
|
||||
"number" : "0x02",
|
||||
"parentHash" : "d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "fb7d4dfb0305bcfb620c084d23c4ce7219923eff61b4798eddcd82acc5a6fdd8",
|
||||
"timestamp" : "0x5694cec9",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "2",
|
||||
"rlp" : "0xf901fcf901f7a0d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0fb7d4dfb0305bcfb620c084d23c4ce7219923eff61b4798eddcd82acc5a6fdd8a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefba80845694cec980a062c3c222d88098426c0679e3c799752781e0747d70fe946962bfd328c4b26d428810a935fd433b24e0c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020080",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "c601ecadb63d026a404c5005a64a04fe9f1599b5883afbb2f28e0d5c220f761d",
|
||||
"mixHash" : "355c5410004ececbae3c7c6450cc915fb7a0e621284b6c09814aee50b65288ed",
|
||||
"nonce" : "01014b0076a682bc",
|
||||
"number" : "0x03",
|
||||
"parentHash" : "3b990c1ef1649c679cb04fb4d6bfa62ee4e6f7e624213b830c7f0c8b5d015d95",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "fbce1488c769b9b4d488fee0fbf12d31c7462f7306181b8a34f243e9e6467afc",
|
||||
"timestamp" : "0x5694cecb",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "3",
|
||||
"rlp" : "0xf901fcf901f7a03b990c1ef1649c679cb04fb4d6bfa62ee4e6f7e624213b830c7f0c8b5d015d95a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0fbce1488c769b9b4d488fee0fbf12d31c7462f7306181b8a34f243e9e6467afca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba80845694cecb80a0355c5410004ececbae3c7c6450cc915fb7a0e621284b6c09814aee50b65288ed8801014b0076a682bcc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0200c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "cfdba9cda5ad3d915989eea53ba117c89e9bb38b708031e2c6cf71c14d23137d",
|
||||
"mixHash" : "0e558ea0b40b8ea61580f788352840430edeec448476f4f72b964b617ec1f7f5",
|
||||
"nonce" : "0be7816da0c9b28c",
|
||||
"number" : "0x04",
|
||||
"parentHash" : "c601ecadb63d026a404c5005a64a04fe9f1599b5883afbb2f28e0d5c220f761d",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "80ddf374bfdab21725d9b1d1a3e41eb10a6ff63a6bde6b25d3eabeef441a695d",
|
||||
"timestamp" : "0x5694ced0",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "e629a7a19d168b83485ef47be3b982c448f1026fdc66bb7c0d27cbdbd2c2c3cb"
|
||||
},
|
||||
"blocknumber" : "4",
|
||||
"rlp" : "0xf905f2f901f7a0c601ecadb63d026a404c5005a64a04fe9f1599b5883afbb2f28e0d5c220f761da0e629a7a19d168b83485ef47be3b982c448f1026fdc66bb7c0d27cbdbd2c2c3cb948888f1f195afa192cfee860698584c030f4c9db1a080ddf374bfdab21725d9b1d1a3e41eb10a6ff63a6bde6b25d3eabeef441a695da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200c004832fefba80845694ced080a00e558ea0b40b8ea61580f788352840430edeec448476f4f72b964b617ec1f7f5880be7816da0c9b28cc0f903f4f901f7a0d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a94f5374fce5edbc8e2a8697c15331677e6ebf0ba0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefba80845694cecd80a0713f485592737fe8e2ef5f7284ba9b4fc276e8d0cec9e8f908a6cb41860f18db88e602b15da898a242f901f7a0d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794bcde5374fce5edbc8e2a8697c15331677e6ebf0ba0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefba80845694cecd80a02ffc9c22274cc4cc568074106f37516acdec517aafdd35fd73aa5593c112e9e68868d4dd8ac9e9a895",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
{
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"difficulty" : "0x020040",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "81afb4f55a8d3c5c8b1b27b0300b91aecb1c391cb65c10a2a3fb229fe5fd5004",
|
||||
"mixHash" : "713f485592737fe8e2ef5f7284ba9b4fc276e8d0cec9e8f908a6cb41860f18db",
|
||||
"nonce" : "e602b15da898a242",
|
||||
"number" : "0x02",
|
||||
"parentHash" : "d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3",
|
||||
"timestamp" : "0x5694cecd",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
{
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "bcde5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"difficulty" : "0x020040",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "3040847d4f9e1be6a023e6474101e4abc7b78a9b50b5643883166f84678e8044",
|
||||
"mixHash" : "2ffc9c22274cc4cc568074106f37516acdec517aafdd35fd73aa5593c112e9e6",
|
||||
"nonce" : "68d4dd8ac9e9a895",
|
||||
"number" : "0x02",
|
||||
"parentHash" : "d7d7078871f66d89188d0d6a54e0a1530cb6648c72187ae4f96b317c2d144849",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3",
|
||||
"timestamp" : "0x5694cecd",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020100",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "a8b795c06d2a3670aa44839090bfac2a91f816982e9a9790d4100a1b57223428",
|
||||
"mixHash" : "86a6d4826b26434dd8d7f68fd2d196e0be43ec00e3f197295008c67e0d3802be",
|
||||
"nonce" : "7126208edb08e2c7",
|
||||
"number" : "0x05",
|
||||
"parentHash" : "cfdba9cda5ad3d915989eea53ba117c89e9bb38b708031e2c6cf71c14d23137d",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "280be4452087ccbff8e4b905b635dbdb5f9a703760b7e239d6e346ef03f57b23",
|
||||
"timestamp" : "0x5694ced1",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "5",
|
||||
"rlp" : "0xf901fcf901f7a0cfdba9cda5ad3d915989eea53ba117c89e9bb38b708031e2c6cf71c14d23137da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0280be4452087ccbff8e4b905b635dbdb5f9a703760b7e239d6e346ef03f57b23a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302010005832fefba80845694ced180a086a6d4826b26434dd8d7f68fd2d196e0be43ec00e3f197295008c67e0d3802be887126208edb08e2c7c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020140",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "e64962d0a1a351566da9dfd2f1901de8f1df2fdbd8f6d3ca748279a01ec09687",
|
||||
"mixHash" : "127456b8d3a44800f14f585a8d0d86903e773157c1b84b5149a31955f6be5afb",
|
||||
"nonce" : "5dccbe99363cf06c",
|
||||
"number" : "0x06",
|
||||
"parentHash" : "a8b795c06d2a3670aa44839090bfac2a91f816982e9a9790d4100a1b57223428",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "6f65dc549a9bc5e1c2a7e64a2cbdf735749c055cbbd6cd4c3e840af387cfd99f",
|
||||
"timestamp" : "0x5694ced4",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "6",
|
||||
"rlp" : "0xf901fcf901f7a0a8b795c06d2a3670aa44839090bfac2a91f816982e9a9790d4100a1b57223428a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06f65dc549a9bc5e1c2a7e64a2cbdf735749c055cbbd6cd4c3e840af387cfd99fa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302014006832fefba80845694ced480a0127456b8d3a44800f14f585a8d0d86903e773157c1b84b5149a31955f6be5afb885dccbe99363cf06cc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020180",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "78ce34c7e0ce8a36ee7d4b4a1eaab8d4620db89f43d99eb3873435b3aaac666d",
|
||||
"mixHash" : "cd98ee1f4f60f1c0d135c980764f97551ec8fa726d8a453b4ae2036c666b7725",
|
||||
"nonce" : "7fbaed2e52104c3d",
|
||||
"number" : "0x07",
|
||||
"parentHash" : "e64962d0a1a351566da9dfd2f1901de8f1df2fdbd8f6d3ca748279a01ec09687",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "582f11ddb23b1db1dbc9c2e87eb9fa0152d58f1500bdbcae4654ecfbdd2936ab",
|
||||
"timestamp" : "0x5694ced5",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "7",
|
||||
"rlp" : "0xf901fcf901f7a0e64962d0a1a351566da9dfd2f1901de8f1df2fdbd8f6d3ca748279a01ec09687a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0582f11ddb23b1db1dbc9c2e87eb9fa0152d58f1500bdbcae4654ecfbdd2936aba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302018007832fefba80845694ced580a0cd98ee1f4f60f1c0d135c980764f97551ec8fa726d8a453b4ae2036c666b7725887fbaed2e52104c3dc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0201c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "8e526ec80df1b8a4f54af3f07899e2ce7dc1a5ae1fd02c5b4fc7a7aee72ec7a4",
|
||||
"mixHash" : "cba785be0402b5233f1acc93ae82bde41fc74c5d7a37863e5168d15edd9fdd97",
|
||||
"nonce" : "c1854224e1caab4b",
|
||||
"number" : "0x08",
|
||||
"parentHash" : "78ce34c7e0ce8a36ee7d4b4a1eaab8d4620db89f43d99eb3873435b3aaac666d",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "04426b893a318169565b6266b5a4bdfe7de70f213c31e95f0507b6636fe03ce9",
|
||||
"timestamp" : "0x5694ced7",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "8",
|
||||
"rlp" : "0xf901fcf901f7a078ce34c7e0ce8a36ee7d4b4a1eaab8d4620db89f43d99eb3873435b3aaac666da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a004426b893a318169565b6266b5a4bdfe7de70f213c31e95f0507b6636fe03ce9a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830201c008832fefba80845694ced780a0cba785be0402b5233f1acc93ae82bde41fc74c5d7a37863e5168d15edd9fdd9788c1854224e1caab4bc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020200",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "74d5671496333ed59f30c02247ad3dcf6efe33d91e050d050f8b1ba9fa768596",
|
||||
"mixHash" : "e4cabfee80a4a939798a784304bb040cb44229d3bbbdf69d72d15404a2ed404f",
|
||||
"nonce" : "591347cbfc749730",
|
||||
"number" : "0x09",
|
||||
"parentHash" : "8e526ec80df1b8a4f54af3f07899e2ce7dc1a5ae1fd02c5b4fc7a7aee72ec7a4",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "304928302bb0c889a6e0e7aea96557e7bae4e8b1fbe9b478f81fce330b4953ad",
|
||||
"timestamp" : "0x5694ced9",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "9",
|
||||
"rlp" : "0xf901fcf901f7a08e526ec80df1b8a4f54af3f07899e2ce7dc1a5ae1fd02c5b4fc7a7aee72ec7a4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0304928302bb0c889a6e0e7aea96557e7bae4e8b1fbe9b478f81fce330b4953ada056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302020009832fefba80845694ced980a0e4cabfee80a4a939798a784304bb040cb44229d3bbbdf69d72d15404a2ed404f88591347cbfc749730c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020240",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "cc2fabc0dcfdcfe1c9127f4972eafbb24d018eb3cca1e17df7ebaf2901580ec1",
|
||||
"mixHash" : "f10734da4c4af4355d04fb74e451a3b57240999fdedeb9e90a9ee415c9385c6b",
|
||||
"nonce" : "834ad218301ed285",
|
||||
"number" : "0x0a",
|
||||
"parentHash" : "74d5671496333ed59f30c02247ad3dcf6efe33d91e050d050f8b1ba9fa768596",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "85023bacf4c4846464dc34fbb5e8458bf056c9c4253bb911e15ddaf4a77431ae",
|
||||
"timestamp" : "0x5694cedb",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "10",
|
||||
"rlp" : "0xf901fcf901f7a074d5671496333ed59f30c02247ad3dcf6efe33d91e050d050f8b1ba9fa768596a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a085023bacf4c4846464dc34fbb5e8458bf056c9c4253bb911e15ddaf4a77431aea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202400a832fefba80845694cedb80a0f10734da4c4af4355d04fb74e451a3b57240999fdedeb9e90a9ee415c9385c6b88834ad218301ed285c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020280",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "1c6abe394dae268c761b37ffb8d3c2bf307f07accc6adb98112c3504719e0322",
|
||||
"mixHash" : "f99e82ba4cbad678e4408a0d360a3b21c05a28e5a09e9ecfef875908560eada6",
|
||||
"nonce" : "d324e985205f087b",
|
||||
"number" : "0x0b",
|
||||
"parentHash" : "cc2fabc0dcfdcfe1c9127f4972eafbb24d018eb3cca1e17df7ebaf2901580ec1",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "287ab46129ee55b6e37c89a78354055e2f517847f7c8336db76e126177bd071d",
|
||||
"timestamp" : "0x5694cedd",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "11",
|
||||
"rlp" : "0xf901fcf901f7a0cc2fabc0dcfdcfe1c9127f4972eafbb24d018eb3cca1e17df7ebaf2901580ec1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0287ab46129ee55b6e37c89a78354055e2f517847f7c8336db76e126177bd071da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202800b832fefba80845694cedd80a0f99e82ba4cbad678e4408a0d360a3b21c05a28e5a09e9ecfef875908560eada688d324e985205f087bc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0202c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "8467eac62823344a851fae432afecb065674993002bd83e5c8099b44b87614ee",
|
||||
"mixHash" : "3dd58623c7f56eba39ec1461c42e82acce86b1b66f31db5b0d5772d0d40b16bb",
|
||||
"nonce" : "7e0d9437c3256b25",
|
||||
"number" : "0x0c",
|
||||
"parentHash" : "1c6abe394dae268c761b37ffb8d3c2bf307f07accc6adb98112c3504719e0322",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "84ce2fefe1928ac5b0fc70da8c1db41ec80e1bce9185c9760c50121e53c03b28",
|
||||
"timestamp" : "0x5694cedf",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "12",
|
||||
"rlp" : "0xf901fcf901f7a01c6abe394dae268c761b37ffb8d3c2bf307f07accc6adb98112c3504719e0322a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a084ce2fefe1928ac5b0fc70da8c1db41ec80e1bce9185c9760c50121e53c03b28a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830202c00c832fefba80845694cedf80a03dd58623c7f56eba39ec1461c42e82acce86b1b66f31db5b0d5772d0d40b16bb887e0d9437c3256b25c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020300",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "6fa85108bbc366cca0d5c6b9c3c8aa3a320459643260c7849e34908d201d601f",
|
||||
"mixHash" : "26dd6662b24bca2d2598dc1c7b0b2ff4b3de505ec2cd3d0fbb8e97cf3dde1045",
|
||||
"nonce" : "0153ec522f29e3c9",
|
||||
"number" : "0x0d",
|
||||
"parentHash" : "8467eac62823344a851fae432afecb065674993002bd83e5c8099b44b87614ee",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "4f39cdccb0741643043bd98560afba8b9161a2d4453314e66b322f8cd24a77da",
|
||||
"timestamp" : "0x5694cee1",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "13",
|
||||
"rlp" : "0xf901fcf901f7a08467eac62823344a851fae432afecb065674993002bd83e5c8099b44b87614eea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a04f39cdccb0741643043bd98560afba8b9161a2d4453314e66b322f8cd24a77daa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830203000d832fefba80845694cee180a026dd6662b24bca2d2598dc1c7b0b2ff4b3de505ec2cd3d0fbb8e97cf3dde1045880153ec522f29e3c9c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020340",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "38a6e4b31e035332e558b9c8f377db9ba3c5bbc98aeab0f05c07225984af7772",
|
||||
"mixHash" : "463041cb1f7676044d827959a5b5be717b465b25e0e3da3a148ba6965de3e716",
|
||||
"nonce" : "4fb42304daae5c0c",
|
||||
"number" : "0x0e",
|
||||
"parentHash" : "6fa85108bbc366cca0d5c6b9c3c8aa3a320459643260c7849e34908d201d601f",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "4264a49721e4d462d5f0c66a77f6d6383ac1057475d391062303a60c62515f3d",
|
||||
"timestamp" : "0x5694cee3",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "14",
|
||||
"rlp" : "0xf901fcf901f7a06fa85108bbc366cca0d5c6b9c3c8aa3a320459643260c7849e34908d201d601fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a04264a49721e4d462d5f0c66a77f6d6383ac1057475d391062303a60c62515f3da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830203400e832fefba80845694cee380a0463041cb1f7676044d827959a5b5be717b465b25e0e3da3a148ba6965de3e716884fb42304daae5c0cc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020380",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "fb4f269f49a683b30c1b4efa179f69feda934abe56637672d6dd93d3c231193e",
|
||||
"mixHash" : "d1997d027352dfd02507cdd3b2ed3c5df2a34ad6a7ca84e64ed599e987f35a67",
|
||||
"nonce" : "255e9f3757161afc",
|
||||
"number" : "0x0f",
|
||||
"parentHash" : "38a6e4b31e035332e558b9c8f377db9ba3c5bbc98aeab0f05c07225984af7772",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "be4ce1e004afa8ff0cacbd6d4f297c8db282a287d94bc0dfb5dc1181f2c62ccd",
|
||||
"timestamp" : "0x5694cee5",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "15",
|
||||
"rlp" : "0xf901fcf901f7a038a6e4b31e035332e558b9c8f377db9ba3c5bbc98aeab0f05c07225984af7772a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0be4ce1e004afa8ff0cacbd6d4f297c8db282a287d94bc0dfb5dc1181f2c62ccda056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830203800f832fefba80845694cee580a0d1997d027352dfd02507cdd3b2ed3c5df2a34ad6a7ca84e64ed599e987f35a6788255e9f3757161afcc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0203c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "9b16e29cb0494a301dbfc62e8f120ac2f4cdc95249c60f4cf18fe5b2bb35f44a",
|
||||
"mixHash" : "5ca729dfb24172d85e1a175cb238b9bf52555941af7b9f4140e799091fd3e41f",
|
||||
"nonce" : "86437c1d929d8896",
|
||||
"number" : "0x10",
|
||||
"parentHash" : "fb4f269f49a683b30c1b4efa179f69feda934abe56637672d6dd93d3c231193e",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "9aba3c8170db81e169cb1836995cf9a3c09c2f92795bc34a5b9efa21dd5a6657",
|
||||
"timestamp" : "0x5694cee8",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "16",
|
||||
"rlp" : "0xf901fcf901f7a0fb4f269f49a683b30c1b4efa179f69feda934abe56637672d6dd93d3c231193ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a09aba3c8170db81e169cb1836995cf9a3c09c2f92795bc34a5b9efa21dd5a6657a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830203c010832fefba80845694cee880a05ca729dfb24172d85e1a175cb238b9bf52555941af7b9f4140e799091fd3e41f8886437c1d929d8896c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020400",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "fa58cab8ee77b542aced71ee0bb5cd121012d0e45cbc7772a762a928d1a074ec",
|
||||
"mixHash" : "610abc381ec56a68e9a33ac6d99019b49704d58b00442d29a4020a92ff19962f",
|
||||
"nonce" : "cb82b8f633dc842d",
|
||||
"number" : "0x11",
|
||||
"parentHash" : "9b16e29cb0494a301dbfc62e8f120ac2f4cdc95249c60f4cf18fe5b2bb35f44a",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "8501b93ecb2e0de794bb9b08d3069659e922298188c00e78e6494f82b2d9ab51",
|
||||
"timestamp" : "0x5694ceeb",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "17",
|
||||
"rlp" : "0xf901fcf901f7a09b16e29cb0494a301dbfc62e8f120ac2f4cdc95249c60f4cf18fe5b2bb35f44aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a08501b93ecb2e0de794bb9b08d3069659e922298188c00e78e6494f82b2d9ab51a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302040011832fefba80845694ceeb80a0610abc381ec56a68e9a33ac6d99019b49704d58b00442d29a4020a92ff19962f88cb82b8f633dc842dc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020440",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "2b49deb3cea3960bc657aae76bc6483f72002d200c308e9691d24e4dc15b0ba8",
|
||||
"mixHash" : "5e9eaa09083defc0304fcc858f4cbc903eec0354f67eeed47662e28a23730af7",
|
||||
"nonce" : "0340be1967329920",
|
||||
"number" : "0x12",
|
||||
"parentHash" : "fa58cab8ee77b542aced71ee0bb5cd121012d0e45cbc7772a762a928d1a074ec",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "ba14fa7ed4e437d13b204ecea5bcad30774db209e4b151dc11052474c02643d6",
|
||||
"timestamp" : "0x5694ceed",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "18",
|
||||
"rlp" : "0xf901fcf901f7a0fa58cab8ee77b542aced71ee0bb5cd121012d0e45cbc7772a762a928d1a074eca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ba14fa7ed4e437d13b204ecea5bcad30774db209e4b151dc11052474c02643d6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302044012832fefba80845694ceed80a05e9eaa09083defc0304fcc858f4cbc903eec0354f67eeed47662e28a23730af7880340be1967329920c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020480",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "55e34f4e08a37def4b7604862b634aa75a0eb1630e896681f031044c9797593e",
|
||||
"mixHash" : "aeaaebb0303d884b6289acbc05b2446178e3104f8a07df7be89d389ced28e05e",
|
||||
"nonce" : "454a4a62f2a0788f",
|
||||
"number" : "0x13",
|
||||
"parentHash" : "2b49deb3cea3960bc657aae76bc6483f72002d200c308e9691d24e4dc15b0ba8",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "448607c16f83d70420ed890b98d76954bff7abb2db70c2e789a8a72a3bddbceb",
|
||||
"timestamp" : "0x5694ceef",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "19",
|
||||
"rlp" : "0xf901fcf901f7a02b49deb3cea3960bc657aae76bc6483f72002d200c308e9691d24e4dc15b0ba8a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0448607c16f83d70420ed890b98d76954bff7abb2db70c2e789a8a72a3bddbceba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302048013832fefba80845694ceef80a0aeaaebb0303d884b6289acbc05b2446178e3104f8a07df7be89d389ced28e05e88454a4a62f2a0788fc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0204c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "287c6bed0b3a2dd4cdc9f1c09041351e75137e395cf4e9c752b0d576b41a7c2e",
|
||||
"mixHash" : "25d0f94d293187bcb8725fdef9da78b1125af2fd34891ea7e80e3234b0302b47",
|
||||
"nonce" : "9bd19ed3d548a315",
|
||||
"number" : "0x14",
|
||||
"parentHash" : "55e34f4e08a37def4b7604862b634aa75a0eb1630e896681f031044c9797593e",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "a793808a844879a28730ba95684e2eb092a7ebca8eac8ee1ffb8cb864053d25c",
|
||||
"timestamp" : "0x5694cef1",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "20",
|
||||
"rlp" : "0xf901fcf901f7a055e34f4e08a37def4b7604862b634aa75a0eb1630e896681f031044c9797593ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a793808a844879a28730ba95684e2eb092a7ebca8eac8ee1ffb8cb864053d25ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830204c014832fefba80845694cef180a025d0f94d293187bcb8725fdef9da78b1125af2fd34891ea7e80e3234b0302b47889bd19ed3d548a315c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020500",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "f04117f8a5fcba5cb995cef619e891683600db67200405d50e5a245dc6088832",
|
||||
"mixHash" : "fd2cf23dab2202c116d56a49c3f1a72e408ce3b17a1e77c45c56f7ae45257f78",
|
||||
"nonce" : "19d620a2fd489695",
|
||||
"number" : "0x15",
|
||||
"parentHash" : "287c6bed0b3a2dd4cdc9f1c09041351e75137e395cf4e9c752b0d576b41a7c2e",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "39af72e94b369e2c85df5dc3ee055e630b65eb070aae54750299468c16111228",
|
||||
"timestamp" : "0x5694cef2",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "21",
|
||||
"rlp" : "0xf901fcf901f7a0287c6bed0b3a2dd4cdc9f1c09041351e75137e395cf4e9c752b0d576b41a7c2ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a039af72e94b369e2c85df5dc3ee055e630b65eb070aae54750299468c16111228a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302050015832fefba80845694cef280a0fd2cf23dab2202c116d56a49c3f1a72e408ce3b17a1e77c45c56f7ae45257f788819d620a2fd489695c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020540",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "ec4029abff5a78e9c4439404644c55059b631233ca3ecb6f4c7d25cd713c42ab",
|
||||
"mixHash" : "5f1cdfd0d23e22a33f1ae32dc8ec0c4dcc9e414345766d85dacc35ebb52228fa",
|
||||
"nonce" : "0fa74894972367a6",
|
||||
"number" : "0x16",
|
||||
"parentHash" : "f04117f8a5fcba5cb995cef619e891683600db67200405d50e5a245dc6088832",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "5671e43f59dba32b649d96c2b10e1eb971d8720f23c871126952d1411155a6e5",
|
||||
"timestamp" : "0x5694cef4",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "22",
|
||||
"rlp" : "0xf901fcf901f7a0f04117f8a5fcba5cb995cef619e891683600db67200405d50e5a245dc6088832a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05671e43f59dba32b649d96c2b10e1eb971d8720f23c871126952d1411155a6e5a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302054016832fefba80845694cef480a05f1cdfd0d23e22a33f1ae32dc8ec0c4dcc9e414345766d85dacc35ebb52228fa880fa74894972367a6c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020580",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "4cac7f691835d4a198a16a2554218fb40bc9511f6fe34a229fb4d7ec4f17dc92",
|
||||
"mixHash" : "ea76921a431d1256c4098ab071671ce831e2ef0f477f491486f71e4948f02d40",
|
||||
"nonce" : "34150404f3d4c1ec",
|
||||
"number" : "0x17",
|
||||
"parentHash" : "ec4029abff5a78e9c4439404644c55059b631233ca3ecb6f4c7d25cd713c42ab",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "f832cf3e6255aa35f6d60bdc45d4e722976b5fb6600f10db8973424b7f0c5081",
|
||||
"timestamp" : "0x5694cef7",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "23",
|
||||
"rlp" : "0xf901fcf901f7a0ec4029abff5a78e9c4439404644c55059b631233ca3ecb6f4c7d25cd713c42aba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0f832cf3e6255aa35f6d60bdc45d4e722976b5fb6600f10db8973424b7f0c5081a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302058017832fefba80845694cef780a0ea76921a431d1256c4098ab071671ce831e2ef0f477f491486f71e4948f02d408834150404f3d4c1ecc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0205c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "165d227300ae401deef187eb6664f4c5eb2a02c15e55b20d0166375c2aa84450",
|
||||
"mixHash" : "16e432c33d29f7781f52c624b78a8de024e1d52f24bded4026f3b53ac745f5c8",
|
||||
"nonce" : "cafc498a79e61cce",
|
||||
"number" : "0x18",
|
||||
"parentHash" : "4cac7f691835d4a198a16a2554218fb40bc9511f6fe34a229fb4d7ec4f17dc92",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "2529b8bbaeebaf2d34e9e979f2a6187fb6582f88ead0e5266820e537cbd6955a",
|
||||
"timestamp" : "0x5694cef9",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "24",
|
||||
"rlp" : "0xf901fcf901f7a04cac7f691835d4a198a16a2554218fb40bc9511f6fe34a229fb4d7ec4f17dc92a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a02529b8bbaeebaf2d34e9e979f2a6187fb6582f88ead0e5266820e537cbd6955aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830205c018832fefba80845694cef980a016e432c33d29f7781f52c624b78a8de024e1d52f24bded4026f3b53ac745f5c888cafc498a79e61ccec0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020600",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "8003d019484f91791a0b6c8c585589a7045fe16c0c0b82afa4297e1ed94a1a7a",
|
||||
"mixHash" : "af53d921af86f800131e2183eb58f06e905ab95fe7e9b8832f79325b1f599b7b",
|
||||
"nonce" : "d8d2f0e92651822b",
|
||||
"number" : "0x19",
|
||||
"parentHash" : "165d227300ae401deef187eb6664f4c5eb2a02c15e55b20d0166375c2aa84450",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "ea24f5a8b9c321b8fbc5d940272d3d2e1c5846be0113e415fe38243c3cbd5806",
|
||||
"timestamp" : "0x5694cefb",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "25",
|
||||
"rlp" : "0xf901fcf901f7a0165d227300ae401deef187eb6664f4c5eb2a02c15e55b20d0166375c2aa84450a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ea24f5a8b9c321b8fbc5d940272d3d2e1c5846be0113e415fe38243c3cbd5806a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302060019832fefba80845694cefb80a0af53d921af86f800131e2183eb58f06e905ab95fe7e9b8832f79325b1f599b7b88d8d2f0e92651822bc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020640",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "a509f8e4295262949d41283d8271a6980e1ae0328c2097aa37355c29d3577395",
|
||||
"mixHash" : "49f4a228a8d2281446a4e7f65c5190d2f092f7f280951bf9592cb4c4d4b02002",
|
||||
"nonce" : "e6f095e50bff794f",
|
||||
"number" : "0x1a",
|
||||
"parentHash" : "8003d019484f91791a0b6c8c585589a7045fe16c0c0b82afa4297e1ed94a1a7a",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "c7f97d70e35d5f97e42e9871b9f17b67ca32d22f2237c5f063b0eb5284804bc0",
|
||||
"timestamp" : "0x5694cefe",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "26",
|
||||
"rlp" : "0xf901fcf901f7a08003d019484f91791a0b6c8c585589a7045fe16c0c0b82afa4297e1ed94a1a7aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c7f97d70e35d5f97e42e9871b9f17b67ca32d22f2237c5f063b0eb5284804bc0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830206401a832fefba80845694cefe80a049f4a228a8d2281446a4e7f65c5190d2f092f7f280951bf9592cb4c4d4b0200288e6f095e50bff794fc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020680",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "903f7866107b3f5de4bf0de0efdee78e1bf414dcb2e8849feb1e5ae14186cedb",
|
||||
"mixHash" : "506a6c7a6ee37afdb1e39af6261970374c8bfcbec6b66b1456e1a52a06218aba",
|
||||
"nonce" : "01e485483aa488a9",
|
||||
"number" : "0x1b",
|
||||
"parentHash" : "a509f8e4295262949d41283d8271a6980e1ae0328c2097aa37355c29d3577395",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "83c43fa4376e86910255317c6d87f8dacc530c120467a51877e1357a1a6fcfb1",
|
||||
"timestamp" : "0x5694cf00",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "27",
|
||||
"reverted" : true,
|
||||
"rlp" : "0xf901fcf901f7a0a509f8e4295262949d41283d8271a6980e1ae0328c2097aa37355c29d3577395a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a083c43fa4376e86910255317c6d87f8dacc530c120467a51877e1357a1a6fcfb1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830206801b832fefba80845694cf0080a0506a6c7a6ee37afdb1e39af6261970374c8bfcbec6b66b1456e1a52a06218aba8801e485483aa488a9c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0206c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "e7d1cfbb80c9a93270a747ada12055bddd66f0164cb83caaa934db4159825c63",
|
||||
"mixHash" : "249fac4ab46fd475e646821b83cd08128bab8fe67b7c5bbe44803495cdaf2492",
|
||||
"nonce" : "815179ad456dacf1",
|
||||
"number" : "0x1c",
|
||||
"parentHash" : "903f7866107b3f5de4bf0de0efdee78e1bf414dcb2e8849feb1e5ae14186cedb",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "ec0c85450315e9370c91f079d831f79cea5bc9c5d918265f1e95d30aeee48ce7",
|
||||
"timestamp" : "0x5694cf02",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "28",
|
||||
"reverted" : true,
|
||||
"rlp" : "0xf901fcf901f7a0903f7866107b3f5de4bf0de0efdee78e1bf414dcb2e8849feb1e5ae14186cedba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ec0c85450315e9370c91f079d831f79cea5bc9c5d918265f1e95d30aeee48ce7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830206c01c832fefba80845694cf0280a0249fac4ab46fd475e646821b83cd08128bab8fe67b7c5bbe44803495cdaf249288815179ad456dacf1c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020680",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "559a2996a0f96eb0ccd760000473d172f39edd471ac41c97dcae0483908f69c3",
|
||||
"mixHash" : "8e70e0f2c6015a72fe07d2fa16caf292f8540aa50dba619a3a15f24d68e28055",
|
||||
"nonce" : "bae9bbe39bd058f2",
|
||||
"number" : "0x1b",
|
||||
"parentHash" : "a509f8e4295262949d41283d8271a6980e1ae0328c2097aa37355c29d3577395",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "83c43fa4376e86910255317c6d87f8dacc530c120467a51877e1357a1a6fcfb1",
|
||||
"timestamp" : "0x5694cf05",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "27",
|
||||
"rlp" : "0xf901fcf901f7a0a509f8e4295262949d41283d8271a6980e1ae0328c2097aa37355c29d3577395a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a083c43fa4376e86910255317c6d87f8dacc530c120467a51877e1357a1a6fcfb1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830206801b832fefba80845694cf0580a08e70e0f2c6015a72fe07d2fa16caf292f8540aa50dba619a3a15f24d68e2805588bae9bbe39bd058f2c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0206c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "97a2b1dbb7d9398a84413577635d680ad226ae6b26d774be7d53f131cffd69bd",
|
||||
"mixHash" : "c9f8b68b4f02f61a0f81841574d36c454fded1547edaaebf703fdcb1078fff31",
|
||||
"nonce" : "0dfbaa1eef8c44fa",
|
||||
"number" : "0x1c",
|
||||
"parentHash" : "559a2996a0f96eb0ccd760000473d172f39edd471ac41c97dcae0483908f69c3",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "ec0c85450315e9370c91f079d831f79cea5bc9c5d918265f1e95d30aeee48ce7",
|
||||
"timestamp" : "0x5694cf08",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "28",
|
||||
"rlp" : "0xf901fcf901f7a0559a2996a0f96eb0ccd760000473d172f39edd471ac41c97dcae0483908f69c3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ec0c85450315e9370c91f079d831f79cea5bc9c5d918265f1e95d30aeee48ce7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830206c01c832fefba80845694cf0880a0c9f8b68b4f02f61a0f81841574d36c454fded1547edaaebf703fdcb1078fff31880dfbaa1eef8c44fac0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020700",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "f01f67742c67a9ba82dc9dbaae9d3750fd052841b6f99b9e646331e5bdb9361f",
|
||||
"mixHash" : "798c11b2d81581f622d1300bc1ad6c3f472c57b899f9d944c886ea34679add4e",
|
||||
"nonce" : "33c635ca4fa27fbf",
|
||||
"number" : "0x1d",
|
||||
"parentHash" : "97a2b1dbb7d9398a84413577635d680ad226ae6b26d774be7d53f131cffd69bd",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "95e6693ccd8bba0cd5b48eaaff8fdefdca2f8d254a28dcae52e6aeda323a04a7",
|
||||
"timestamp" : "0x5694cf0a",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "29",
|
||||
"rlp" : "0xf901fcf901f7a097a2b1dbb7d9398a84413577635d680ad226ae6b26d774be7d53f131cffd69bda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a095e6693ccd8bba0cd5b48eaaff8fdefdca2f8d254a28dcae52e6aeda323a04a7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830207001d832fefba80845694cf0a80a0798c11b2d81581f622d1300bc1ad6c3f472c57b899f9d944c886ea34679add4e8833c635ca4fa27fbfc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020740",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "ea2d150f9c67c215a11aefaedb25528cf6a5870254409181c1b0e65cbaa122e7",
|
||||
"mixHash" : "e6737451d2836a1a5dbb8f8fc2eb8dda3a9d15b298746d8a5228053951b21db1",
|
||||
"nonce" : "41b6feffcbb04286",
|
||||
"number" : "0x1e",
|
||||
"parentHash" : "f01f67742c67a9ba82dc9dbaae9d3750fd052841b6f99b9e646331e5bdb9361f",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "4e0afe8a13c6eb4d600b3b50e9cdcfc097209dcd2d66b4a0a7fba02ec4d8dceb",
|
||||
"timestamp" : "0x5694cf0d",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "30",
|
||||
"rlp" : "0xf901fcf901f7a0f01f67742c67a9ba82dc9dbaae9d3750fd052841b6f99b9e646331e5bdb9361fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a04e0afe8a13c6eb4d600b3b50e9cdcfc097209dcd2d66b4a0a7fba02ec4d8dceba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830207401e832fefba80845694cf0d80a0e6737451d2836a1a5dbb8f8fc2eb8dda3a9d15b298746d8a5228053951b21db18841b6feffcbb04286c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020780",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "4bf016f65e4dc6a3da6473b412fe30f2c9c18816912b4dd20a4d013b876ac033",
|
||||
"mixHash" : "3a3edf0dfa3ea1115f09c763f035138c1a5f5be85adf920954ac6cb3e1c355b7",
|
||||
"nonce" : "bd0dda9df06ead43",
|
||||
"number" : "0x1f",
|
||||
"parentHash" : "ea2d150f9c67c215a11aefaedb25528cf6a5870254409181c1b0e65cbaa122e7",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "8f045ded5ca49298d6f98c86380a8ec45cc3274bc6d42ca7f34e6d9ddcb5a10b",
|
||||
"timestamp" : "0x5694cf0f",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "31",
|
||||
"rlp" : "0xf901fcf901f7a0ea2d150f9c67c215a11aefaedb25528cf6a5870254409181c1b0e65cbaa122e7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a08f045ded5ca49298d6f98c86380a8ec45cc3274bc6d42ca7f34e6d9ddcb5a10ba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830207801f832fefba80845694cf0f80a03a3edf0dfa3ea1115f09c763f035138c1a5f5be85adf920954ac6cb3e1c355b788bd0dda9df06ead43c0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x0207c0",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefba",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "30ea29dfc3962e8d206405d493cf39365c19e4cdfb0b3ee6bf4220985c15407f",
|
||||
"mixHash" : "59e690bbe774ae4f8a312683d895cc57d38b8878d5854a30c8089c3f42719bd3",
|
||||
"nonce" : "88e7ede1d41faaac",
|
||||
"number" : "0x20",
|
||||
"parentHash" : "4bf016f65e4dc6a3da6473b412fe30f2c9c18816912b4dd20a4d013b876ac033",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "c895a2c5accfc1ddfdc668b59b2654940473b950b3133aeaa7a301512ae0c381",
|
||||
"timestamp" : "0x5694cf12",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"blocknumber" : "32",
|
||||
"rlp" : "0xf901fcf901f7a04bf016f65e4dc6a3da6473b412fe30f2c9c18816912b4dd20a4d013b876ac033a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c895a2c5accfc1ddfdc668b59b2654940473b950b3133aeaa7a301512ae0c381a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830207c020832fefba80845694cf1280a059e690bbe774ae4f8a312683d895cc57d38b8878d5854a30c8089c3f42719bd38888e7ede1d41faaacc0c0",
|
||||
"transactions" : [
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
}
|
||||
],
|
||||
"genesisBlockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x42",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae",
|
||||
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"nonce" : "0102030405060708",
|
||||
"number" : "0x00",
|
||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "7dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1",
|
||||
"timestamp" : "0x54c98c81",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||
"lastblockhash" : "30ea29dfc3962e8d206405d493cf39365c19e4cdfb0b3ee6bf4220985c15407f",
|
||||
"postState" : {
|
||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||
"balance" : "0x08b0c86960c2cf4000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x340ab63a0229a000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"bcde5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x340aad21b3b70000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
},
|
||||
"pre" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x09184e72a000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1145
tests/files/BlockchainTests/Homestead/bcStateTest.json
Executable file
1145
tests/files/BlockchainTests/Homestead/bcStateTest.json
Executable file
File diff suppressed because it is too large
Load Diff
5468
tests/files/BlockchainTests/Homestead/bcTotalDifficultyTest.json
Executable file
5468
tests/files/BlockchainTests/Homestead/bcTotalDifficultyTest.json
Executable file
File diff suppressed because it is too large
Load Diff
2116
tests/files/BlockchainTests/Homestead/bcUncleHeaderValiditiy.json
Executable file
2116
tests/files/BlockchainTests/Homestead/bcUncleHeaderValiditiy.json
Executable file
File diff suppressed because it is too large
Load Diff
4514
tests/files/BlockchainTests/Homestead/bcUncleTest.json
Executable file
4514
tests/files/BlockchainTests/Homestead/bcUncleTest.json
Executable file
File diff suppressed because it is too large
Load Diff
1902
tests/files/BlockchainTests/Homestead/bcValidBlockTest.json
Executable file
1902
tests/files/BlockchainTests/Homestead/bcValidBlockTest.json
Executable file
File diff suppressed because it is too large
Load Diff
10915
tests/files/BlockchainTests/Homestead/bcWalletTest.json
Executable file
10915
tests/files/BlockchainTests/Homestead/bcWalletTest.json
Executable file
File diff suppressed because one or more lines are too long
0
tests/files/BlockchainTests/RandomTests/bl10251623GO.json
Normal file → Executable file
0
tests/files/BlockchainTests/RandomTests/bl10251623GO.json
Normal file → Executable file
0
tests/files/BlockchainTests/RandomTests/bl201507071825GO.json
Normal file → Executable file
0
tests/files/BlockchainTests/RandomTests/bl201507071825GO.json
Normal file → Executable file
2200
tests/files/BlockchainTests/TestNetwork/bcSimpleTransitionTest.json
Executable file
2200
tests/files/BlockchainTests/TestNetwork/bcSimpleTransitionTest.json
Executable file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user