Compare commits
31 Commits
master
...
release/1.
Author | SHA1 | Date | |
---|---|---|---|
|
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,10 +20,6 @@ env:
|
|||||||
global:
|
global:
|
||||||
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
|
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
|
||||||
sudo: false
|
sudo: false
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libgmp3-dev
|
|
||||||
notifications:
|
notifications:
|
||||||
webhooks:
|
webhooks:
|
||||||
urls:
|
urls:
|
||||||
|
68
Makefile
68
Makefile
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
GOBIN = build/bin
|
GOBIN = build/bin
|
||||||
|
|
||||||
CROSSDEPS = https://gmplib.org/download/gmp/gmp-6.0.0a.tar.bz2
|
MODE ?= default
|
||||||
GO ?= latest
|
GO ?= latest
|
||||||
|
|
||||||
geth:
|
geth:
|
||||||
@ -26,32 +26,51 @@ geth-linux: xgo geth-linux-arm geth-linux-386 geth-linux-amd64
|
|||||||
@echo "Linux cross compilation done:"
|
@echo "Linux cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-linux-*
|
@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
|
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:"
|
@echo "Linux 386 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-linux-* | grep 386
|
@ls -l $(GOBIN)/geth-linux-* | grep 386
|
||||||
|
|
||||||
geth-linux-amd64: xgo
|
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:"
|
@echo "Linux amd64 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-linux-* | grep amd64
|
@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:"
|
@echo "Darwin cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-darwin-*
|
@ls -l $(GOBIN)/geth-darwin-*
|
||||||
|
|
||||||
geth-darwin-386: xgo
|
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:"
|
@echo "Darwin 386 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-darwin-* | grep 386
|
@ls -l $(GOBIN)/geth-darwin-* | grep 386
|
||||||
|
|
||||||
geth-darwin-amd64: xgo
|
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:"
|
@echo "Darwin amd64 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-darwin-* | grep amd64
|
@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-*
|
@ls -l $(GOBIN)/geth-windows-*
|
||||||
|
|
||||||
geth-windows-386: xgo
|
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:"
|
@echo "Windows 386 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-windows-* | grep 386
|
@ls -l $(GOBIN)/geth-windows-* | grep 386
|
||||||
|
|
||||||
geth-windows-amd64: xgo
|
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:"
|
@echo "Windows amd64 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-windows-* | grep amd64
|
@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:"
|
@echo "Android cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-android-*
|
@ls -l $(GOBIN)/geth-android-*
|
||||||
|
|
||||||
geth-android-16: xgo
|
geth-ios: geth-ios-arm-7 geth-ios-arm64
|
||||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android-16/* -v $(shell build/flags.sh) ./cmd/geth
|
@echo "iOS cross compilation done:"
|
||||||
@echo "Android 16 cross compilation done:"
|
@ls -l $(GOBIN)/geth-ios-*
|
||||||
@ls -l $(GOBIN)/geth-android-16-*
|
|
||||||
|
|
||||||
geth-android-21: xgo
|
geth-ios-arm-7: xgo
|
||||||
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android-21/* -v $(shell build/flags.sh) ./cmd/geth
|
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=ios/arm-7 -v $(shell build/flags.sh) ./cmd/geth
|
||||||
@echo "Android 21 cross compilation done:"
|
@echo "iOS ARMv7 cross compilation done:"
|
||||||
@ls -l $(GOBIN)/geth-android-21-*
|
@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:
|
evm:
|
||||||
build/env.sh $(GOROOT)/bin/go install -v $(shell build/flags.sh) ./cmd/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)
|
[Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum)
|
||||||
on the wiki.
|
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.
|
You can install them using your favourite package manager.
|
||||||
Once the dependencies are installed, run
|
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
|
self.Gas = gas
|
||||||
return core.Call(self, caller, addr, data, gas, price, value)
|
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) {
|
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)
|
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) {
|
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)
|
return core.Create(self, caller, data, gas, price, value)
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,10 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "Geth"
|
ClientIdentifier = "Geth"
|
||||||
Version = "1.4.0-unstable"
|
Version = "1.3.5"
|
||||||
VersionMajor = 1
|
VersionMajor = 1
|
||||||
VersionMinor = 4
|
VersionMinor = 3
|
||||||
VersionPatch = 0
|
VersionPatch = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -183,7 +183,7 @@ var (
|
|||||||
GasPriceFlag = cli.StringFlag{
|
GasPriceFlag = cli.StringFlag{
|
||||||
Name: "gasprice",
|
Name: "gasprice",
|
||||||
Usage: "Minimal gas price to accept for mining a transactions",
|
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{
|
ExtraDataFlag = cli.StringFlag{
|
||||||
Name: "extradata",
|
Name: "extradata",
|
||||||
@ -356,7 +356,7 @@ var (
|
|||||||
GpoMinGasPriceFlag = cli.StringFlag{
|
GpoMinGasPriceFlag = cli.StringFlag{
|
||||||
Name: "gpomin",
|
Name: "gpomin",
|
||||||
Usage: "Minimum suggested gas price",
|
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{
|
GpoMaxGasPriceFlag = cli.StringFlag{
|
||||||
Name: "gpomax",
|
Name: "gpomax",
|
||||||
@ -472,6 +472,8 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
|||||||
cfg.DataDir += "/testnet"
|
cfg.DataDir += "/testnet"
|
||||||
cfg.NetworkId = 2
|
cfg.NetworkId = 2
|
||||||
cfg.TestNet = true
|
cfg.TestNet = true
|
||||||
|
// overwrite homestead block
|
||||||
|
params.HomesteadBlock = params.TestNetHomesteadBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.GlobalBool(VMEnableJitFlag.Name) {
|
if ctx.GlobalBool(VMEnableJitFlag.Name) {
|
||||||
|
@ -82,7 +82,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
|||||||
return func(i int, gen *BlockGen) {
|
return func(i int, gen *BlockGen) {
|
||||||
toaddr := common.Address{}
|
toaddr := common.Address{}
|
||||||
data := make([]byte, nbytes)
|
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)
|
tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(benchRootKey)
|
||||||
gen.AddTx(tx)
|
gen.AddTx(tx)
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,12 @@ import (
|
|||||||
"gopkg.in/fatih/set.v0"
|
"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
|
// BlockValidator is responsible for validating block headers, uncles and
|
||||||
// processed state.
|
// 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.
|
// For valid blocks this should always validate to true.
|
||||||
rbloom := types.CreateBloom(receipts)
|
rbloom := types.CreateBloom(receipts)
|
||||||
if rbloom != header.Bloom {
|
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]]))
|
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
|
||||||
receiptSha := types.DeriveSha(receipts)
|
receiptSha := types.DeriveSha(receipts)
|
||||||
@ -241,3 +247,127 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
|
|||||||
}
|
}
|
||||||
return nil
|
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
|
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.
|
// GetBlock retrieves a block from the database by hash, caching it if found.
|
||||||
func (self *BlockChain) GetBlock(hash common.Hash) *types.Block {
|
func (self *BlockChain) GetBlock(hash common.Hash) *types.Block {
|
||||||
// Short circuit if the block's already in the cache, retrieve otherwise
|
// 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 {
|
if ptd == nil {
|
||||||
return ParentError(header.ParentHash)
|
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
|
// Make sure no inconsistent state is leaked during insertion
|
||||||
self.mu.Lock()
|
self.mu.Lock()
|
||||||
defer self.mu.Unlock()
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
// If the total difficulty is higher than our known, add it to the canonical chain
|
// 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
|
// Delete any canonical number assignments above the new head
|
||||||
for i := header.Number.Uint64() + 1; GetCanonicalHash(self.chainDb, i) != (common.Hash{}); i++ {
|
for i := header.Number.Uint64() + 1; GetCanonicalHash(self.chainDb, i) != (common.Hash{}); i++ {
|
||||||
DeleteCanonicalHash(self.chainDb, i)
|
DeleteCanonicalHash(self.chainDb, i)
|
||||||
@ -744,7 +761,7 @@ func (self *BlockChain) writeHeader(header *types.Header) error {
|
|||||||
self.currentHeader = types.CopyHeader(header)
|
self.currentHeader = types.CopyHeader(header)
|
||||||
}
|
}
|
||||||
// Irrelevant of the canonical status, write the header itself to the database
|
// 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)
|
glog.Fatalf("failed to write header total difficulty: %v", err)
|
||||||
}
|
}
|
||||||
if err := WriteHeader(self.chainDb, header); err != nil {
|
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 {
|
if ptd == nil {
|
||||||
return NonStatTy, ParentError(block.ParentHash())
|
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
|
// Make sure no inconsistent state is leaked during insertion
|
||||||
self.mu.Lock()
|
self.mu.Lock()
|
||||||
defer self.mu.Unlock()
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
// If the total difficulty is higher than our known, add it to the canonical chain
|
// 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
|
// Reorganize the chain if the parent is not the head block
|
||||||
if block.ParentHash() != self.currentBlock.Hash() {
|
if block.ParentHash() != self.currentBlock.Hash() {
|
||||||
if err := self.reorg(self.currentBlock, block); err != nil {
|
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
|
status = SideStatTy
|
||||||
}
|
}
|
||||||
// Irrelevant of the canonical status, write the block itself to the database
|
// 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)
|
glog.Fatalf("failed to write block total difficulty: %v", err)
|
||||||
}
|
}
|
||||||
if err := WriteBlock(self.chainDb, block); err != nil {
|
if err := WriteBlock(self.chainDb, block); err != nil {
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,77 +49,9 @@ var (
|
|||||||
mipmapPre = []byte("mipmap-log-bloom-")
|
mipmapPre = []byte("mipmap-log-bloom-")
|
||||||
MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
|
MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
|
||||||
|
|
||||||
ExpDiffPeriod = big.NewInt(100000)
|
|
||||||
blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
|
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.
|
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
|
||||||
func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
|
func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
|
||||||
data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))
|
data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))
|
||||||
|
@ -62,7 +62,7 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDifficulty(t *testing.T) {
|
func TestDifficultyFrontier(t *testing.T) {
|
||||||
file, err := os.Open("../tests/files/BasicTests/difficulty.json")
|
file, err := os.Open("../tests/files/BasicTests/difficulty.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -77,7 +77,7 @@ func TestDifficulty(t *testing.T) {
|
|||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
|
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 {
|
if diff.Cmp(test.CurrentDifficulty) != 0 {
|
||||||
t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
|
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
|
// 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) {
|
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()
|
callerAddr := caller.Address()
|
||||||
ret, _, err = exec(env, caller, &prev, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
|
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
|
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) {
|
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)
|
evm := vm.NewVm(env)
|
||||||
|
|
||||||
// Depth check execution. Fail if we're trying to execute above the
|
// Depth check execution. Fail if we're trying to execute above the
|
||||||
// limit.
|
// limit.
|
||||||
if env.Depth() > int(params.CallCreateDepth.Int64()) {
|
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
|
var createAccount bool
|
||||||
if address == nil {
|
if address == nil {
|
||||||
// Generate a new address
|
// Create a new account on the state
|
||||||
nonce := env.Db().GetNonce(caller.Address())
|
nonce := env.Db().GetNonce(caller.Address())
|
||||||
env.Db().SetNonce(caller.Address(), nonce+1)
|
env.Db().SetNonce(caller.Address(), nonce+1)
|
||||||
|
|
||||||
addr = crypto.CreateAddress(caller.Address(), nonce)
|
addr = crypto.CreateAddress(caller.Address(), nonce)
|
||||||
|
|
||||||
address = &addr
|
address = &addr
|
||||||
createAccount = true
|
createAccount = true
|
||||||
}
|
}
|
||||||
snapshot := env.MakeSnapshot()
|
|
||||||
|
|
||||||
|
snapshotPreTransfer := env.MakeSnapshot()
|
||||||
var (
|
var (
|
||||||
from = env.Db().GetAccount(caller.Address())
|
from = env.Db().GetAccount(caller.Address())
|
||||||
to vm.Account
|
to vm.Account
|
||||||
@ -95,12 +101,68 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
|
|||||||
}
|
}
|
||||||
env.Transfer(from, to, value)
|
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 := vm.NewContract(caller, to, value, gas, gasPrice)
|
||||||
contract.SetCallCode(codeAddr, code)
|
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)
|
ret, err = evm.Run(contract, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.SetSnapshot(snapshot) //env.Db().Set(snapshot)
|
contract.UseGas(contract.Gas)
|
||||||
|
|
||||||
|
env.SetSnapshot(snapshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, addr, err
|
return ret, addr, err
|
||||||
|
@ -28,6 +28,7 @@ type Account struct {
|
|||||||
Nonce uint64 `json:"nonce"`
|
Nonce uint64 `json:"nonce"`
|
||||||
Root string `json:"root"`
|
Root string `json:"root"`
|
||||||
CodeHash string `json:"codeHash"`
|
CodeHash string `json:"codeHash"`
|
||||||
|
Code string `json:"code"`
|
||||||
Storage map[string]string `json:"storage"`
|
Storage map[string]string `json:"storage"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ func (self *StateDB) RawDump() World {
|
|||||||
addr := self.trie.GetKey(it.Key)
|
addr := self.trie.GetKey(it.Key)
|
||||||
stateObject := NewStateObjectFromBytes(common.BytesToAddress(addr), it.Value, self.db)
|
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)
|
account.Storage = make(map[string]string)
|
||||||
|
|
||||||
storageIt := stateObject.trie.Iterator()
|
storageIt := stateObject.trie.Iterator()
|
||||||
|
@ -260,6 +260,13 @@ func (self *StateObject) Nonce() uint64 {
|
|||||||
return self.nonce
|
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)) {
|
func (self *StateObject) EachStorage(cb func(key, value []byte)) {
|
||||||
// When iterating over the storage check the cache first
|
// When iterating over the storage check the cache first
|
||||||
for h, v := range self.storage {
|
for h, v := range self.storage {
|
||||||
|
@ -55,7 +55,6 @@ type StateDB struct {
|
|||||||
func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
||||||
tr, err := trie.NewSecure(root, db)
|
tr, err := trie.NewSecure(root, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("can't create state trie with root %x: %v", root[:], err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &StateDB{
|
return &StateDB{
|
||||||
|
@ -43,7 +43,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (ty
|
|||||||
|
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
||||||
|
|
||||||
receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas)
|
receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, totalUsedGas, err
|
return nil, nil, totalUsedGas, err
|
||||||
|
@ -27,6 +27,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Big0 = big.NewInt(0)
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The State Transitioning Model
|
The State Transitioning Model
|
||||||
|
|
||||||
@ -59,6 +63,7 @@ type StateTransition struct {
|
|||||||
// Message represents a message sent to a contract.
|
// Message represents a message sent to a contract.
|
||||||
type Message interface {
|
type Message interface {
|
||||||
From() (common.Address, error)
|
From() (common.Address, error)
|
||||||
|
FromFrontier() (common.Address, error)
|
||||||
To() *common.Address
|
To() *common.Address
|
||||||
|
|
||||||
GasPrice() *big.Int
|
GasPrice() *big.Int
|
||||||
@ -75,8 +80,13 @@ func MessageCreatesContract(msg Message) bool {
|
|||||||
|
|
||||||
// IntrinsicGas computes the 'intrisic gas' for a message
|
// IntrinsicGas computes the 'intrisic gas' for a message
|
||||||
// with the given data.
|
// with the given data.
|
||||||
func IntrinsicGas(data []byte) *big.Int {
|
func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
|
||||||
igas := new(big.Int).Set(params.TxGas)
|
igas := new(big.Int)
|
||||||
|
if contractCreation && homestead {
|
||||||
|
igas.Set(params.TxGasContractCreation)
|
||||||
|
} else {
|
||||||
|
igas.Set(params.TxGas)
|
||||||
|
}
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
var nz int64
|
var nz int64
|
||||||
for _, byt := range data {
|
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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -195,35 +213,35 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
|
|||||||
if err = self.preCheck(); err != nil {
|
if err = self.preCheck(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := self.msg
|
msg := self.msg
|
||||||
sender, _ := self.from() // err checked in preCheck
|
sender, _ := self.from() // err checked in preCheck
|
||||||
|
|
||||||
|
homestead := params.IsHomestead(self.env.BlockNumber())
|
||||||
|
contractCreation := MessageCreatesContract(msg)
|
||||||
// Pay intrinsic gas
|
// 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)
|
return nil, nil, InvalidTxError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
vmenv := self.env
|
vmenv := self.env
|
||||||
var addr common.Address
|
//var addr common.Address
|
||||||
if MessageCreatesContract(msg) {
|
if contractCreation {
|
||||||
ret, addr, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
|
ret, _, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
|
||||||
if err == nil {
|
if homestead && err == vm.CodeStoreOutOfGasError {
|
||||||
dataGas := big.NewInt(int64(len(ret)))
|
self.gas = Big0
|
||||||
dataGas.Mul(dataGas, params.CreateDataGas)
|
}
|
||||||
if err := self.useGas(dataGas); err == nil {
|
|
||||||
self.state.SetCode(addr, ret)
|
if err != nil {
|
||||||
} else {
|
ret = nil
|
||||||
ret = nil // does not affect consensus but useful for StateTests validations
|
glog.V(logger.Core).Infoln("VM create err:", err)
|
||||||
glog.V(logger.Core).Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
glog.V(logger.Core).Infoln("VM create err:", err)
|
|
||||||
} else {
|
} else {
|
||||||
// Increment the nonce for the next transaction
|
// Increment the nonce for the next transaction
|
||||||
self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
|
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)
|
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) {
|
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/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -65,10 +66,11 @@ type TxPool struct {
|
|||||||
minGasPrice *big.Int
|
minGasPrice *big.Int
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
events event.Subscription
|
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
|
homestead bool
|
||||||
pending map[common.Hash]*types.Transaction // processable transactions
|
|
||||||
queue map[common.Address]map[common.Hash]*types.Transaction
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
|
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,
|
pendingState: nil,
|
||||||
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
|
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
go pool.eventLoop()
|
go pool.eventLoop()
|
||||||
|
|
||||||
return pool
|
return pool
|
||||||
@ -96,6 +99,10 @@ func (pool *TxPool) eventLoop() {
|
|||||||
switch ev := ev.Data.(type) {
|
switch ev := ev.Data.(type) {
|
||||||
case ChainHeadEvent:
|
case ChainHeadEvent:
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
|
if ev.Block != nil && params.IsHomestead(ev.Block.Number()) {
|
||||||
|
pool.homestead = true
|
||||||
|
}
|
||||||
|
|
||||||
pool.resetState()
|
pool.resetState()
|
||||||
pool.mu.Unlock()
|
pool.mu.Unlock()
|
||||||
case GasPriceChanged:
|
case GasPriceChanged:
|
||||||
@ -138,7 +145,6 @@ func (pool *TxPool) resetState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the queue and move transactions over to the pending if possible
|
// Check the queue and move transactions over to the pending if possible
|
||||||
// or remove those that have become invalid
|
// or remove those that have become invalid
|
||||||
pool.checkQueue()
|
pool.checkQueue()
|
||||||
@ -171,29 +177,23 @@ func (pool *TxPool) Stats() (pending int, queued int) {
|
|||||||
// validateTx checks whether a transaction is valid according
|
// validateTx checks whether a transaction is valid according
|
||||||
// to the consensus rules.
|
// to the consensus rules.
|
||||||
func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
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
|
// Drop transactions under our own minimal accepted gas price
|
||||||
if pool.minGasPrice.Cmp(tx.GasPrice()) > 0 {
|
if pool.minGasPrice.Cmp(tx.GasPrice()) > 0 {
|
||||||
return ErrCheap
|
return ErrCheap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the transaction sender and it's sig. Throw
|
currentState, err := pool.currentState()
|
||||||
// if the from fields is invalid.
|
if err != nil {
|
||||||
if from, err = tx.From(); err != nil {
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
from, err := tx.From()
|
||||||
|
if err != nil {
|
||||||
return ErrInvalidSender
|
return ErrInvalidSender
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the account exist. Non existent accounts
|
// Make sure the account exist. Non existent accounts
|
||||||
// haven't got funds and well therefor never pass.
|
// haven't got funds and well therefor never pass.
|
||||||
currentState, err := pool.currentState()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !currentState.HasAccount(from) {
|
if !currentState.HasAccount(from) {
|
||||||
return ErrNonExistentAccount
|
return ErrNonExistentAccount
|
||||||
}
|
}
|
||||||
@ -222,8 +222,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
|||||||
return ErrInsufficientFunds
|
return ErrInsufficientFunds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should supply enough intrinsic gas
|
intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead)
|
||||||
if tx.Gas().Cmp(IntrinsicGas(tx.Data())) < 0 {
|
if tx.Gas().Cmp(intrGas) < 0 {
|
||||||
return ErrIntrinsicGas
|
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.
|
// 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()
|
self.mu.Lock()
|
||||||
defer self.mu.Unlock()
|
defer self.mu.Unlock()
|
||||||
|
|
||||||
err = self.add(tx)
|
if err := self.add(tx); err != nil {
|
||||||
if err == nil {
|
return err
|
||||||
// check and validate the queueue
|
|
||||||
self.checkQueue()
|
|
||||||
}
|
}
|
||||||
|
self.checkQueue()
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTransactions attempts to queue all valid transactions in txs.
|
// AddTransactions attempts to queue all valid transactions in txs.
|
||||||
@ -368,7 +366,7 @@ func (self *TxPool) GetQueuedTransactions() types.Transactions {
|
|||||||
ret = append(ret, tx)
|
ret = append(ret, tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Sort(types.TxByNonce{ret})
|
sort.Sort(types.TxByNonce(ret))
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,51 +404,55 @@ func (pool *TxPool) checkQueue() {
|
|||||||
pool.resetState()
|
pool.resetState()
|
||||||
}
|
}
|
||||||
|
|
||||||
var addq txQueue
|
var promote txQueue
|
||||||
for address, txs := range pool.queue {
|
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()
|
currentState, err := pool.currentState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("could not get current state: %v", err)
|
glog.Errorf("could not get current state: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
trueNonce := currentState.GetNonce(address)
|
balance := currentState.GetBalance(address)
|
||||||
addq := addq[:0]
|
|
||||||
|
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 {
|
for hash, tx := range txs {
|
||||||
if tx.Nonce() < trueNonce {
|
// Drop processed or out of fund transactions
|
||||||
// Drop queued transactions whose nonce is lower than
|
if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 {
|
||||||
// the account nonce because they have been processed.
|
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)
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
// Collect the remaining transactions for the next pass.
|
||||||
if e.Nonce() > guessedNonce {
|
promote = append(promote, txQueueEntry{hash, address, tx})
|
||||||
if len(addq)-i > maxQueued {
|
}
|
||||||
|
// 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) {
|
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++ {
|
for _, drop := range promote[i+maxQueued:] {
|
||||||
delete(txs, addq[j].hash)
|
delete(txs, drop.hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
delete(txs, e.hash)
|
// Otherwise promote the transaction and move the guess nonce if needed
|
||||||
pool.addTx(e.hash, address, e.Transaction)
|
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.
|
// Delete the entire queue entry if it became empty.
|
||||||
if len(txs) == 0 {
|
if len(txs) == 0 {
|
||||||
@ -460,20 +462,56 @@ func (pool *TxPool) checkQueue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validatePool removes invalid and processed transactions from the main pool.
|
// 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() {
|
func (pool *TxPool) validatePool() {
|
||||||
state, err := pool.currentState()
|
state, err := pool.currentState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
|
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
|
||||||
return
|
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 {
|
for hash, tx := range pool.pending {
|
||||||
from, _ := tx.From() // err already checked
|
sender, _ := tx.From() // err already checked
|
||||||
// perform light nonce validation
|
|
||||||
if state.GetNonce(from) > tx.Nonce() {
|
// 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) {
|
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)
|
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
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"container/heap"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -155,11 +157,47 @@ func (tx *Transaction) Size() common.StorageSize {
|
|||||||
return common.StorageSize(c)
|
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) {
|
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 {
|
if from := tx.from.Load(); from != nil {
|
||||||
return from.(common.Address), nil
|
return from.(common.Address), nil
|
||||||
}
|
}
|
||||||
pubkey, err := tx.publicKey()
|
pubkey, err := tx.publicKey(homestead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
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)
|
return tx.data.V, new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) publicKey() ([]byte, error) {
|
func (tx *Transaction) publicKey(homestead bool) ([]byte, error) {
|
||||||
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S) {
|
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S, homestead) {
|
||||||
return nil, ErrInvalidSig
|
return nil, ErrInvalidSig
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,27 +340,78 @@ func TxDifference(a, b Transactions) (keep Transactions) {
|
|||||||
return keep
|
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 {
|
func (s TxByNonce) Len() int { return len(s) }
|
||||||
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
|
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) Pop() interface{} {
|
||||||
|
old := *s
|
||||||
func (s TxByPrice) Less(i, j int) bool {
|
n := len(old)
|
||||||
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
|
x := old[n-1]
|
||||||
|
*s = old[0 : n-1]
|
||||||
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
type TxByPriceAndNonce struct{ Transactions }
|
// SortByPriceAndNonce sorts the transactions by price in such a way that the
|
||||||
|
// nonce orderings within a single account are maintained.
|
||||||
func (s TxByPriceAndNonce) Less(i, j int) bool {
|
//
|
||||||
// we can ignore the error here. Sorting shouldn't care about validness
|
// Note, this is not as trivial as it seems from the first look as there are three
|
||||||
ifrom, _ := s.Transactions[i].From()
|
// different criteria that need to be taken into account (price, nonce, account
|
||||||
jfrom, _ := s.Transactions[j].From()
|
// match), which cannot be done with any plain sorting method, as certain items
|
||||||
// favour nonce if they are from the same recipient
|
// cannot be compared without context.
|
||||||
if ifrom == jfrom {
|
//
|
||||||
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
|
// 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")
|
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 {
|
type ContractRef interface {
|
||||||
ReturnGas(*big.Int, *big.Int)
|
ReturnGas(*big.Int, *big.Int)
|
||||||
Address() common.Address
|
Address() common.Address
|
||||||
|
Value() *big.Int
|
||||||
SetCode([]byte)
|
SetCode([]byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contract represents an ethereum contract in the state database. It contains
|
// 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 {
|
type Contract struct {
|
||||||
caller ContractRef
|
// CallerAddress is the result of the caller which initialised this
|
||||||
self ContractRef
|
// 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.
|
jumpdests destinations // result of JUMPDEST analysis.
|
||||||
|
|
||||||
@ -44,11 +49,13 @@ type Contract struct {
|
|||||||
value, Gas, UsedGas, Price *big.Int
|
value, Gas, UsedGas, Price *big.Int
|
||||||
|
|
||||||
Args []byte
|
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 {
|
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 {
|
if parent, ok := caller.(*Contract); ok {
|
||||||
// Reuse JUMPDEST analysis from parent context if available.
|
// Reuse JUMPDEST analysis from parent context if available.
|
||||||
@ -69,6 +76,16 @@ func NewContract(caller ContractRef, object ContractRef, value, gas, price *big.
|
|||||||
return c
|
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
|
// GetOp returns the n'th element in the contract's byte array
|
||||||
func (c *Contract) GetOp(n uint64) OpCode {
|
func (c *Contract) GetOp(n uint64) OpCode {
|
||||||
return OpCode(c.GetByte(n))
|
return OpCode(c.GetByte(n))
|
||||||
@ -83,13 +100,19 @@ func (c *Contract) GetByte(n uint64) byte {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return returns the given ret argument and returns any remaining gas to the
|
// Caller returns the caller of the contract.
|
||||||
// caller
|
//
|
||||||
func (c *Contract) Return(ret []byte) []byte {
|
// 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
|
// Return the remaining gas to the caller
|
||||||
c.caller.ReturnGas(c.Gas, c.Price)
|
c.caller.ReturnGas(c.Gas, c.Price)
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseGas attempts the use gas and subtracts it and returns true on success
|
// 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()
|
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
|
// SetCode sets the code to the contract
|
||||||
func (self *Contract) SetCode(code []byte) {
|
func (self *Contract) SetCode(code []byte) {
|
||||||
self.Code = code
|
self.Code = code
|
||||||
|
@ -93,7 +93,8 @@ func ecrecoverFunc(in []byte) []byte {
|
|||||||
vbig := common.Bytes2Big(in[32:64])
|
vbig := common.Bytes2Big(in[32:64])
|
||||||
v := byte(vbig.Uint64())
|
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")
|
glog.V(logger.Debug).Infof("EC RECOVER FAIL: v, r or s value invalid")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,8 @@ type Environment interface {
|
|||||||
Call(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
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
|
// 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)
|
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 a new contract
|
||||||
Create(me ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error)
|
Create(me ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error)
|
||||||
}
|
}
|
||||||
@ -121,4 +123,6 @@ type Account interface {
|
|||||||
Address() common.Address
|
Address() common.Address
|
||||||
ReturnGas(*big.Int, *big.Int)
|
ReturnGas(*big.Int, *big.Int)
|
||||||
SetCode([]byte)
|
SetCode([]byte)
|
||||||
|
EachStorage(cb func(key, value []byte))
|
||||||
|
Value() *big.Int
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var OutOfGasError = errors.New("Out of gas")
|
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)
|
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},
|
CREATE: {3, params.CreateGas, 1},
|
||||||
CALL: {7, params.CallGas, 1},
|
CALL: {7, params.CallGas, 1},
|
||||||
CALLCODE: {7, params.CallGas, 1},
|
CALLCODE: {7, params.CallGas, 1},
|
||||||
|
DELEGATECALL: {6, params.CallGas, 1},
|
||||||
JUMPDEST: {0, params.JumpdestGas, 0},
|
JUMPDEST: {0, params.JumpdestGas, 0},
|
||||||
SUICIDE: {1, Zero, 0},
|
SUICIDE: {1, Zero, 0},
|
||||||
RETURN: {2, 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) {
|
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) {
|
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) {
|
func opSstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
|
||||||
loc := common.BigToHash(stack.pop())
|
loc := common.BigToHash(stack.pop())
|
||||||
val := stack.pop()
|
val := stack.pop()
|
||||||
|
|
||||||
env.Db().SetState(contract.Address(), loc, common.BigToHash(val))
|
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()
|
offset, size = stack.pop(), stack.pop()
|
||||||
input = memory.Get(offset.Int64(), size.Int64())
|
input = memory.Get(offset.Int64(), size.Int64())
|
||||||
gas = new(big.Int).Set(contract.Gas)
|
gas = new(big.Int).Set(contract.Gas)
|
||||||
addr common.Address
|
|
||||||
ret []byte
|
|
||||||
suberr error
|
|
||||||
)
|
)
|
||||||
|
|
||||||
contract.UseGas(contract.Gas)
|
contract.UseGas(contract.Gas)
|
||||||
ret, addr, suberr = env.Create(contract, input, gas, contract.Price, value)
|
_, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
|
||||||
if suberr != nil {
|
// 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))
|
stack.push(new(big.Int))
|
||||||
} else {
|
} 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())
|
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 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) {
|
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)
|
program.addInstr(op, pc, opGas, nil)
|
||||||
case CREATE:
|
case CREATE:
|
||||||
program.addInstr(op, pc, opCreate, nil)
|
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:
|
case CALL:
|
||||||
program.addInstr(op, pc, opCall, nil)
|
program.addInstr(op, pc, opCall, nil)
|
||||||
case CALLCODE:
|
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)) {
|
for pc < uint64(len(program.instructions)) {
|
||||||
instrCount++
|
instrCount++
|
||||||
|
|
||||||
instr := program.instructions[pc]
|
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)
|
ret, err := instr.do(program, &pc, env, contract, mem, stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -328,13 +337,13 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
|
|||||||
}
|
}
|
||||||
|
|
||||||
if instr.halts() {
|
if instr.halts() {
|
||||||
return contract.Return(ret), nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract.Input = nil
|
contract.Input = nil
|
||||||
|
|
||||||
return contract.Return(nil), nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validDest checks if the given distination is a valid one given the
|
// 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])
|
gas.Add(gas, stack.data[stack.len()-1])
|
||||||
|
|
||||||
if op == CALL {
|
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])) {
|
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
|
||||||
gas.Add(gas, params.CallNewAccountGas)
|
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])
|
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||||
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
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)
|
newMemSize = common.BigMax(x, y)
|
||||||
}
|
}
|
||||||
quadMemGas(mem, newMemSize, gas)
|
quadMemGas(mem, newMemSize, gas)
|
||||||
|
@ -125,14 +125,17 @@ type vmBench struct {
|
|||||||
|
|
||||||
type account struct{}
|
type account struct{}
|
||||||
|
|
||||||
func (account) SubBalance(amount *big.Int) {}
|
func (account) SubBalance(amount *big.Int) {}
|
||||||
func (account) AddBalance(amount *big.Int) {}
|
func (account) AddBalance(amount *big.Int) {}
|
||||||
func (account) SetBalance(*big.Int) {}
|
func (account) SetAddress(common.Address) {}
|
||||||
func (account) SetNonce(uint64) {}
|
func (account) Value() *big.Int { return nil }
|
||||||
func (account) Balance() *big.Int { return nil }
|
func (account) SetBalance(*big.Int) {}
|
||||||
func (account) Address() common.Address { return common.Address{} }
|
func (account) SetNonce(uint64) {}
|
||||||
func (account) ReturnGas(*big.Int, *big.Int) {}
|
func (account) Balance() *big.Int { return nil }
|
||||||
func (account) SetCode([]byte) {}
|
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) {
|
func runVmBench(test vmBench, b *testing.B) {
|
||||||
var sender account
|
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) {
|
func (self *Env) Create(caller ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
|
||||||
return nil, common.Address{}, nil
|
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
|
package vm
|
||||||
|
|
||||||
import "math/big"
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
type jumpPtr struct {
|
type jumpPtr struct {
|
||||||
fn instrFn
|
fn instrFn
|
||||||
valid bool
|
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() {
|
func init() {
|
||||||
jumpTable[ADD] = jumpPtr{opAdd, true}
|
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
|
CALL
|
||||||
CALLCODE
|
CALLCODE
|
||||||
RETURN
|
RETURN
|
||||||
|
DELEGATECALL
|
||||||
|
|
||||||
SUICIDE = 0xff
|
SUICIDE = 0xff
|
||||||
)
|
)
|
||||||
@ -349,11 +350,12 @@ var opCodeToString = map[OpCode]string{
|
|||||||
LOG4: "LOG4",
|
LOG4: "LOG4",
|
||||||
|
|
||||||
// 0xf0 range
|
// 0xf0 range
|
||||||
CREATE: "CREATE",
|
CREATE: "CREATE",
|
||||||
CALL: "CALL",
|
CALL: "CALL",
|
||||||
RETURN: "RETURN",
|
RETURN: "RETURN",
|
||||||
CALLCODE: "CALLCODE",
|
CALLCODE: "CALLCODE",
|
||||||
SUICIDE: "SUICIDE",
|
DELEGATECALL: "DELEGATECALL",
|
||||||
|
SUICIDE: "SUICIDE",
|
||||||
|
|
||||||
PUSH: "PUSH",
|
PUSH: "PUSH",
|
||||||
DUP: "DUP",
|
DUP: "DUP",
|
||||||
@ -402,6 +404,7 @@ var stringToOp = map[string]OpCode{
|
|||||||
"CALLDATALOAD": CALLDATALOAD,
|
"CALLDATALOAD": CALLDATALOAD,
|
||||||
"CALLDATASIZE": CALLDATASIZE,
|
"CALLDATASIZE": CALLDATASIZE,
|
||||||
"CALLDATACOPY": CALLDATACOPY,
|
"CALLDATACOPY": CALLDATACOPY,
|
||||||
|
"DELEGATECALL": DELEGATECALL,
|
||||||
"CODESIZE": CODESIZE,
|
"CODESIZE": CODESIZE,
|
||||||
"CODECOPY": CODECOPY,
|
"CODECOPY": CODECOPY,
|
||||||
"GASPRICE": GASPRICE,
|
"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)
|
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) {
|
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)
|
return core.Create(self, caller, data, gas, price, value)
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ type Vm struct {
|
|||||||
|
|
||||||
// New returns a new Vm
|
// New returns a new Vm
|
||||||
func New(env Environment) *Vm {
|
func New(env Environment) *Vm {
|
||||||
|
// init the jump table. Also prepares the homestead changes
|
||||||
|
jumpTable.init(env.BlockNumber())
|
||||||
|
|
||||||
return &Vm{env: env}
|
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)
|
self.env.SetDepth(self.env.Depth() + 1)
|
||||||
defer 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 contract.CodeAddr != nil {
|
||||||
if p := Precompiled[contract.CodeAddr.Str()]; p != nil {
|
if p := Precompiled[contract.CodeAddr.Str()]; p != nil {
|
||||||
return self.RunPrecompiled(p, input, contract)
|
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.
|
// Don't bother with the execution if there's no code.
|
||||||
if len(contract.Code) == 0 {
|
if len(contract.Code) == 0 {
|
||||||
return contract.Return(nil), nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -160,7 +153,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
|||||||
|
|
||||||
// Get the memory location of pc
|
// Get the memory location of pc
|
||||||
op = contract.GetOp(pc)
|
op = contract.GetOp(pc)
|
||||||
|
|
||||||
// calculate the new memory size and gas price for the current executing opcode
|
// 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)
|
newMemSize, cost, err = calculateGasAndSize(self.env, contract, caller, op, statedb, mem, stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -177,7 +169,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
|||||||
mem.Resize(newMemSize.Uint64())
|
mem.Resize(newMemSize.Uint64())
|
||||||
// Add a log message
|
// Add a log message
|
||||||
self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil)
|
self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil)
|
||||||
|
|
||||||
if opPtr := jumpTable[op]; opPtr.valid {
|
if opPtr := jumpTable[op]; opPtr.valid {
|
||||||
if opPtr.fn != nil {
|
if opPtr.fn != nil {
|
||||||
opPtr.fn(instruction{}, &pc, self.env, contract, mem, stack)
|
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()
|
offset, size := stack.pop(), stack.pop()
|
||||||
ret := mem.GetPtr(offset.Int64(), size.Int64())
|
ret := mem.GetPtr(offset.Int64(), size.Int64())
|
||||||
|
|
||||||
return contract.Return(ret), nil
|
return ret, nil
|
||||||
case SUICIDE:
|
case SUICIDE:
|
||||||
opSuicide(instruction{}, nil, self.env, contract, mem, stack)
|
opSuicide(instruction{}, nil, self.env, contract, mem, stack)
|
||||||
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case STOP: // Stop the contract
|
case STOP: // Stop the contract
|
||||||
return contract.Return(nil), nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -332,7 +323,6 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
|
|||||||
gas.Add(gas, stack.data[stack.len()-1])
|
gas.Add(gas, stack.data[stack.len()-1])
|
||||||
|
|
||||||
if op == CALL {
|
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])) {
|
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
|
||||||
gas.Add(gas, params.CallNewAccountGas)
|
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])
|
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||||
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
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)
|
newMemSize = common.BigMax(x, y)
|
||||||
}
|
}
|
||||||
quadMemGas(mem, newMemSize, gas)
|
quadMemGas(mem, newMemSize, gas)
|
||||||
@ -358,7 +355,7 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Co
|
|||||||
if contract.UseGas(gas) {
|
if contract.UseGas(gas) {
|
||||||
ret = p.Call(input)
|
ret = p.Call(input)
|
||||||
|
|
||||||
return contract.Return(ret), nil
|
return ret, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, OutOfGasError
|
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)
|
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) {
|
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)
|
return Create(self, me, data, gas, price, value)
|
||||||
}
|
}
|
||||||
|
@ -171,12 +171,21 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
|
|||||||
return ecdsa.GenerateKey(S256(), rand.Reader)
|
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 {
|
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
vint := uint32(v)
|
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
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
@ -174,7 +174,7 @@ func TestLoadECDSAFile(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidateSignatureValues(t *testing.T) {
|
func TestValidateSignatureValues(t *testing.T) {
|
||||||
check := func(expected bool, v byte, r, s *big.Int) {
|
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)
|
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
|
// messageTag computes the MAC of a message (called the tag) as per
|
||||||
// SEC 1, 3.5.
|
// SEC 1, 3.5.
|
||||||
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
|
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
|
||||||
if shared == nil {
|
|
||||||
shared = make([]byte, 0)
|
|
||||||
}
|
|
||||||
mac := hmac.New(hash, km)
|
mac := hmac.New(hash, km)
|
||||||
mac.Write(msg)
|
mac.Write(msg)
|
||||||
|
mac.Write(shared)
|
||||||
tag := mac.Sum(nil)
|
tag := mac.Sum(nil)
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
@ -242,9 +240,11 @@ func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
|
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1.
|
||||||
// the shared information parameters aren't being used, they should be
|
//
|
||||||
// nil.
|
// 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) {
|
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
|
||||||
params := pub.Params
|
params := pub.Params
|
||||||
if params == nil {
|
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
|
// TestMarshalEncryption validates the encode/decode produces a valid
|
||||||
// ECIES encryption key.
|
// ECIES encryption key.
|
||||||
func TestMarshalEncryption(t *testing.T) {
|
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 CFLAGS: -I./libsecp256k1
|
||||||
#cgo darwin CFLAGS: -I/usr/local/include
|
#cgo CFLAGS: -I./libsecp256k1/src/
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/include
|
#define USE_NUM_NONE
|
||||||
#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
|
|
||||||
#define USE_FIELD_10X26
|
#define USE_FIELD_10X26
|
||||||
#define USE_FIELD_INV_BUILTIN
|
#define USE_FIELD_INV_BUILTIN
|
||||||
#define USE_SCALAR_8X32
|
#define USE_SCALAR_8X32
|
||||||
@ -44,6 +38,7 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"math/big"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
||||||
@ -60,9 +55,17 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
|
// 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() {
|
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.
|
// around 20 ms on a modern CPU.
|
||||||
context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
|
context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
|
||||||
C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
|
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
|
syncStatsLock sync.RWMutex // Lock protecting the sync stats fields
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
hasHeader headerCheckFn // Checks if a header is present in the chain
|
hasHeader headerCheckFn // Checks if a header is present in the chain
|
||||||
hasBlock blockCheckFn // Checks if a block 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
|
getHeader headerRetrievalFn // Retrieves a header from the chain
|
||||||
getBlock blockRetrievalFn // Retrieves a block from the chain
|
getBlock blockRetrievalFn // Retrieves a block from the chain
|
||||||
headHeader headHeaderRetrievalFn // Retrieves the head header from the chain
|
headHeader headHeaderRetrievalFn // Retrieves the head header from the chain
|
||||||
headBlock headBlockRetrievalFn // Retrieves the head block from the chain
|
headBlock headBlockRetrievalFn // Retrieves the head block from the chain
|
||||||
headFastBlock headFastBlockRetrievalFn // Retrieves the head fast-sync 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
|
commitHeadBlock headBlockCommitterFn // Commits a manually assembled block as the chain head
|
||||||
getTd tdRetrievalFn // Retrieves the TD of a block from the chain
|
getTd tdRetrievalFn // Retrieves the TD of a block from the chain
|
||||||
insertHeaders headerChainInsertFn // Injects a batch of headers into the chain
|
insertHeaders headerChainInsertFn // Injects a batch of headers into the chain
|
||||||
insertBlocks blockChainInsertFn // Injects a batch of blocks 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
|
insertReceipts receiptChainInsertFn // Injects a batch of blocks and their receipts into the chain
|
||||||
rollback chainRollbackFn // Removes a batch of recently added chain links
|
rollback chainRollbackFn // Removes a batch of recently added chain links
|
||||||
dropPeer peerDropFn // Drops a peer for misbehaving
|
dropPeer peerDropFn // Drops a peer for misbehaving
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
synchroniseMock func(id string, hash common.Hash) error // Replacement for synchronise during testing
|
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.
|
// 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,
|
func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, hasBlockAndState blockAndStateCheckFn,
|
||||||
getBlock blockRetrievalFn, headHeader headHeaderRetrievalFn, headBlock headBlockRetrievalFn, headFastBlock headFastBlockRetrievalFn,
|
getHeader headerRetrievalFn, getBlock blockRetrievalFn, headHeader headHeaderRetrievalFn, headBlock headBlockRetrievalFn,
|
||||||
commitHeadBlock headBlockCommitterFn, getTd tdRetrievalFn, insertHeaders headerChainInsertFn, insertBlocks blockChainInsertFn,
|
headFastBlock headFastBlockRetrievalFn, commitHeadBlock headBlockCommitterFn, getTd tdRetrievalFn, insertHeaders headerChainInsertFn,
|
||||||
insertReceipts receiptChainInsertFn, rollback chainRollbackFn, dropPeer peerDropFn) *Downloader {
|
insertBlocks blockChainInsertFn, insertReceipts receiptChainInsertFn, rollback chainRollbackFn, dropPeer peerDropFn) *Downloader {
|
||||||
|
|
||||||
return &Downloader{
|
return &Downloader{
|
||||||
mode: FullSync,
|
mode: FullSync,
|
||||||
mux: mux,
|
mux: mux,
|
||||||
queue: newQueue(stateDb),
|
queue: newQueue(stateDb),
|
||||||
peers: newPeerSet(),
|
peers: newPeerSet(),
|
||||||
hasHeader: hasHeader,
|
hasHeader: hasHeader,
|
||||||
hasBlock: hasBlock,
|
hasBlockAndState: hasBlockAndState,
|
||||||
getHeader: getHeader,
|
getHeader: getHeader,
|
||||||
getBlock: getBlock,
|
getBlock: getBlock,
|
||||||
headHeader: headHeader,
|
headHeader: headHeader,
|
||||||
headBlock: headBlock,
|
headBlock: headBlock,
|
||||||
headFastBlock: headFastBlock,
|
headFastBlock: headFastBlock,
|
||||||
commitHeadBlock: commitHeadBlock,
|
commitHeadBlock: commitHeadBlock,
|
||||||
getTd: getTd,
|
getTd: getTd,
|
||||||
insertHeaders: insertHeaders,
|
insertHeaders: insertHeaders,
|
||||||
insertBlocks: insertBlocks,
|
insertBlocks: insertBlocks,
|
||||||
insertReceipts: insertReceipts,
|
insertReceipts: insertReceipts,
|
||||||
rollback: rollback,
|
rollback: rollback,
|
||||||
dropPeer: dropPeer,
|
dropPeer: dropPeer,
|
||||||
newPeerCh: make(chan *peer, 1),
|
newPeerCh: make(chan *peer, 1),
|
||||||
hashCh: make(chan dataPack, 1),
|
hashCh: make(chan dataPack, 1),
|
||||||
blockCh: make(chan dataPack, 1),
|
blockCh: make(chan dataPack, 1),
|
||||||
headerCh: make(chan dataPack, 1),
|
headerCh: make(chan dataPack, 1),
|
||||||
bodyCh: make(chan dataPack, 1),
|
bodyCh: make(chan dataPack, 1),
|
||||||
receiptCh: make(chan dataPack, 1),
|
receiptCh: make(chan dataPack, 1),
|
||||||
stateCh: make(chan dataPack, 1),
|
stateCh: make(chan dataPack, 1),
|
||||||
blockWakeCh: make(chan bool, 1),
|
blockWakeCh: make(chan bool, 1),
|
||||||
bodyWakeCh: make(chan bool, 1),
|
bodyWakeCh: make(chan bool, 1),
|
||||||
receiptWakeCh: make(chan bool, 1),
|
receiptWakeCh: make(chan bool, 1),
|
||||||
stateWakeCh: 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
|
// Check if a common ancestor was found
|
||||||
finished = true
|
finished = true
|
||||||
for i := len(hashes) - 1; i >= 0; i-- {
|
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]
|
number, hash = uint64(from)+uint64(i), hashes[i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -620,11 +620,11 @@ func (d *Downloader) findAncestor61(p *peer) (uint64, error) {
|
|||||||
arrived = true
|
arrived = true
|
||||||
|
|
||||||
// Modify the search interval based on the response
|
// Modify the search interval based on the response
|
||||||
block := d.getBlock(hashes[0])
|
if !d.hasBlockAndState(hashes[0]) {
|
||||||
if block == nil {
|
|
||||||
end = check
|
end = check
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
block := d.getBlock(hashes[0]) // this doesn't check state, hence the above explicit check
|
||||||
if block.NumberU64() != 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)
|
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
|
return 0, errBadPeer
|
||||||
@ -989,7 +989,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
|
|||||||
// Check if a common ancestor was found
|
// Check if a common ancestor was found
|
||||||
finished = true
|
finished = true
|
||||||
for i := len(headers) - 1; i >= 0; i-- {
|
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()
|
number, hash = headers[i].Number.Uint64(), headers[i].Hash()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1045,7 +1045,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
|
|||||||
arrived = true
|
arrived = true
|
||||||
|
|
||||||
// Modify the search interval based on the response
|
// 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
|
end = check
|
||||||
break
|
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
|
// 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} {
|
for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh, d.stateWakeCh} {
|
||||||
if cont {
|
if cont {
|
||||||
// We still have headers to fetch, send continuation wake signal (potential)
|
// 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 ch <- false:
|
||||||
case <-d.cancelCh:
|
case <-d.cancelCh:
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !cont {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Queue not yet full, fetch the next batch
|
// Queue not yet full, fetch the next batch
|
||||||
from += uint64(len(headers))
|
from += uint64(len(headers))
|
||||||
getHeaders(from)
|
getHeaders(from)
|
||||||
|
@ -150,6 +150,8 @@ func newTester() *downloadTester {
|
|||||||
peerChainTds: make(map[string]map[common.Hash]*big.Int),
|
peerChainTds: make(map[string]map[common.Hash]*big.Int),
|
||||||
}
|
}
|
||||||
tester.stateDb, _ = ethdb.NewMemDatabase()
|
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.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.getBlock, tester.headHeader, tester.headBlock, tester.headFastBlock, tester.commitHeadBlock, tester.getTd,
|
||||||
tester.insertHeaders, tester.insertBlocks, tester.insertReceipts, tester.rollback, tester.dropPeer)
|
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
|
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 {
|
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.
|
// 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()
|
defer dl.lock.Unlock()
|
||||||
|
|
||||||
for i, block := range blocks {
|
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")
|
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 {
|
if _, ok := dl.ownHeaders[block.Hash()]; !ok {
|
||||||
dl.ownHashes = append(dl.ownHashes, block.Hash())
|
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
|
// 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 TestInvalidHeaderRollback63Fast(t *testing.T) { testInvalidHeaderRollback(t, 63, FastSync) }
|
||||||
func TestInvalidHeaderRollback64Fast(t *testing.T) { testInvalidHeaderRollback(t, 64, FastSync) }
|
func TestInvalidHeaderRollback64Fast(t *testing.T) { testInvalidHeaderRollback(t, 64, FastSync) }
|
||||||
func TestInvalidHeaderRollback64Light(t *testing.T) { testInvalidHeaderRollback(t, 64, LightSync) }
|
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.
|
// headerCheckFn is a callback type for verifying a header's presence in the local chain.
|
||||||
type headerCheckFn func(common.Hash) bool
|
type headerCheckFn func(common.Hash) bool
|
||||||
|
|
||||||
// blockCheckFn is a callback type for verifying a block's presence in the local chain.
|
// blockAndStateCheckFn is a callback type for verifying block and associated states' presence in the local chain.
|
||||||
type blockCheckFn func(common.Hash) bool
|
type blockAndStateCheckFn func(common.Hash) bool
|
||||||
|
|
||||||
// headerRetrievalFn is a callback type for retrieving a header from the local chain.
|
// headerRetrievalFn is a callback type for retrieving a header from the local chain.
|
||||||
type headerRetrievalFn func(common.Hash) *types.Header
|
type headerRetrievalFn func(common.Hash) *types.Header
|
||||||
|
@ -138,9 +138,10 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
|
|||||||
return nil, errIncompatibleConfig
|
return nil, errIncompatibleConfig
|
||||||
}
|
}
|
||||||
// Construct the different synchronisation mechanisms
|
// Construct the different synchronisation mechanisms
|
||||||
manager.downloader = downloader.New(chaindb, manager.eventMux, blockchain.HasHeader, blockchain.HasBlock, blockchain.GetHeader, blockchain.GetBlock,
|
manager.downloader = downloader.New(chaindb, manager.eventMux, blockchain.HasHeader, blockchain.HasBlockAndState, blockchain.GetHeader,
|
||||||
blockchain.CurrentHeader, blockchain.CurrentBlock, blockchain.CurrentFastBlock, blockchain.FastSyncCommitHead, blockchain.GetTd,
|
blockchain.GetBlock, blockchain.CurrentHeader, blockchain.CurrentBlock, blockchain.CurrentFastBlock, blockchain.FastSyncCommitHead,
|
||||||
blockchain.InsertHeaderChain, blockchain.InsertChain, blockchain.InsertReceiptChain, blockchain.Rollback, manager.removePeer)
|
blockchain.GetTd, blockchain.InsertHeaderChain, blockchain.InsertChain, blockchain.InsertReceiptChain, blockchain.Rollback,
|
||||||
|
manager.removePeer)
|
||||||
|
|
||||||
validator := func(block *types.Block, parent *types.Block) error {
|
validator := func(block *types.Block, parent *types.Block) error {
|
||||||
return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false)
|
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
|
uncles[i] = body.Uncles
|
||||||
}
|
}
|
||||||
// Filter out any explicitly requested bodies, deliver the rest to the downloader
|
// 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)
|
err := pm.downloader.DeliverBodies(p.id, trasactions, uncles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(logger.Debug).Infoln(err)
|
glog.V(logger.Debug).Infoln(err)
|
||||||
|
@ -19,7 +19,6 @@ package miner
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -495,12 +494,12 @@ func (self *worker) commitNewWork() {
|
|||||||
|
|
||||||
/* //approach 1
|
/* //approach 1
|
||||||
transactions := self.eth.TxPool().GetTransactions()
|
transactions := self.eth.TxPool().GetTransactions()
|
||||||
sort.Sort(types.TxByNonce{transactions})
|
sort.Sort(types.TxByNonce(transactions))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//approach 2
|
//approach 2
|
||||||
transactions := self.eth.TxPool().GetTransactions()
|
transactions := self.eth.TxPool().GetTransactions()
|
||||||
sort.Sort(types.TxByPriceAndNonce{transactions})
|
types.SortByPriceAndNonce(transactions)
|
||||||
|
|
||||||
/* // approach 3
|
/* // approach 3
|
||||||
// commit transactions for this run.
|
// commit transactions for this run.
|
||||||
@ -524,8 +523,8 @@ func (self *worker) commitNewWork() {
|
|||||||
multiTxOwner = append(multiTxOwner, txs...)
|
multiTxOwner = append(multiTxOwner, txs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Sort(types.TxByPrice{singleTxOwner})
|
sort.Sort(types.TxByPrice(singleTxOwner))
|
||||||
sort.Sort(types.TxByNonce{multiTxOwner})
|
sort.Sort(types.TxByNonce(multiTxOwner))
|
||||||
transactions := append(singleTxOwner, 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) {
|
func (env *Work) commitTransactions(transactions types.Transactions, gasPrice *big.Int, bc *core.BlockChain) {
|
||||||
gp := new(core.GasPool).AddGas(env.header.GasLimit)
|
gp := new(core.GasPool).AddGas(env.header.GasLimit)
|
||||||
for _, tx := range transactions {
|
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()
|
from, _ := tx.From()
|
||||||
|
|
||||||
// Check if it falls within margin. Txs from owned accounts are always processed.
|
// Check if it falls within margin. Txs from owned accounts are always processed.
|
||||||
|
@ -67,6 +67,8 @@ type (
|
|||||||
Version uint
|
Version uint
|
||||||
From, To rpcEndpoint
|
From, To rpcEndpoint
|
||||||
Expiration uint64
|
Expiration uint64
|
||||||
|
// Ignore additional fields (for forward compatibility).
|
||||||
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// pong is the reply to ping.
|
// pong is the reply to ping.
|
||||||
@ -78,18 +80,24 @@ type (
|
|||||||
|
|
||||||
ReplyTok []byte // This contains the hash of the ping packet.
|
ReplyTok []byte // This contains the hash of the ping packet.
|
||||||
Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
|
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 is a query for nodes close to the given target.
|
||||||
findnode struct {
|
findnode struct {
|
||||||
Target NodeID // doesn't need to be an actual public key
|
Target NodeID // doesn't need to be an actual public key
|
||||||
Expiration uint64
|
Expiration uint64
|
||||||
|
// Ignore additional fields (for forward compatibility).
|
||||||
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// reply to findnode
|
// reply to findnode
|
||||||
neighbors struct {
|
neighbors struct {
|
||||||
Nodes []rpcNode
|
Nodes []rpcNode
|
||||||
Expiration uint64
|
Expiration uint64
|
||||||
|
// Ignore additional fields (for forward compatibility).
|
||||||
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcNode struct {
|
rpcNode struct {
|
||||||
@ -447,8 +455,11 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte,
|
|||||||
return packet, nil
|
return packet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type tempError interface {
|
func isTemporaryError(err error) bool {
|
||||||
Temporary() bool
|
tempErr, ok := err.(interface {
|
||||||
|
Temporary() bool
|
||||||
|
})
|
||||||
|
return ok && tempErr.Temporary() || isPacketTooBig(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// readLoop runs in its own goroutine. it handles incoming UDP packets.
|
// readLoop runs in its own goroutine. it handles incoming UDP packets.
|
||||||
@ -460,7 +471,7 @@ func (t *udp) readLoop() {
|
|||||||
buf := make([]byte, 1280)
|
buf := make([]byte, 1280)
|
||||||
for {
|
for {
|
||||||
nbytes, from, err := t.conn.ReadFromUDP(buf)
|
nbytes, from, err := t.conn.ReadFromUDP(buf)
|
||||||
if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
|
if isTemporaryError(err) {
|
||||||
// Ignore temporary read errors.
|
// Ignore temporary read errors.
|
||||||
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
|
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
|
||||||
continue
|
continue
|
||||||
@ -513,7 +524,8 @@ func decodePacket(buf []byte) (packet, NodeID, []byte, error) {
|
|||||||
default:
|
default:
|
||||||
return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype)
|
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
|
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"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
logpkg "log"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -34,12 +33,64 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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
|
// 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.
|
// dgramPipe is a fake UDP socket. It queues all sent datagrams.
|
||||||
type dgramPipe struct {
|
type dgramPipe struct {
|
||||||
mu *sync.Mutex
|
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 {
|
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 {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("invalid hex string: %q", str))
|
panic(fmt.Sprintf("invalid hex string: %q", str))
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@ type protoHandshake struct {
|
|||||||
Caps []Cap
|
Caps []Cap
|
||||||
ListenPort uint64
|
ListenPort uint64
|
||||||
ID discover.NodeID
|
ID discover.NodeID
|
||||||
|
|
||||||
|
// Ignore additional fields (for forward compatibility).
|
||||||
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer represents a connected remote node.
|
// Peer represents a connected remote node.
|
||||||
|
363
p2p/rlpx.go
363
p2p/rlpx.go
@ -24,11 +24,14 @@ import (
|
|||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
mrand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -51,9 +54,10 @@ const (
|
|||||||
authMsgLen = sigLen + shaLen + pubLen + shaLen + 1
|
authMsgLen = sigLen + shaLen + pubLen + shaLen + 1
|
||||||
authRespLen = pubLen + shaLen + 1
|
authRespLen = pubLen + shaLen + 1
|
||||||
|
|
||||||
eciesBytes = 65 + 16 + 32
|
eciesOverhead = 65 /* pubkey */ + 16 /* IV */ + 32 /* MAC */
|
||||||
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
|
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
|
// total timeout for encryption handshake and protocol
|
||||||
// handshake in both directions.
|
// handshake in both directions.
|
||||||
@ -151,10 +155,6 @@ func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake,
|
|||||||
if err := msg.Decode(&hs); err != nil {
|
if err := msg.Decode(&hs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// validate handshake info
|
|
||||||
if hs.Version != our.Version {
|
|
||||||
return nil, DiscIncompatibleVersion
|
|
||||||
}
|
|
||||||
if (hs.ID == discover.NodeID{}) {
|
if (hs.ID == discover.NodeID{}) {
|
||||||
return nil, DiscInvalidIdentity
|
return nil, DiscInvalidIdentity
|
||||||
}
|
}
|
||||||
@ -200,6 +200,29 @@ type secrets struct {
|
|||||||
Token []byte
|
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.
|
// secrets is called after the handshake is completed.
|
||||||
// It extracts the connection secrets from the handshake values.
|
// It extracts the connection secrets from the handshake values.
|
||||||
func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
|
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,
|
RemoteID: h.remoteID,
|
||||||
AES: aesSecret,
|
AES: aesSecret,
|
||||||
MAC: crypto.Sha3(ecdheSecret, aesSecret),
|
MAC: crypto.Sha3(ecdheSecret, aesSecret),
|
||||||
Token: crypto.Sha3(sharedSecret),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup sha3 instances for the MACs
|
// setup sha3 instances for the MACs
|
||||||
@ -234,114 +256,89 @@ func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
|
|||||||
return s, nil
|
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)
|
return ecies.ImportECDSA(prv).GenerateShared(h.remotePub, sskLen, sskLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var configSendEIP = os.Getenv("RLPX_EIP8") != ""
|
||||||
|
|
||||||
// initiatorEncHandshake negotiates a session token on conn.
|
// initiatorEncHandshake negotiates a session token on conn.
|
||||||
// it should be called on the dialing side of the connection.
|
// it should be called on the dialing side of the connection.
|
||||||
//
|
//
|
||||||
// prv is the local client's private key.
|
// 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) {
|
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 {
|
if err != nil {
|
||||||
return s, err
|
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 {
|
if err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
if _, err = conn.Write(auth); err != nil {
|
if _, err = conn.Write(authPacket); err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response := make([]byte, encAuthRespLen)
|
authRespMsg := new(authRespV4)
|
||||||
if _, err = io.ReadFull(conn, response); err != nil {
|
authRespPacket, err := readHandshakeMsg(authRespMsg, encAuthRespLen, prv, conn)
|
||||||
|
if err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
if err := h.decodeAuthResp(response, prv); err != nil {
|
if err := h.handleAuthResp(authRespMsg); err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
return h.secrets(auth, response)
|
return h.secrets(authPacket, authRespPacket)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInitiatorHandshake(remoteID discover.NodeID) (*encHandshake, error) {
|
// makeAuthMsg creates the initiator handshake message.
|
||||||
rpub, err := remoteID.Pubkey()
|
func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey, token []byte) (*authMsgV4, error) {
|
||||||
|
rpub, err := h.remoteID.Pubkey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("bad remoteID: %v", err)
|
return nil, fmt.Errorf("bad remoteID: %v", err)
|
||||||
}
|
}
|
||||||
// generate random initiator nonce
|
h.remotePub = ecies.ImportECDSAPublic(rpub)
|
||||||
n := make([]byte, shaLen)
|
// Generate random initiator nonce.
|
||||||
if _, err := rand.Read(n); err != nil {
|
h.initNonce = make([]byte, shaLen)
|
||||||
|
if _, err := rand.Read(h.initNonce); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// generate random keypair to use for signing
|
// Generate random keypair to for ECDH.
|
||||||
randpriv, err := ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// Sign known message: static-shared-secret ^ nonce
|
||||||
func (h *encHandshake) authMsg(prv *ecdsa.PrivateKey, token []byte) ([]byte, error) {
|
token, err = h.staticSharedSecret(prv)
|
||||||
var tokenFlag byte
|
if err != nil {
|
||||||
if token == nil {
|
return nil, err
|
||||||
// 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:
|
|
||||||
// ecdh-shared-secret^nonce for new peers
|
|
||||||
// token^nonce for old peers
|
|
||||||
signed := xor(token, h.initNonce)
|
signed := xor(token, h.initNonce)
|
||||||
signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
|
signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode auth message
|
msg := new(authMsgV4)
|
||||||
// signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag
|
copy(msg.Signature[:], signature)
|
||||||
msg := make([]byte, authMsgLen)
|
copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
|
||||||
n := copy(msg, signature)
|
copy(msg.Nonce[:], h.initNonce)
|
||||||
n += copy(msg[n:], crypto.Sha3(exportPubkey(&h.randomPrivKey.PublicKey)))
|
msg.Version = 4
|
||||||
n += copy(msg[n:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
|
return msg, nil
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeAuthResp decode an encrypted authentication response message.
|
func (h *encHandshake) handleAuthResp(msg *authRespV4) (err error) {
|
||||||
func (h *encHandshake) decodeAuthResp(auth []byte, prv *ecdsa.PrivateKey) error {
|
h.respNonce = msg.Nonce[:]
|
||||||
msg, err := crypto.Decrypt(prv, auth)
|
h.remoteRandomPub, err = importPublicKey(msg.RandomPubkey[:])
|
||||||
if err != nil {
|
return err
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiverEncHandshake negotiates a session token on conn.
|
// 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.
|
// prv is the local client's private key.
|
||||||
// token is the token from a previous session with this node.
|
// 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) {
|
func receiverEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, token []byte) (s secrets, err error) {
|
||||||
// read remote auth sent by initiator.
|
authMsg := new(authMsgV4)
|
||||||
auth := make([]byte, encAuthMsgLen)
|
authPacket, err := readHandshakeMsg(authMsg, encAuthMsgLen, prv, conn)
|
||||||
if _, err := io.ReadFull(conn, auth); err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
h, err := decodeAuthMsg(prv, token, auth)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
h := new(encHandshake)
|
||||||
|
if err := h.handleAuthMsg(authMsg, prv); err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
// send auth response
|
authRespMsg, err := h.makeAuthResp()
|
||||||
resp, err := h.authResp(prv, token)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return s, err
|
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 s, err
|
||||||
}
|
}
|
||||||
|
if _, err = conn.Write(authRespPacket); err != nil {
|
||||||
return h.secrets(auth, resp)
|
return s, err
|
||||||
|
}
|
||||||
|
return h.secrets(authPacket, authRespPacket)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeAuthMsg(prv *ecdsa.PrivateKey, token []byte, auth []byte) (*encHandshake, error) {
|
func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error {
|
||||||
var err error
|
// Import the remote identity.
|
||||||
h := new(encHandshake)
|
h.initNonce = msg.Nonce[:]
|
||||||
// generate random keypair for session
|
h.remoteID = msg.InitiatorPubkey
|
||||||
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
rpub, err := h.remoteID.Pubkey()
|
||||||
if err != nil {
|
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)
|
h.respNonce = make([]byte, shaLen)
|
||||||
if _, err = rand.Read(h.respNonce); err != nil {
|
if _, err = rand.Read(h.respNonce); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := crypto.Decrypt(prv, auth)
|
msg = new(authRespV4)
|
||||||
if err != nil {
|
copy(msg.Nonce[:], h.respNonce)
|
||||||
return nil, fmt.Errorf("could not decrypt auth message (%v)", err)
|
copy(msg.RandomPubkey[:], exportPubkey(&h.randomPrivKey.PublicKey))
|
||||||
}
|
msg.Version = 4
|
||||||
|
return msg, nil
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// authResp generates the encrypted authentication response message.
|
func (msg *authMsgV4) sealPlain(h *encHandshake) ([]byte, error) {
|
||||||
func (h *encHandshake) authResp(prv *ecdsa.PrivateKey, token []byte) ([]byte, error) {
|
buf := make([]byte, authMsgLen)
|
||||||
// responder auth message
|
n := copy(buf, msg.Signature[:])
|
||||||
// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
|
n += copy(buf[n:], crypto.Sha3(exportPubkey(&h.randomPrivKey.PublicKey)))
|
||||||
resp := make([]byte, authRespLen)
|
n += copy(buf[n:], msg.InitiatorPubkey[:])
|
||||||
n := copy(resp, exportPubkey(&h.randomPrivKey.PublicKey))
|
n += copy(buf[n:], msg.Nonce[:])
|
||||||
n += copy(resp[n:], h.respNonce)
|
buf[n] = 0 // token-flag
|
||||||
if token == nil {
|
return ecies.Encrypt(rand.Reader, h.remotePub, buf, nil, nil)
|
||||||
resp[n] = 0
|
}
|
||||||
} else {
|
|
||||||
resp[n] = 1
|
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
|
// pad with random amount of data. the amount needs to be at least 100 bytes to make
|
||||||
return ecies.Encrypt(rand.Reader, h.remotePub, resp, nil, nil)
|
// 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.
|
// 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))
|
return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey))
|
||||||
}
|
}
|
||||||
// TODO: fewer pointless conversions
|
// 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 {
|
func exportPubkey(pub *ecies.PublicKey) []byte {
|
||||||
|
235
p2p/rlpx_test.go
235
p2p/rlpx_test.go
@ -21,6 +21,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -160,6 +161,7 @@ func TestProtocolHandshake(t *testing.T) {
|
|||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
defer fd1.Close()
|
||||||
rlpx := newRLPX(fd0)
|
rlpx := newRLPX(fd0)
|
||||||
remid, err := rlpx.doEncHandshake(prv0, node1)
|
remid, err := rlpx.doEncHandshake(prv0, node1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -176,6 +178,7 @@ func TestProtocolHandshake(t *testing.T) {
|
|||||||
t.Errorf("dial side proto handshake error: %v", err)
|
t.Errorf("dial side proto handshake error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
phs.Rest = nil
|
||||||
if !reflect.DeepEqual(phs, hs1) {
|
if !reflect.DeepEqual(phs, hs1) {
|
||||||
t.Errorf("dial side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs1))
|
t.Errorf("dial side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs1))
|
||||||
return
|
return
|
||||||
@ -184,6 +187,7 @@ func TestProtocolHandshake(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
defer fd1.Close()
|
||||||
rlpx := newRLPX(fd1)
|
rlpx := newRLPX(fd1)
|
||||||
remid, err := rlpx.doEncHandshake(prv1, nil)
|
remid, err := rlpx.doEncHandshake(prv1, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -200,6 +204,7 @@ func TestProtocolHandshake(t *testing.T) {
|
|||||||
t.Errorf("listen side proto handshake error: %v", err)
|
t.Errorf("listen side proto handshake error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
phs.Rest = nil
|
||||||
if !reflect.DeepEqual(phs, hs0) {
|
if !reflect.DeepEqual(phs, hs0) {
|
||||||
t.Errorf("listen side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs0))
|
t.Errorf("listen side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs0))
|
||||||
return
|
return
|
||||||
@ -214,7 +219,6 @@ func TestProtocolHandshake(t *testing.T) {
|
|||||||
|
|
||||||
func TestProtocolHandshakeErrors(t *testing.T) {
|
func TestProtocolHandshakeErrors(t *testing.T) {
|
||||||
our := &protoHandshake{Version: 3, Caps: []Cap{{"foo", 2}, {"bar", 3}}, Name: "quux"}
|
our := &protoHandshake{Version: 3, Caps: []Cap{{"foo", 2}, {"bar", 3}}, Name: "quux"}
|
||||||
id := randomID()
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
code uint64
|
code uint64
|
||||||
msg interface{}
|
msg interface{}
|
||||||
@ -240,11 +244,6 @@ func TestProtocolHandshakeErrors(t *testing.T) {
|
|||||||
msg: []byte{1, 2, 3},
|
msg: []byte{1, 2, 3},
|
||||||
err: newPeerError(errInvalidMsg, "(code 0) (size 4) rlp: expected input list for p2p.protoHandshake"),
|
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,
|
code: handshakeMsg,
|
||||||
msg: &protoHandshake{Version: 3},
|
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.
|
MaximumExtraDataSize = big.NewInt(32) // Maximum size extra data may be after Genesis.
|
||||||
ExpByteGas = big.NewInt(10) // Times ceil(log256(exponent)) for the EXP instruction.
|
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.
|
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.
|
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.
|
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.
|
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.
|
QuadCoeffDiv = big.NewInt(512) // Divisor for the quadratic particle of the memory cost equation.
|
||||||
@ -40,7 +41,7 @@ var (
|
|||||||
Sha256WordGas = big.NewInt(12) //
|
Sha256WordGas = big.NewInt(12) //
|
||||||
|
|
||||||
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
|
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.
|
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
|
||||||
Sha256Gas = big.NewInt(60) //
|
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
|
// must contain an element for each decoded field. Decode returns an
|
||||||
// error if there are too few or too many elements.
|
// error if there are too few or too many elements.
|
||||||
//
|
//
|
||||||
// The decoding of struct fields honours one particular struct tag,
|
// The decoding of struct fields honours two struct tags, "tail" and
|
||||||
// "nil". This tag applies to pointer-typed fields and changes the
|
// "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
|
// 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
|
// decode as a nil pointer. This tag can be useful when decoding
|
||||||
// types.
|
// recursive types.
|
||||||
//
|
//
|
||||||
// type StructWithEmptyOK struct {
|
// type StructWithEmptyOK struct {
|
||||||
// Foo *[20]byte `rlp:"nil"`
|
// Foo *[20]byte `rlp:"nil"`
|
||||||
@ -190,7 +191,7 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
|
|||||||
case kind == reflect.String:
|
case kind == reflect.String:
|
||||||
return decodeString, nil
|
return decodeString, nil
|
||||||
case kind == reflect.Slice || kind == reflect.Array:
|
case kind == reflect.Slice || kind == reflect.Array:
|
||||||
return makeListDecoder(typ)
|
return makeListDecoder(typ, tags)
|
||||||
case kind == reflect.Struct:
|
case kind == reflect.Struct:
|
||||||
return makeStructDecoder(typ)
|
return makeStructDecoder(typ)
|
||||||
case kind == reflect.Ptr:
|
case kind == reflect.Ptr:
|
||||||
@ -264,7 +265,7 @@ func decodeBigInt(s *Stream, val reflect.Value) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeListDecoder(typ reflect.Type) (decoder, error) {
|
func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) {
|
||||||
etype := typ.Elem()
|
etype := typ.Elem()
|
||||||
if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) {
|
if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) {
|
||||||
if typ.Kind() == reflect.Array {
|
if typ.Kind() == reflect.Array {
|
||||||
@ -277,15 +278,26 @@ func makeListDecoder(typ reflect.Type) (decoder, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
var dec decoder
|
||||||
isArray := typ.Kind() == reflect.Array
|
switch {
|
||||||
return func(s *Stream, val reflect.Value) error {
|
case typ.Kind() == reflect.Array:
|
||||||
if isArray {
|
dec = func(s *Stream, val reflect.Value) error {
|
||||||
return decodeListArray(s, val, etypeinfo.decoder)
|
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)
|
return decodeListSlice(s, val, etypeinfo.decoder)
|
||||||
}
|
}
|
||||||
}, nil
|
}
|
||||||
|
return dec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
|
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))
|
val.Set(reflect.MakeSlice(val.Type(), 0, 0))
|
||||||
return s.ListEnd()
|
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
|
i := 0
|
||||||
for ; ; i++ {
|
for ; ; i++ {
|
||||||
// grow slice if necessary
|
// grow slice if necessary
|
||||||
@ -323,12 +341,11 @@ func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
|
|||||||
if i < val.Len() {
|
if i < val.Len() {
|
||||||
val.SetLen(i)
|
val.SetLen(i)
|
||||||
}
|
}
|
||||||
return s.ListEnd()
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error {
|
func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error {
|
||||||
_, err := s.List()
|
if _, err := s.List(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return wrapStreamError(err, val.Type())
|
return wrapStreamError(err, val.Type())
|
||||||
}
|
}
|
||||||
vlen := val.Len()
|
vlen := val.Len()
|
||||||
@ -398,11 +415,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dec := func(s *Stream, val reflect.Value) (err error) {
|
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)
|
return wrapStreamError(err, typ)
|
||||||
}
|
}
|
||||||
for _, f := range fields {
|
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 {
|
if err == EOL {
|
||||||
return &decodeError{msg: "too few elements", typ: typ}
|
return &decodeError{msg: "too few elements", typ: typ}
|
||||||
} else if err != nil {
|
} 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"`
|
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 (
|
var (
|
||||||
veryBigInt = big.NewInt(0).Add(
|
veryBigInt = big.NewInt(0).Add(
|
||||||
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
|
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
|
||||||
@ -437,6 +457,38 @@ var decodeTests = []decodeTest{
|
|||||||
ptr: new(recstruct),
|
ptr: new(recstruct),
|
||||||
error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I",
|
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
|
// RawValue
|
||||||
{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
|
{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
|
||||||
|
@ -345,7 +345,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// makeWriter creates a writer function for the given type.
|
// 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()
|
kind := typ.Kind()
|
||||||
switch {
|
switch {
|
||||||
case typ == rawValueType:
|
case typ == rawValueType:
|
||||||
@ -371,7 +371,7 @@ func makeWriter(typ reflect.Type) (writer, error) {
|
|||||||
case kind == reflect.Array && isByte(typ.Elem()):
|
case kind == reflect.Array && isByte(typ.Elem()):
|
||||||
return writeByteArray, nil
|
return writeByteArray, nil
|
||||||
case kind == reflect.Slice || kind == reflect.Array:
|
case kind == reflect.Slice || kind == reflect.Array:
|
||||||
return makeSliceWriter(typ)
|
return makeSliceWriter(typ, ts)
|
||||||
case kind == reflect.Struct:
|
case kind == reflect.Struct:
|
||||||
return makeStructWriter(typ)
|
return makeStructWriter(typ)
|
||||||
case kind == reflect.Ptr:
|
case kind == reflect.Ptr:
|
||||||
@ -507,20 +507,21 @@ func writeInterface(val reflect.Value, w *encbuf) error {
|
|||||||
return ti.writer(eval, w)
|
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{})
|
etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
writer := func(val reflect.Value, w *encbuf) error {
|
writer := func(val reflect.Value, w *encbuf) error {
|
||||||
lh := w.list()
|
if !ts.tail {
|
||||||
|
defer w.listEnd(w.list())
|
||||||
|
}
|
||||||
vlen := val.Len()
|
vlen := val.Len()
|
||||||
for i := 0; i < vlen; i++ {
|
for i := 0; i < vlen; i++ {
|
||||||
if err := etypeinfo.writer(val.Index(i), w); err != nil {
|
if err := etypeinfo.writer(val.Index(i), w); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.listEnd(lh)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return writer, nil
|
return writer, nil
|
||||||
|
@ -214,6 +214,10 @@ var encTests = []encTest{
|
|||||||
{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
|
{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
|
||||||
{val: &recstruct{5, nil}, output: "C205C0"},
|
{val: &recstruct{5, nil}, output: "C205C0"},
|
||||||
{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
|
{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
|
// nil
|
||||||
{val: (*uint)(nil), output: "80"},
|
{val: (*uint)(nil), output: "80"},
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
package rlp
|
package rlp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,7 +35,13 @@ type typeinfo struct {
|
|||||||
|
|
||||||
// represents struct tags
|
// represents struct tags
|
||||||
type tags struct {
|
type tags struct {
|
||||||
|
// rlp:"nil" controls whether empty input results in a nil pointer.
|
||||||
nilOK bool
|
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 {
|
type typekey struct {
|
||||||
@ -89,7 +97,10 @@ type field struct {
|
|||||||
func structFields(typ reflect.Type) (fields []field, err error) {
|
func structFields(typ reflect.Type) (fields []field, err error) {
|
||||||
for i := 0; i < typ.NumField(); i++ {
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
if f := typ.Field(i); f.PkgPath == "" { // exported
|
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)
|
info, err := cachedTypeInfo1(f.Type, tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -100,8 +111,27 @@ func structFields(typ reflect.Type) (fields []field, err error) {
|
|||||||
return fields, nil
|
return fields, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStructTag(tag string) tags {
|
func parseStructTag(typ reflect.Type, fi int) (tags, error) {
|
||||||
return tags{nilOK: tag == "nil"}
|
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) {
|
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 {
|
if info.decoder, err = makeDecoder(typ, tags); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if info.writer, err = makeWriter(typ); err != nil {
|
if info.writer, err = makeWriter(typ, tags); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
|
@ -661,7 +661,7 @@ func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
|
|||||||
|
|
||||||
pending := self.ethereum.TxPool().GetTransactions()
|
pending := self.ethereum.TxPool().GetTransactions()
|
||||||
for _, p := range pending {
|
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))
|
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)
|
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
|
var ltxs []*tx
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
if from, _ := tx.From(); accountSet.Has(from) {
|
if from, _ := tx.FromFrontier(); accountSet.Has(from) {
|
||||||
ltxs = append(ltxs, newTx(tx))
|
ltxs = append(ltxs, newTx(tx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes {
|
|||||||
// v.BlockHash =
|
// v.BlockHash =
|
||||||
// v.BlockNumber =
|
// v.BlockNumber =
|
||||||
// v.TxIndex =
|
// v.TxIndex =
|
||||||
from, _ := tx.From()
|
from, _ := tx.FromFrontier()
|
||||||
v.From = newHexData(from)
|
v.From = newHexData(from)
|
||||||
v.To = newHexData(tx.To())
|
v.To = newHexData(tx.To())
|
||||||
v.Value = newHexNum(tx.Value())
|
v.Value = newHexNum(tx.Value())
|
||||||
|
@ -17,11 +17,15 @@
|
|||||||
package tests
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBcValidBlockTests(t *testing.T) {
|
func TestBcValidBlockTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -29,6 +33,7 @@ func TestBcValidBlockTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcUncleHeaderValidityTests(t *testing.T) {
|
func TestBcUncleHeaderValidityTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -36,6 +41,7 @@ func TestBcUncleHeaderValidityTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcUncleTests(t *testing.T) {
|
func TestBcUncleTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -43,6 +49,7 @@ func TestBcUncleTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcForkUncleTests(t *testing.T) {
|
func TestBcForkUncleTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -50,6 +57,7 @@ func TestBcForkUncleTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcInvalidHeaderTests(t *testing.T) {
|
func TestBcInvalidHeaderTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -57,6 +65,7 @@ func TestBcInvalidHeaderTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcInvalidRLPTests(t *testing.T) {
|
func TestBcInvalidRLPTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -64,6 +73,7 @@ func TestBcInvalidRLPTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcRPCAPITests(t *testing.T) {
|
func TestBcRPCAPITests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -71,6 +81,7 @@ func TestBcRPCAPITests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcForkBlockTests(t *testing.T) {
|
func TestBcForkBlockTests(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -78,6 +89,7 @@ func TestBcForkBlockTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcForkStress(t *testing.T) {
|
func TestBcForkStress(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -85,6 +97,10 @@ func TestBcForkStress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcTotalDifficulty(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)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -92,6 +108,7 @@ func TestBcTotalDifficulty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcWallet(t *testing.T) {
|
func TestBcWallet(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -99,6 +116,7 @@ func TestBcWallet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcGasPricer(t *testing.T) {
|
func TestBcGasPricer(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -107,6 +125,7 @@ func TestBcGasPricer(t *testing.T) {
|
|||||||
|
|
||||||
// TODO: iterate over files once we got more than a few
|
// TODO: iterate over files once we got more than a few
|
||||||
func TestBcRandom(t *testing.T) {
|
func TestBcRandom(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -114,6 +133,10 @@ func TestBcRandom(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcMultiChain(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)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -121,8 +144,98 @@ func TestBcMultiChain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcState(t *testing.T) {
|
func TestBcState(t *testing.T) {
|
||||||
|
params.HomesteadBlock = big.NewInt(1000000)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
|
err := RunBlockTest(filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
for name, test := range bt {
|
||||||
// if the test should be skipped, return
|
|
||||||
if skipTest[name] {
|
if skipTest[name] {
|
||||||
glog.Infoln("Skipping block test", name)
|
glog.Infoln("Skipping block test", name)
|
||||||
continue
|
continue
|
||||||
@ -192,6 +191,7 @@ func runBlockTest(test *BlockTest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cm := ethereum.BlockChain()
|
cm := ethereum.BlockChain()
|
||||||
|
//vm.Debug = true
|
||||||
validBlocks, err := test.TryBlocksInsert(cm)
|
validBlocks, err := test.TryBlocksInsert(cm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -292,12 +292,13 @@ func (t *BlockTest) TryBlocksInsert(blockchain *core.BlockChain) ([]btBlock, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// RLP decoding worked, try to insert into chain:
|
// 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 err != nil {
|
||||||
if b.BlockHeader == nil {
|
if b.BlockHeader == nil {
|
||||||
continue // OK - block is supposed to be invalid, continue with next block
|
continue // OK - block is supposed to be invalid, continue with next block
|
||||||
} else {
|
} 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 {
|
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
56
tests/files/BlockchainTests/bcBlockGasLimitTest.json
Normal file → Executable file
56
tests/files/BlockchainTests/bcBlockGasLimitTest.json
Normal file → Executable file
@ -9,18 +9,18 @@
|
|||||||
"extraData" : "0x",
|
"extraData" : "0x",
|
||||||
"gasLimit" : "0x023ec6",
|
"gasLimit" : "0x023ec6",
|
||||||
"gasUsed" : "0x021536",
|
"gasUsed" : "0x021536",
|
||||||
"hash" : "e433cd38b3d31279392499dd9e4c4969afe85d52a2bf1c3f728e787526d20b57",
|
"hash" : "f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3",
|
||||||
"mixHash" : "cf4ed8d7669d68dc3662bacaf5420eff1dba962056d1268a84b592851802a11f",
|
"mixHash" : "29f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3",
|
||||||
"nonce" : "99ac9fa654859890",
|
"nonce" : "8957e6d004a31802",
|
||||||
"number" : "0x01",
|
"number" : "0x01",
|
||||||
"parentHash" : "502a4f910dd14c9167d304f1e20a3587085b310a2c01ea7e9670c228edbeb11e",
|
"parentHash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||||
"receiptTrie" : "5c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7",
|
"receiptTrie" : "5c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7",
|
||||||
"stateRoot" : "a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4",
|
"stateRoot" : "a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4",
|
||||||
"timestamp" : "0x561bc63a",
|
"timestamp" : "0x56851097",
|
||||||
"transactionsTrie" : "70616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2",
|
"transactionsTrie" : "70616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2",
|
||||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||||
},
|
},
|
||||||
"rlp" : "0xf904a8f901faa0502a4f910dd14c9167d304f1e20a3587085b310a2c01ea7e9670c228edbeb11ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec68302153684561bc63a80a0cf4ed8d7669d68dc3662bacaf5420eff1dba962056d1268a84b592851802a11f8899ac9fa654859890f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0",
|
"rlp" : "0xf904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec683021536845685109780a029f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3888957e6d004a31802f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0",
|
||||||
"transactions" : [
|
"transactions" : [
|
||||||
{
|
{
|
||||||
"data" : "0x",
|
"data" : "0x",
|
||||||
@ -111,9 +111,9 @@
|
|||||||
"extraData" : "0x42",
|
"extraData" : "0x42",
|
||||||
"gasLimit" : "0x023e38",
|
"gasLimit" : "0x023e38",
|
||||||
"gasUsed" : "0x00",
|
"gasUsed" : "0x00",
|
||||||
"hash" : "502a4f910dd14c9167d304f1e20a3587085b310a2c01ea7e9670c228edbeb11e",
|
"hash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||||
"mixHash" : "e22e898463379d46e98deeb6fe2cdda27f6fdc6f4b42838302dd0b4891282012",
|
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"nonce" : "99f1fc570eb39f57",
|
"nonce" : "0102030405060708",
|
||||||
"number" : "0x00",
|
"number" : "0x00",
|
||||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
@ -122,8 +122,8 @@
|
|||||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||||
},
|
},
|
||||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a0e22e898463379d46e98deeb6fe2cdda27f6fdc6f4b42838302dd0b48912820128899f1fc570eb39f57c0c0",
|
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||||
"lastblockhash" : "e433cd38b3d31279392499dd9e4c4969afe85d52a2bf1c3f728e787526d20b57",
|
"lastblockhash" : "f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3",
|
||||||
"postState" : {
|
"postState" : {
|
||||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||||
"balance" : "0x456391824508d41c",
|
"balance" : "0x456391824508d41c",
|
||||||
@ -167,7 +167,7 @@
|
|||||||
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideLast" : {
|
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideLast" : {
|
||||||
"blocks" : [
|
"blocks" : [
|
||||||
{
|
{
|
||||||
"rlp" : "0xf904a8f901faa0a88789a0ebcf96c1a73705b60cfe4ed947855ffe669f3f9d4366403dd58ed17aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a039b55901ee38a65fa27c7d60137fd431afcf6a7615746ae9501e7cf0ca68bd11a0b19fdedc6b45294e091f08780e0e51b746e43897ab98eaf872d180e0cb157cceb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023dd48302153684561bc63d80a0eb5133a15a92e24f07d494e4a1cbc72e9a3d8fa5cadcb6149f406c89fb2c3bfe88ea027ba286f8d5b2f902a7f85f800a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba01117bd549fe17f8383012bf168dabd9e70851fdf2f332e5bfea89318dddd6c77a001364d3a0e23f462052127c53a5473c428e2211806c927601562f840eb6b899cf85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0c40c1300a7cc64b842c9421a6c6e985b5531020d1a26c82f9c6a5200154e91dfa052c28fc6dc0dad9ea23fcce6510a9dc23b9903b1b19a126ac25f77a195b50f83c0"
|
"rlp" : "0xf904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a039b55901ee38a65fa27c7d60137fd431afcf6a7615746ae9501e7cf0ca68bd11a0b19fdedc6b45294e091f08780e0e51b746e43897ab98eaf872d180e0cb157cceb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023dd483021536845685109980a0dd3fe9b9d559e9c7cfa71c1418941ab7f3e2240de7415a7cbbfc6c678572b2408830f179ce6b7e4be7f902a7f85f800a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba01117bd549fe17f8383012bf168dabd9e70851fdf2f332e5bfea89318dddd6c77a001364d3a0e23f462052127c53a5473c428e2211806c927601562f840eb6b899cf85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0c40c1300a7cc64b842c9421a6c6e985b5531020d1a26c82f9c6a5200154e91dfa052c28fc6dc0dad9ea23fcce6510a9dc23b9903b1b19a126ac25f77a195b50f83c0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"genesisBlockHeader" : {
|
"genesisBlockHeader" : {
|
||||||
@ -177,9 +177,9 @@
|
|||||||
"extraData" : "0x42",
|
"extraData" : "0x42",
|
||||||
"gasLimit" : "0x023e38",
|
"gasLimit" : "0x023e38",
|
||||||
"gasUsed" : "0x00",
|
"gasUsed" : "0x00",
|
||||||
"hash" : "a88789a0ebcf96c1a73705b60cfe4ed947855ffe669f3f9d4366403dd58ed17a",
|
"hash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||||
"mixHash" : "5e365a8d2f4c91e9d67a88b440da630433fc08b484e89e32b01771cd8b7f85c9",
|
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"nonce" : "3f12cb80e372f8b4",
|
"nonce" : "0102030405060708",
|
||||||
"number" : "0x00",
|
"number" : "0x00",
|
||||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
@ -188,8 +188,8 @@
|
|||||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||||
},
|
},
|
||||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a05e365a8d2f4c91e9d67a88b440da630433fc08b484e89e32b01771cd8b7f85c9883f12cb80e372f8b4c0c0",
|
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||||
"lastblockhash" : "a88789a0ebcf96c1a73705b60cfe4ed947855ffe669f3f9d4366403dd58ed17a",
|
"lastblockhash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
|
||||||
"postState" : {
|
"postState" : {
|
||||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
"balance" : "0x4a723dc6b40b8a9a000000",
|
"balance" : "0x4a723dc6b40b8a9a000000",
|
||||||
@ -233,18 +233,18 @@
|
|||||||
"extraData" : "0x",
|
"extraData" : "0x",
|
||||||
"gasLimit" : "0x01e8c1",
|
"gasLimit" : "0x01e8c1",
|
||||||
"gasUsed" : "0x2906",
|
"gasUsed" : "0x2906",
|
||||||
"hash" : "d2263099eaafae9d7f4dcbd94d70d87a2584458a2255720379f4c72873feeee6",
|
"hash" : "457fb9c19f1b1719cc3a709ca0b2ee8f1614c20821c2e8892baa42d6ac5cac7a",
|
||||||
"mixHash" : "4905ceb4acb4d5f6f205b0205f7c95d343f5be46001505d738508d0cc7cc86ba",
|
"mixHash" : "16528eced6a9959df657e8bb4325efad00ce3a8077edf3cc4b6effd4c67e863e",
|
||||||
"nonce" : "4e1a3c143f09f0d2",
|
"nonce" : "f45f14f56d3ccefc",
|
||||||
"number" : "0x01",
|
"number" : "0x01",
|
||||||
"parentHash" : "5da0c900a0fb0958f01c630526a773c426ec8e49a0317af49251a8fc41971bf2",
|
"parentHash" : "926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921d",
|
||||||
"receiptTrie" : "bc1ca7335ccb32ac45ecd0ef287eb7f2323801a695f23a3d241e6a2cf0b4a9af",
|
"receiptTrie" : "bc1ca7335ccb32ac45ecd0ef287eb7f2323801a695f23a3d241e6a2cf0b4a9af",
|
||||||
"stateRoot" : "00a62f7cedb73f6ce84dc4e27a983adf20bb45553b11d1bb11b5f18fe450542d",
|
"stateRoot" : "00a62f7cedb73f6ce84dc4e27a983adf20bb45553b11d1bb11b5f18fe450542d",
|
||||||
"timestamp" : "0x561bc63f",
|
"timestamp" : "0x5685109c",
|
||||||
"transactionsTrie" : "f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5",
|
"transactionsTrie" : "f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5",
|
||||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||||
},
|
},
|
||||||
"rlp" : "0xf90261f901f9a05da0c900a0fb0958f01c630526a773c426ec8e49a0317af49251a8fc41971bf2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a000a62f7cedb73f6ce84dc4e27a983adf20bb45553b11d1bb11b5f18fe450542da0f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5a0bc1ca7335ccb32ac45ecd0ef287eb7f2323801a695f23a3d241e6a2cf0b4a9afb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018301e8c182290684561bc63f80a04905ceb4acb4d5f6f205b0205f7c95d343f5be46001505d738508d0cc7cc86ba884e1a3c143f09f0d2f862f860800a830186a094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0444ed2cb67c1cce2c37add4bef48d3dda9ef05e28eaf023006036a4c5f7c96b0a00c56b07bfc50471d458e67923c91108b90cb7bba23f4d373f0a75632a413bd84c0",
|
"rlp" : "0xf90261f901f9a0926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a000a62f7cedb73f6ce84dc4e27a983adf20bb45553b11d1bb11b5f18fe450542da0f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5a0bc1ca7335ccb32ac45ecd0ef287eb7f2323801a695f23a3d241e6a2cf0b4a9afb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018301e8c1822906845685109c80a016528eced6a9959df657e8bb4325efad00ce3a8077edf3cc4b6effd4c67e863e88f45f14f56d3ccefcf862f860800a830186a094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0444ed2cb67c1cce2c37add4bef48d3dda9ef05e28eaf023006036a4c5f7c96b0a00c56b07bfc50471d458e67923c91108b90cb7bba23f4d373f0a75632a413bd84c0",
|
||||||
"transactions" : [
|
"transactions" : [
|
||||||
{
|
{
|
||||||
"data" : "0x",
|
"data" : "0x",
|
||||||
@ -269,9 +269,9 @@
|
|||||||
"extraData" : "0x42",
|
"extraData" : "0x42",
|
||||||
"gasLimit" : "0x01e848",
|
"gasLimit" : "0x01e848",
|
||||||
"gasUsed" : "0x00",
|
"gasUsed" : "0x00",
|
||||||
"hash" : "5da0c900a0fb0958f01c630526a773c426ec8e49a0317af49251a8fc41971bf2",
|
"hash" : "926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921d",
|
||||||
"mixHash" : "ee942ca5af3fecd8e5b9fc741d1f01db0f59159124d4808abea087bc1f90bb73",
|
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"nonce" : "73e16454e5ece703",
|
"nonce" : "0102030405060708",
|
||||||
"number" : "0x00",
|
"number" : "0x00",
|
||||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
@ -280,8 +280,8 @@
|
|||||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||||
},
|
},
|
||||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808301e848808454c98c8142a0ee942ca5af3fecd8e5b9fc741d1f01db0f59159124d4808abea087bc1f90bb738873e16454e5ece703c0c0",
|
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808301e848808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
|
||||||
"lastblockhash" : "d2263099eaafae9d7f4dcbd94d70d87a2584458a2255720379f4c72873feeee6",
|
"lastblockhash" : "457fb9c19f1b1719cc3a709ca0b2ee8f1614c20821c2e8892baa42d6ac5cac7a",
|
||||||
"postState" : {
|
"postState" : {
|
||||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||||
"balance" : "0x4563918244f59a3c",
|
"balance" : "0x4563918244f59a3c",
|
||||||
|
0
tests/files/BlockchainTests/bcForkBlockTest.json
Normal file → Executable file
0
tests/files/BlockchainTests/bcForkBlockTest.json
Normal file → Executable file
4252
tests/files/BlockchainTests/bcForkStressTest.json
Normal file → Executable file
4252
tests/files/BlockchainTests/bcForkStressTest.json
Normal file → 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
Loading…
x
Reference in New Issue
Block a user