Compare commits

...

36 Commits

Author SHA1 Message Date
Jeffrey Wilcke
bf324bd24b VERSION, cmd/geth: bumped version number 1.3.6 2016-04-01 12:12:59 +02:00
Ramesh Nair
a2e1e5c6a0 [release/1.3.6]: cmd/utils: removed password line endings when not using liner.
(cherry picked from commit 6f300344135894970bc417285c2f45f723cd3aa5)
2016-04-01 12:10:02 +02:00
Jeffrey Wilcke
506c927791 Merge pull request #2343 from obscuren/issue-templates-master
templates: added issue template
2016-03-14 23:46:04 +01:00
Jeffrey Wilcke
c0673eefb1 templates: added issue template
(cherry picked from commit a0e2e22a4f61eab801b6fa0ac21ae32f634525cc)
2016-03-14 23:43:11 +01:00
Jeffrey Wilcke
34b622a248 Merge pull request #2287 from obscuren/release/1.3.5
Release/1.3.5
2016-03-03 15:22:12 +01:00
Jeffrey Wilcke
cab802b40f VERSION, cmd/geth: bumped version 1.3.5 2016-03-03 15:10:48 +01:00
Péter Szilágyi
869d9792b3 [release/1.3.5] eth: forward empty body responses to the downlaoder
(cherry picked from commit ae4982a365ae396f928c76e332777563c9cc6b40)
2016-03-03 15:10:32 +01:00
Felix Lange
d3f8b763bf VERSION: bumped version to 1.3.4 2016-02-29 20:57:48 +01:00
Jeffrey Wilcke
4044a8cea4 Merge pull request #2258 from obscuren/release/1.3.4
Homestead Release Candidate
2016-02-29 15:05:37 +01:00
Jeffrey Wilcke
61be63bb9b [release/1.3.4] cmd/utils, params: homestead block
(cherry picked from commit e22fd22c97b4f5d4af118dca3fb2cb6292a520a6)

Conflicts:
	cmd/utils/flags.go
2016-02-29 14:59:30 +01:00
Jeffrey Wilcke
5f7e74d5c8 [release/1.3.4] cmd/utils: lower the min accepted gas price for relay and GPO to 20 shannon
(cherry picked from commit ab92678fb39300d5823857a170be6638b1c2b2c5)
2016-02-29 14:59:20 +01:00
Péter Szilágyi
2be2842758 [release/1.3.4] eth/downloader: fix premature exit before notifying all part fetchers
(cherry picked from commit 64ee5763eebe7e57e761be840f0b80ed7be93ca7)
2016-02-29 13:44:34 +01:00
Felix Lange
c2df9d356a [release/1.3.4] crypto/secp256k1: remove dependency on libgmp
Turns out we actually don't need it, USE_NUM_NONE works
because we also set USE_FIELD_INV_BUILTIN.

Conflicts:
	Makefile
	crypto/secp256k1/secp256.go
2016-02-29 13:32:26 +01:00
Felix Lange
a4f4846fff [release/1.3.4] eth/downloader: fix header download limiting
Fixes #2201
(cherry picked from commit 26e72b2ccd728b00e08bd692bdd7241ff0bfe2cc)
2016-02-29 13:24:33 +01:00
Jeffrey Wilcke
7f83e68b13 [release/1.3.4] eth: fixed homestead tx check
When a block is queried for retrieval we should add a check whether the
block falls within the frontier rules. If we'd always use `From`
retrieving transaction might fail. This PR temporarily changes
everything to `FromFrontier` (safe!).

This is a backport of c616391df2dda2c21b0a8eed03531a7d44669421
2016-02-29 13:24:33 +01:00
Jeffrey Wilcke
5570b11398 [release/1.3.4] params: settle the Pi vs Tau dispute
This commit increases the artificial gas floor to 4712388
(cherry picked from commit f954a8b6660792cce6e4e44a204b01a2dac87d0d)
2016-02-29 13:24:33 +01:00
Jeffrey Wilcke
e7fb300053 [release/1.3.4] cmd/geth: bump version v1.3.4 2016-02-29 13:24:32 +01:00
Jeffrey Wilcke
4e0fe48e20 [release/1.3.4] xeth: backward fix for messages 2016-02-24 13:46:37 +01:00
Jeffrey Wilcke
bcf565730b [release/1.3.4] core: Added new TD strategy which mitigate the risk for selfish mining
Assuming the following scenario where a miner has 15% of all hashing
power and the ability to exert a moderate control over the network to
the point where if the attacker sees a message A, it can't stop A from
propagating, but what it **can** do is send a message B and ensure that
most nodes see B before A. The attacker can then selfish mine and
augment selfish mining strategy by giving his own blocks an advantage.

This change makes the time at which a block is received less relevant
and so the level of control an attacker has over the network no longer
makes a difference.

This change changes the current td algorithm `B_td > C_td` to the new
algorithm `B_td > C_td || B_td == C_td && rnd < 0.5`.
2016-02-24 13:46:33 +01:00
Jeffrey Wilcke
587bafaa9f [release/1.3.4] core, core/vm, crypto: fixes for homestead
* Removed some strange code that didn't apply state reverting properly
* Refactored code setting from vm & state transition to the executioner
* Updated tests

Conflicts:
	common/registrar/ethreg/api.go
	core/tx_pool.go
	core/vm/jit_test.go
2016-02-24 13:46:30 +01:00
Jeffrey Wilcke
7bb496f737 [release/1.3.4] tests: updated homestead tests 2016-02-24 13:46:23 +01:00
Gustav Simonsson
61404979ed [release/1.3.4] parmas, crypto, core, core/vm: homestead consensus protocol changes
* change gas cost for contract creating txs
* invalidate signature with s value greater than secp256k1 N / 2
* OOG contract creation if not enough gas to store code
* new difficulty adjustment algorithm
* new DELEGATECALL op code

Conflicts:
	core/vm/environment.go
	crypto/crypto.go
	crypto/secp256k1/secp256.go
	eth/api.go
2016-02-24 13:46:11 +01:00
Péter Szilágyi
300f1e2abf [release/1.3.4] core, core/types, miner: fix transaction nonce-price combo sort 2016-02-24 13:46:06 +01:00
Felix Lange
4ce7970340 [release/1.3.4] p2p/discover: fix Windows-specific issue for larger-than-buffer packets
On Windows, UDPConn.ReadFrom returns an error for packets larger
than the receive buffer. The error is not marked temporary, causing
our loop to exit when the first oversized packet arrived. The fix
is to treat this particular error as temporary.

Fixes: #1579, #2087
Updates: #2082

Conflicts:
	p2p/discover/udp_test.go
2016-02-24 13:46:03 +01:00
Jeffrey Wilcke
0c17be92fb [release/1.3.4] p2p: backward fix for S256 curve 2016-02-24 13:45:59 +01:00
Felix Lange
b5a0cf488c [release/1.3.4] p2p: EIP-8 changes
Conflicts:
	p2p/rlpx.go
2016-02-24 13:45:56 +01:00
Felix Lange
b25da7c3f4 [release/1.3.4] p2p/discover: EIP-8 changes
Conflicts:
	p2p/discover/udp_test.go
2016-02-24 13:45:53 +01:00
Felix Lange
93077941d3 [release/1.3.4] rlp: add "tail" struct tag 2016-02-24 13:44:56 +01:00
Felix Lange
8cb69b9e9b [release/1.3.4] crypto/ecies: make authenticated shared data work
The s2 parameter was not actually written to the MAC.
2016-02-24 13:44:37 +01:00
Jeffrey Wilcke
c541b38fb3 VERSION, cmd/geth: bumped version number 1.3.3 2016-01-05 13:02:07 +01:00
Péter Szilágyi
336a4d7b8d core: fix transaction reorg issues within the tx pool 2016-01-05 13:02:07 +01:00
Péter Szilágyi
8938768f75 core, eth/downloader: ensure state presence in ancestor lookup 2016-01-05 12:31:45 +01:00
Jeffrey Wilcke
5490437942 Merge branch 'develop' into release/1.3.2
Conflicts:
	VERSION
	cmd/geth/main.go
2015-11-24 13:48:47 +01:00
Jeffrey Wilcke
e5532154a5 Merge branch 'release/1.3.0'
Conflicts:
	VERSION
	cmd/geth/main.go
2015-11-03 11:47:07 +01:00
Jeffrey Wilcke
f75becc264 cmd/geth, VERSION: bumped version 1.3.1 2015-10-31 20:00:58 +01:00
Jeffrey Wilcke
9666db2a44 VERSION, cmd/geth: bumped version 1.2.1 2015-10-01 10:38:43 +02:00
872 changed files with 197214 additions and 10828 deletions

20
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,20 @@
#### System information
Geth version: `geth version`
OS & Version: Windows/Linux/OSX
Commit hash : (if `develop`)
#### Expected behaviour
#### Actual behaviour
#### Steps to reproduce the behaviour
#### Backtrace
````
[backtrace]
````

View File

@ -20,10 +20,6 @@ env:
global:
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
sudo: false
addons:
apt:
packages:
- libgmp3-dev
notifications:
webhooks:
urls:

View File

@ -10,7 +10,7 @@
GOBIN = build/bin
CROSSDEPS = https://gmplib.org/download/gmp/gmp-6.0.0a.tar.bz2
MODE ?= default
GO ?= latest
geth:
@ -26,32 +26,51 @@ geth-linux: xgo geth-linux-arm geth-linux-386 geth-linux-amd64
@echo "Linux cross compilation done:"
@ls -l $(GOBIN)/geth-linux-*
geth-linux-arm: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/arm -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux ARM cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep arm
geth-linux-386: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/386 -v $(shell build/flags.sh) ./cmd/geth
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/386 -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux 386 cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep 386
geth-linux-amd64: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/amd64 -v $(shell build/flags.sh) ./cmd/geth
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/amd64 -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux amd64 cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep amd64
geth-darwin: xgo geth-darwin-386 geth-darwin-amd64
geth-linux-arm: geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
@echo "Linux ARM cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep arm
geth-linux-arm-5: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm-5 -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux ARMv5 cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep arm-5
geth-linux-arm-6: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm-6 -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux ARMv6 cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep arm-6
geth-linux-arm-7: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm-7 -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux ARMv7 cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep arm-7
geth-linux-arm64: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=linux/arm64 -v $(shell build/flags.sh) ./cmd/geth
@echo "Linux ARM64 cross compilation done:"
@ls -l $(GOBIN)/geth-linux-* | grep arm64
geth-darwin: geth-darwin-386 geth-darwin-amd64
@echo "Darwin cross compilation done:"
@ls -l $(GOBIN)/geth-darwin-*
geth-darwin-386: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=darwin/386 -v $(shell build/flags.sh) ./cmd/geth
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=darwin/386 -v $(shell build/flags.sh) ./cmd/geth
@echo "Darwin 386 cross compilation done:"
@ls -l $(GOBIN)/geth-darwin-* | grep 386
geth-darwin-amd64: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=darwin/amd64 -v $(shell build/flags.sh) ./cmd/geth
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=darwin/amd64 -v $(shell build/flags.sh) ./cmd/geth
@echo "Darwin amd64 cross compilation done:"
@ls -l $(GOBIN)/geth-darwin-* | grep amd64
@ -60,28 +79,33 @@ geth-windows: xgo geth-windows-386 geth-windows-amd64
@ls -l $(GOBIN)/geth-windows-*
geth-windows-386: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=windows/386 -v $(shell build/flags.sh) ./cmd/geth
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=windows/386 -v $(shell build/flags.sh) ./cmd/geth
@echo "Windows 386 cross compilation done:"
@ls -l $(GOBIN)/geth-windows-* | grep 386
geth-windows-amd64: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=windows/amd64 -v $(shell build/flags.sh) ./cmd/geth
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=windows/amd64 -v $(shell build/flags.sh) ./cmd/geth
@echo "Windows amd64 cross compilation done:"
@ls -l $(GOBIN)/geth-windows-* | grep amd64
geth-android: xgo geth-android-16 geth-android-21
geth-android: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=android/* -v $(shell build/flags.sh) ./cmd/geth
@echo "Android cross compilation done:"
@ls -l $(GOBIN)/geth-android-*
geth-android-16: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android-16/* -v $(shell build/flags.sh) ./cmd/geth
@echo "Android 16 cross compilation done:"
@ls -l $(GOBIN)/geth-android-16-*
geth-ios: geth-ios-arm-7 geth-ios-arm64
@echo "iOS cross compilation done:"
@ls -l $(GOBIN)/geth-ios-*
geth-android-21: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android-21/* -v $(shell build/flags.sh) ./cmd/geth
@echo "Android 21 cross compilation done:"
@ls -l $(GOBIN)/geth-android-21-*
geth-ios-arm-7: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=ios/arm-7 -v $(shell build/flags.sh) ./cmd/geth
@echo "iOS ARMv7 cross compilation done:"
@ls -l $(GOBIN)/geth-ios-* | grep arm-7
geth-ios-arm64: xgo
build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --targets=ios-7.0/arm64 -v $(shell build/flags.sh) ./cmd/geth
@echo "iOS ARM64 cross compilation done:"
@ls -l $(GOBIN)/geth-ios-* | grep arm64
evm:
build/env.sh $(GOROOT)/bin/go install -v $(shell build/flags.sh) ./cmd/evm

View File

@ -30,7 +30,7 @@ For prerequisites and detailed build instructions please read the
[Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum)
on the wiki.
Building geth requires two external dependencies, Go and GMP.
Building geth requires both a Go and a C compiler.
You can install them using your favourite package manager.
Once the dependencies are installed, run

View File

@ -1 +1 @@
1.4.0
1.3.6

View File

@ -225,10 +225,15 @@ func (self *VMEnv) Call(caller vm.ContractRef, addr common.Address, data []byte,
self.Gas = gas
return core.Call(self, caller, addr, data, gas, price, value)
}
func (self *VMEnv) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
return core.CallCode(self, caller, addr, data, gas, price, value)
}
func (self *VMEnv) DelegateCall(caller vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
return core.DelegateCall(self, caller, addr, data, gas, price)
}
func (self *VMEnv) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
return core.Create(self, caller, data, gas, price, value)
}

View File

@ -48,10 +48,10 @@ import (
const (
ClientIdentifier = "Geth"
Version = "1.4.0-unstable"
Version = "1.3.6"
VersionMajor = 1
VersionMinor = 4
VersionPatch = 0
VersionMinor = 3
VersionPatch = 6
)
var (

View File

@ -91,6 +91,7 @@ func PromptPassword(prompt string, warnTerm bool) (string, error) {
}
fmt.Print(prompt)
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
input = strings.TrimRight(input, "\r\n")
fmt.Println()
return input, err
}

View File

@ -183,7 +183,7 @@ var (
GasPriceFlag = cli.StringFlag{
Name: "gasprice",
Usage: "Minimal gas price to accept for mining a transactions",
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(),
}
ExtraDataFlag = cli.StringFlag{
Name: "extradata",
@ -356,7 +356,7 @@ var (
GpoMinGasPriceFlag = cli.StringFlag{
Name: "gpomin",
Usage: "Minimum suggested gas price",
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(),
}
GpoMaxGasPriceFlag = cli.StringFlag{
Name: "gpomax",
@ -472,6 +472,8 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
cfg.DataDir += "/testnet"
cfg.NetworkId = 2
cfg.TestNet = true
// overwrite homestead block
params.HomesteadBlock = params.TestNetHomesteadBlock
}
if ctx.GlobalBool(VMEnableJitFlag.Name) {

View File

@ -82,7 +82,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas := IntrinsicGas(data)
gas := IntrinsicGas(data, false, false)
tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(benchRootKey)
gen.AddTx(tx)
}

View File

@ -30,6 +30,12 @@ import (
"gopkg.in/fatih/set.v0"
)
var (
ExpDiffPeriod = big.NewInt(100000)
big10 = big.NewInt(10)
bigMinus99 = big.NewInt(-99)
)
// BlockValidator is responsible for validating block headers, uncles and
// processed state.
//
@ -111,7 +117,7 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
// For valid blocks this should always validate to true.
rbloom := types.CreateBloom(receipts)
if rbloom != header.Bloom {
return fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
return fmt.Errorf("unable to replicate block's bloom=%x vs calculated bloom=%x", header.Bloom, rbloom)
}
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
receiptSha := types.DeriveSha(receipts)
@ -241,3 +247,127 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
}
return nil
}
// CalcDifficulty is the difficulty adjustment algorithm. It returns
// the difficulty that a new block should have when created at time
// given the parent block's time and difficulty.
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
if params.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
} else {
return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
}
}
func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
// algorithm:
// diff = (parent_diff +
// (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
// ) + 2^(periodCount - 2)
bigTime := new(big.Int).SetUint64(time)
bigParentTime := new(big.Int).SetUint64(parentTime)
// holds intermediate values to make the algo easier to read & audit
x := new(big.Int)
y := new(big.Int)
// 1 - (block_timestamp -parent_timestamp) // 10
x.Sub(bigTime, bigParentTime)
x.Div(x, big10)
x.Sub(common.Big1, x)
// max(1 - (block_timestamp - parent_timestamp) // 10, -99)))
if x.Cmp(bigMinus99) < 0 {
x.Set(bigMinus99)
}
// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
y.Div(parentDiff, params.DifficultyBoundDivisor)
x.Mul(y, x)
x.Add(parentDiff, x)
// minimum difficulty can ever be (before exponential factor)
if x.Cmp(params.MinimumDifficulty) < 0 {
x = params.MinimumDifficulty
}
// for the exponential factor
periodCount := new(big.Int).Add(parentNumber, common.Big1)
periodCount.Div(periodCount, ExpDiffPeriod)
// the exponential factor, commonly refered to as "the bomb"
// diff = diff + 2^(periodCount - 2)
if periodCount.Cmp(common.Big1) > 0 {
y.Sub(periodCount, common.Big2)
y.Exp(common.Big2, y, nil)
x.Add(x, y)
}
return x
}
func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
diff := new(big.Int)
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
bigTime := new(big.Int)
bigParentTime := new(big.Int)
bigTime.SetUint64(time)
bigParentTime.SetUint64(parentTime)
if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
diff.Add(parentDiff, adjust)
} else {
diff.Sub(parentDiff, adjust)
}
if diff.Cmp(params.MinimumDifficulty) < 0 {
diff = params.MinimumDifficulty
}
periodCount := new(big.Int).Add(parentNumber, common.Big1)
periodCount.Div(periodCount, ExpDiffPeriod)
if periodCount.Cmp(common.Big1) > 0 {
// diff = diff + 2^(periodCount - 2)
expDiff := periodCount.Sub(periodCount, common.Big2)
expDiff.Exp(common.Big2, expDiff, nil)
diff.Add(diff, expDiff)
diff = common.BigMax(diff, params.MinimumDifficulty)
}
return diff
}
// CalcGasLimit computes the gas limit of the next block after parent.
// The result may be modified by the caller.
// This is miner strategy, not consensus protocol.
func CalcGasLimit(parent *types.Block) *big.Int {
// contrib = (parentGasUsed * 3 / 2) / 1024
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
contrib = contrib.Div(contrib, big.NewInt(2))
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
// decay = parentGasLimit / 1024 -1
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
decay.Sub(decay, big.NewInt(1))
/*
strategy: gasLimit of block-to-mine is set based on parent's
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
increase it, otherwise lower it (or leave it unchanged if it's right
at that usage) the amount increased/decreased depends on how far away
from parentGasLimit * (2/3) parentGasUsed is.
*/
gl := new(big.Int).Sub(parent.GasLimit(), decay)
gl = gl.Add(gl, contrib)
gl.Set(common.BigMax(gl, params.MinGasLimit))
// however, if we're now below the target (GenesisGasLimit) we increase the
// limit as much as we can (parentGasLimit / 1024 -1)
if gl.Cmp(params.GenesisGasLimit) < 0 {
gl.Add(parent.GasLimit(), decay)
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
}
return gl
}

View File

@ -591,6 +591,19 @@ func (bc *BlockChain) HasBlock(hash common.Hash) bool {
return bc.GetBlock(hash) != nil
}
// HasBlockAndState checks if a block and associated state trie is fully present
// in the database or not, caching it if present.
func (bc *BlockChain) HasBlockAndState(hash common.Hash) bool {
// Check first that the block itself is known
block := bc.GetBlock(hash)
if block == nil {
return false
}
// Ensure the associated state is also present
_, err := state.New(block.Root(), bc.chainDb)
return err == nil
}
// GetBlock retrieves a block from the database by hash, caching it if found.
func (self *BlockChain) GetBlock(hash common.Hash) *types.Block {
// Short circuit if the block's already in the cache, retrieve otherwise
@ -716,14 +729,18 @@ func (self *BlockChain) writeHeader(header *types.Header) error {
if ptd == nil {
return ParentError(header.ParentHash)
}
td := new(big.Int).Add(header.Difficulty, ptd)
localTd := self.GetTd(self.currentHeader.Hash())
externTd := new(big.Int).Add(header.Difficulty, ptd)
// Make sure no inconsistent state is leaked during insertion
self.mu.Lock()
defer self.mu.Unlock()
// If the total difficulty is higher than our known, add it to the canonical chain
if td.Cmp(self.GetTd(self.currentHeader.Hash())) > 0 {
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) {
// Delete any canonical number assignments above the new head
for i := header.Number.Uint64() + 1; GetCanonicalHash(self.chainDb, i) != (common.Hash{}); i++ {
DeleteCanonicalHash(self.chainDb, i)
@ -744,7 +761,7 @@ func (self *BlockChain) writeHeader(header *types.Header) error {
self.currentHeader = types.CopyHeader(header)
}
// Irrelevant of the canonical status, write the header itself to the database
if err := WriteTd(self.chainDb, header.Hash(), td); err != nil {
if err := WriteTd(self.chainDb, header.Hash(), externTd); err != nil {
glog.Fatalf("failed to write header total difficulty: %v", err)
}
if err := WriteHeader(self.chainDb, header); err != nil {
@ -1039,14 +1056,18 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status writeStatus, err
if ptd == nil {
return NonStatTy, ParentError(block.ParentHash())
}
td := new(big.Int).Add(block.Difficulty(), ptd)
localTd := self.GetTd(self.currentBlock.Hash())
externTd := new(big.Int).Add(block.Difficulty(), ptd)
// Make sure no inconsistent state is leaked during insertion
self.mu.Lock()
defer self.mu.Unlock()
// If the total difficulty is higher than our known, add it to the canonical chain
if td.Cmp(self.GetTd(self.currentBlock.Hash())) > 0 {
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) {
// Reorganize the chain if the parent is not the head block
if block.ParentHash() != self.currentBlock.Hash() {
if err := self.reorg(self.currentBlock, block); err != nil {
@ -1060,7 +1081,7 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status writeStatus, err
status = SideStatTy
}
// Irrelevant of the canonical status, write the block itself to the database
if err := WriteTd(self.chainDb, block.Hash(), td); err != nil {
if err := WriteTd(self.chainDb, block.Hash(), externTd); err != nil {
glog.Fatalf("failed to write block total difficulty: %v", err)
}
if err := WriteBlock(self.chainDb, block); err != nil {

View File

@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@ -50,77 +49,9 @@ var (
mipmapPre = []byte("mipmap-log-bloom-")
MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
ExpDiffPeriod = big.NewInt(100000)
blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
)
// CalcDifficulty is the difficulty adjustment algorithm. It returns
// the difficulty that a new block b should have when created at time
// given the parent block's time and difficulty.
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
diff := new(big.Int)
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
bigTime := new(big.Int)
bigParentTime := new(big.Int)
bigTime.SetUint64(time)
bigParentTime.SetUint64(parentTime)
if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
diff.Add(parentDiff, adjust)
} else {
diff.Sub(parentDiff, adjust)
}
if diff.Cmp(params.MinimumDifficulty) < 0 {
diff = params.MinimumDifficulty
}
periodCount := new(big.Int).Add(parentNumber, common.Big1)
periodCount.Div(periodCount, ExpDiffPeriod)
if periodCount.Cmp(common.Big1) > 0 {
// diff = diff + 2^(periodCount - 2)
expDiff := periodCount.Sub(periodCount, common.Big2)
expDiff.Exp(common.Big2, expDiff, nil)
diff.Add(diff, expDiff)
diff = common.BigMax(diff, params.MinimumDifficulty)
}
return diff
}
// CalcGasLimit computes the gas limit of the next block after parent.
// The result may be modified by the caller.
// This is miner strategy, not consensus protocol.
func CalcGasLimit(parent *types.Block) *big.Int {
// contrib = (parentGasUsed * 3 / 2) / 1024
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
contrib = contrib.Div(contrib, big.NewInt(2))
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
// decay = parentGasLimit / 1024 -1
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
decay.Sub(decay, big.NewInt(1))
/*
strategy: gasLimit of block-to-mine is set based on parent's
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
increase it, otherwise lower it (or leave it unchanged if it's right
at that usage) the amount increased/decreased depends on how far away
from parentGasLimit * (2/3) parentGasUsed is.
*/
gl := new(big.Int).Sub(parent.GasLimit(), decay)
gl = gl.Add(gl, contrib)
gl.Set(common.BigMax(gl, params.MinGasLimit))
// however, if we're now below the target (GenesisGasLimit) we increase the
// limit as much as we can (parentGasLimit / 1024 -1)
if gl.Cmp(params.GenesisGasLimit) < 0 {
gl.Add(parent.GasLimit(), decay)
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
}
return gl
}
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))

View File

@ -62,7 +62,7 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
return nil
}
func TestDifficulty(t *testing.T) {
func TestDifficultyFrontier(t *testing.T) {
file, err := os.Open("../tests/files/BasicTests/difficulty.json")
if err != nil {
t.Fatal(err)
@ -77,7 +77,7 @@ func TestDifficulty(t *testing.T) {
for name, test := range tests {
number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
diff := CalcDifficulty(test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
diff := calcDifficultyFrontier(test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
if diff.Cmp(test.CurrentDifficulty) != 0 {
t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
}

View File

@ -33,8 +33,17 @@ func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input
// CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
prev := caller.Address()
ret, _, err = exec(env, caller, &prev, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
callerAddr := caller.Address()
ret, _, err = exec(env, caller, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err
}
// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope
func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
callerAddr := caller.Address()
originAddr := env.Origin()
callerValue := caller.Value()
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
return ret, err
}
@ -52,7 +61,6 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := vm.NewVm(env)
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
@ -69,17 +77,15 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
var createAccount bool
if address == nil {
// Generate a new address
// Create a new account on the state
nonce := env.Db().GetNonce(caller.Address())
env.Db().SetNonce(caller.Address(), nonce+1)
addr = crypto.CreateAddress(caller.Address(), nonce)
address = &addr
createAccount = true
}
snapshot := env.MakeSnapshot()
snapshotPreTransfer := env.MakeSnapshot()
var (
from = env.Db().GetAccount(caller.Address())
to vm.Account
@ -95,12 +101,68 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
}
env.Transfer(from, to, value)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(codeAddr, code)
defer contract.Finalise()
ret, err = evm.Run(contract, input)
// if the contract creation ran successfully and no errors were returned
// calculate the gas required to store the code. If the code could not
// be stored due to not enough gas set an error and let it be handled
// by the error checking condition below.
if err == nil && createAccount {
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
if contract.UseGas(dataGas) {
env.Db().SetCode(*address, ret)
} else {
err = vm.CodeStoreOutOfGasError
}
}
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if err != nil && (params.IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
contract.UseGas(contract.Gas)
env.SetSnapshot(snapshotPreTransfer)
}
return ret, addr, err
}
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := vm.NewVm(env)
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
}
snapshot := env.MakeSnapshot()
var to vm.Account
if !env.Db().Exist(*toAddr) {
to = env.Db().CreateAccount(*toAddr)
} else {
to = env.Db().GetAccount(*toAddr)
}
// Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
contract.SetCallCode(codeAddr, code)
defer contract.Finalise()
ret, err = evm.Run(contract, input)
if err != nil {
env.SetSnapshot(snapshot) //env.Db().Set(snapshot)
contract.UseGas(contract.Gas)
env.SetSnapshot(snapshot)
}
return ret, addr, err

View File

@ -28,6 +28,7 @@ type Account struct {
Nonce uint64 `json:"nonce"`
Root string `json:"root"`
CodeHash string `json:"codeHash"`
Code string `json:"code"`
Storage map[string]string `json:"storage"`
}
@ -47,7 +48,7 @@ func (self *StateDB) RawDump() World {
addr := self.trie.GetKey(it.Key)
stateObject := NewStateObjectFromBytes(common.BytesToAddress(addr), it.Value, self.db)
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash)}
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash), Code: common.Bytes2Hex(stateObject.Code())}
account.Storage = make(map[string]string)
storageIt := stateObject.trie.Iterator()

View File

@ -260,6 +260,13 @@ func (self *StateObject) Nonce() uint64 {
return self.nonce
}
// Never called, but must be present to allow StateObject to be used
// as a vm.Account interface that also satisfies the vm.ContractRef
// interface. Interfaces are awesome.
func (self *StateObject) Value() *big.Int {
panic("Value on StateObject should never be called")
}
func (self *StateObject) EachStorage(cb func(key, value []byte)) {
// When iterating over the storage check the cache first
for h, v := range self.storage {

View File

@ -55,7 +55,6 @@ type StateDB struct {
func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
tr, err := trie.NewSecure(root, db)
if err != nil {
glog.Errorf("can't create state trie with root %x: %v", root[:], err)
return nil, err
}
return &StateDB{

View File

@ -43,7 +43,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (ty
for i, tx := range block.Transactions() {
statedb.StartRecord(tx.Hash(), block.Hash(), i)
receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas)
if err != nil {
return nil, nil, totalUsedGas, err

View File

@ -27,6 +27,10 @@ import (
"github.com/ethereum/go-ethereum/params"
)
var (
Big0 = big.NewInt(0)
)
/*
The State Transitioning Model
@ -59,6 +63,7 @@ type StateTransition struct {
// Message represents a message sent to a contract.
type Message interface {
From() (common.Address, error)
FromFrontier() (common.Address, error)
To() *common.Address
GasPrice() *big.Int
@ -75,8 +80,13 @@ func MessageCreatesContract(msg Message) bool {
// IntrinsicGas computes the 'intrisic gas' for a message
// with the given data.
func IntrinsicGas(data []byte) *big.Int {
igas := new(big.Int).Set(params.TxGas)
func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
igas := new(big.Int)
if contractCreation && homestead {
igas.Set(params.TxGasContractCreation)
} else {
igas.Set(params.TxGas)
}
if len(data) > 0 {
var nz int64
for _, byt := range data {
@ -110,7 +120,15 @@ func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.In
}
func (self *StateTransition) from() (vm.Account, error) {
f, err := self.msg.From()
var (
f common.Address
err error
)
if params.IsHomestead(self.env.BlockNumber()) {
f, err = self.msg.From()
} else {
f, err = self.msg.FromFrontier()
}
if err != nil {
return nil, err
}
@ -195,35 +213,35 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
if err = self.preCheck(); err != nil {
return
}
msg := self.msg
sender, _ := self.from() // err checked in preCheck
homestead := params.IsHomestead(self.env.BlockNumber())
contractCreation := MessageCreatesContract(msg)
// Pay intrinsic gas
if err = self.useGas(IntrinsicGas(self.data)); err != nil {
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
return nil, nil, InvalidTxError(err)
}
vmenv := self.env
var addr common.Address
if MessageCreatesContract(msg) {
ret, addr, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
if err == nil {
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
if err := self.useGas(dataGas); err == nil {
self.state.SetCode(addr, ret)
} else {
ret = nil // does not affect consensus but useful for StateTests validations
glog.V(logger.Core).Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas)
}
//var addr common.Address
if contractCreation {
ret, _, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
if homestead && err == vm.CodeStoreOutOfGasError {
self.gas = Big0
}
if err != nil {
ret = nil
glog.V(logger.Core).Infoln("VM create err:", err)
}
glog.V(logger.Core).Infoln("VM create err:", err)
} else {
// Increment the nonce for the next transaction
self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
ret, err = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.gasPrice, self.value)
glog.V(logger.Core).Infoln("VM call err:", err)
if err != nil {
glog.V(logger.Core).Infoln("VM call err:", err)
}
}
if err != nil && IsValueTransferErr(err) {

View File

@ -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))
}
}

View File

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
)
var (
@ -65,10 +66,11 @@ type TxPool struct {
minGasPrice *big.Int
eventMux *event.TypeMux
events event.Subscription
mu sync.RWMutex
pending map[common.Hash]*types.Transaction // processable transactions
queue map[common.Address]map[common.Hash]*types.Transaction
mu sync.RWMutex
pending map[common.Hash]*types.Transaction // processable transactions
queue map[common.Address]map[common.Hash]*types.Transaction
homestead bool
}
func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
@ -83,6 +85,7 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
pendingState: nil,
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
}
go pool.eventLoop()
return pool
@ -96,6 +99,10 @@ func (pool *TxPool) eventLoop() {
switch ev := ev.Data.(type) {
case ChainHeadEvent:
pool.mu.Lock()
if ev.Block != nil && params.IsHomestead(ev.Block.Number()) {
pool.homestead = true
}
pool.resetState()
pool.mu.Unlock()
case GasPriceChanged:
@ -138,7 +145,6 @@ func (pool *TxPool) resetState() {
}
}
}
// Check the queue and move transactions over to the pending if possible
// or remove those that have become invalid
pool.checkQueue()
@ -171,29 +177,23 @@ func (pool *TxPool) Stats() (pending int, queued int) {
// validateTx checks whether a transaction is valid according
// to the consensus rules.
func (pool *TxPool) validateTx(tx *types.Transaction) error {
// Validate sender
var (
from common.Address
err error
)
// Drop transactions under our own minimal accepted gas price
if pool.minGasPrice.Cmp(tx.GasPrice()) > 0 {
return ErrCheap
}
// Validate the transaction sender and it's sig. Throw
// if the from fields is invalid.
if from, err = tx.From(); err != nil {
currentState, err := pool.currentState()
if err != nil {
return err
}
from, err := tx.From()
if err != nil {
return ErrInvalidSender
}
// Make sure the account exist. Non existent accounts
// haven't got funds and well therefor never pass.
currentState, err := pool.currentState()
if err != nil {
return err
}
if !currentState.HasAccount(from) {
return ErrNonExistentAccount
}
@ -222,8 +222,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
return ErrInsufficientFunds
}
// Should supply enough intrinsic gas
if tx.Gas().Cmp(IntrinsicGas(tx.Data())) < 0 {
intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead)
if tx.Gas().Cmp(intrGas) < 0 {
return ErrIntrinsicGas
}
@ -290,17 +290,15 @@ func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Trans
}
// Add queues a single transaction in the pool if it is valid.
func (self *TxPool) Add(tx *types.Transaction) (err error) {
func (self *TxPool) Add(tx *types.Transaction) error {
self.mu.Lock()
defer self.mu.Unlock()
err = self.add(tx)
if err == nil {
// check and validate the queueue
self.checkQueue()
if err := self.add(tx); err != nil {
return err
}
return
self.checkQueue()
return nil
}
// AddTransactions attempts to queue all valid transactions in txs.
@ -368,7 +366,7 @@ func (self *TxPool) GetQueuedTransactions() types.Transactions {
ret = append(ret, tx)
}
}
sort.Sort(types.TxByNonce{ret})
sort.Sort(types.TxByNonce(ret))
return ret
}
@ -406,51 +404,55 @@ func (pool *TxPool) checkQueue() {
pool.resetState()
}
var addq txQueue
var promote txQueue
for address, txs := range pool.queue {
// guessed nonce is the nonce currently kept by the tx pool (pending state)
guessedNonce := pool.pendingState.GetNonce(address)
// true nonce is the nonce known by the last state
currentState, err := pool.currentState()
if err != nil {
glog.Errorf("could not get current state: %v", err)
return
}
trueNonce := currentState.GetNonce(address)
addq := addq[:0]
balance := currentState.GetBalance(address)
var (
guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state)
trueNonce = currentState.GetNonce(address) // nonce known by the last state
)
promote = promote[:0]
for hash, tx := range txs {
if tx.Nonce() < trueNonce {
// Drop queued transactions whose nonce is lower than
// the account nonce because they have been processed.
// Drop processed or out of fund transactions
if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 {
if glog.V(logger.Core) {
glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx)
}
delete(txs, hash)
} else {
// Collect the remaining transactions for the next pass.
addq = append(addq, txQueueEntry{hash, address, tx})
}
}
// Find the next consecutive nonce range starting at the
// current account nonce.
sort.Sort(addq)
for i, e := range addq {
// start deleting the transactions from the queue if they exceed the limit
if i > maxQueued {
delete(pool.queue[address], e.hash)
continue
}
if e.Nonce() > guessedNonce {
if len(addq)-i > maxQueued {
// Collect the remaining transactions for the next pass.
promote = append(promote, txQueueEntry{hash, address, tx})
}
// Find the next consecutive nonce range starting at the current account nonce,
// pushing the guessed nonce forward if we add consecutive transactions.
sort.Sort(promote)
for i, entry := range promote {
// If we reached a gap in the nonces, enforce transaction limit and stop
if entry.Nonce() > guessedNonce {
if len(promote)-i > maxQueued {
if glog.V(logger.Debug) {
glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:]))
glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:]))
}
for j := i + maxQueued; j < len(addq); j++ {
delete(txs, addq[j].hash)
for _, drop := range promote[i+maxQueued:] {
delete(txs, drop.hash)
}
}
break
}
delete(txs, e.hash)
pool.addTx(e.hash, address, e.Transaction)
// Otherwise promote the transaction and move the guess nonce if needed
pool.addTx(entry.hash, address, entry.Transaction)
delete(txs, entry.hash)
if entry.Nonce() == guessedNonce {
guessedNonce++
}
}
// Delete the entire queue entry if it became empty.
if len(txs) == 0 {
@ -460,20 +462,56 @@ func (pool *TxPool) checkQueue() {
}
// validatePool removes invalid and processed transactions from the main pool.
// If a transaction is removed for being invalid (e.g. out of funds), all sub-
// sequent (Still valid) transactions are moved back into the future queue. This
// is important to prevent a drained account from DOSing the network with non
// executable transactions.
func (pool *TxPool) validatePool() {
state, err := pool.currentState()
if err != nil {
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
return
}
balanceCache := make(map[common.Address]*big.Int)
// Clean up the pending pool, accumulating invalid nonces
gaps := make(map[common.Address]uint64)
for hash, tx := range pool.pending {
from, _ := tx.From() // err already checked
// perform light nonce validation
if state.GetNonce(from) > tx.Nonce() {
sender, _ := tx.From() // err already checked
// Perform light nonce and balance validation
balance := balanceCache[sender]
if balance == nil {
balance = state.GetBalance(sender)
balanceCache[sender] = balance
}
if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 {
// Remove an already past it invalidated transaction
if glog.V(logger.Core) {
glog.Infof("removed tx (%x) from pool: low tx nonce\n", hash[:4])
glog.Infof("removed tx (%v) from pool: low tx nonce or out of funds\n", tx)
}
delete(pool.pending, hash)
// Track the smallest invalid nonce to postpone subsequent transactions
if !past {
if prev, ok := gaps[sender]; !ok || tx.Nonce() < prev {
gaps[sender] = tx.Nonce()
}
}
}
}
// Move all transactions after a gap back to the future queue
if len(gaps) > 0 {
for hash, tx := range pool.pending {
sender, _ := tx.From()
if gap, ok := gaps[sender]; ok && tx.Nonce() >= gap {
if glog.V(logger.Core) {
glog.Infof("postponed tx (%v) due to introduced gap\n", tx)
}
pool.queueTx(hash, tx)
delete(pool.pending, hash)
}
}
}
}

526
core/tx_pool_test.go Normal file
View 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()
}
}

View File

@ -17,11 +17,13 @@
package types
import (
"container/heap"
"crypto/ecdsa"
"errors"
"fmt"
"io"
"math/big"
"sort"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
@ -155,11 +157,47 @@ func (tx *Transaction) Size() common.StorageSize {
return common.StorageSize(c)
}
// From returns the address derived from the signature (V, R, S) using secp256k1
// eliptic curve and an error if it failed deriving or upon an incorrect
// signature.
//
// From Uses the homestead consensus rules to determine whether the signature is
// valid.
//
// From caches the address, allowing it to be used regardless of
// Frontier / Homestead. however, the first time called it runs
// signature validations, so we need two versions. This makes it
// easier to ensure backwards compatibility of things like package rpc
// where eth_getblockbynumber uses tx.From() and needs to work for
// both txs before and after the first homestead block. Signatures
// valid in homestead are a subset of valid ones in Frontier)
func (tx *Transaction) From() (common.Address, error) {
return doFrom(tx, true)
}
// FromFrontier returns the address derived from the signature (V, R, S) using
// secp256k1 eliptic curve and an error if it failed deriving or upon an
// incorrect signature.
//
// FromFrantier uses the frontier consensus rules to determine whether the
// signature is valid.
//
// FromFrontier caches the address, allowing it to be used regardless of
// Frontier / Homestead. however, the first time called it runs
// signature validations, so we need two versions. This makes it
// easier to ensure backwards compatibility of things like package rpc
// where eth_getblockbynumber uses tx.From() and needs to work for
// both txs before and after the first homestead block. Signatures
// valid in homestead are a subset of valid ones in Frontier)
func (tx *Transaction) FromFrontier() (common.Address, error) {
return doFrom(tx, false)
}
func doFrom(tx *Transaction, homestead bool) (common.Address, error) {
if from := tx.from.Load(); from != nil {
return from.(common.Address), nil
}
pubkey, err := tx.publicKey()
pubkey, err := tx.publicKey(homestead)
if err != nil {
return common.Address{}, err
}
@ -180,8 +218,8 @@ func (tx *Transaction) SignatureValues() (v byte, r *big.Int, s *big.Int) {
return tx.data.V, new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
}
func (tx *Transaction) publicKey() ([]byte, error) {
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S) {
func (tx *Transaction) publicKey(homestead bool) ([]byte, error) {
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S, homestead) {
return nil, ErrInvalidSig
}
@ -302,27 +340,78 @@ func TxDifference(a, b Transactions) (keep Transactions) {
return keep
}
type TxByNonce struct{ Transactions }
// TxByNonce implements the sort interface to allow sorting a list of transactions
// by their nonces. This is usually only useful for sorting transactions from a
// single account, otherwise a nonce comparison doesn't make much sense.
type TxByNonce Transactions
func (s TxByNonce) Less(i, j int) bool {
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
func (s TxByNonce) Len() int { return len(s) }
func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce }
func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// TxByPrice implements both the sort and the heap interface, making it useful
// for all at once sorting as well as individually adding and removing elements.
type TxByPrice Transactions
func (s TxByPrice) Len() int { return len(s) }
func (s TxByPrice) Less(i, j int) bool { return s[i].data.Price.Cmp(s[j].data.Price) > 0 }
func (s TxByPrice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s *TxByPrice) Push(x interface{}) {
*s = append(*s, x.(*Transaction))
}
type TxByPrice struct{ Transactions }
func (s TxByPrice) Less(i, j int) bool {
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
func (s *TxByPrice) Pop() interface{} {
old := *s
n := len(old)
x := old[n-1]
*s = old[0 : n-1]
return x
}
type TxByPriceAndNonce struct{ Transactions }
func (s TxByPriceAndNonce) Less(i, j int) bool {
// we can ignore the error here. Sorting shouldn't care about validness
ifrom, _ := s.Transactions[i].From()
jfrom, _ := s.Transactions[j].From()
// favour nonce if they are from the same recipient
if ifrom == jfrom {
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
// SortByPriceAndNonce sorts the transactions by price in such a way that the
// nonce orderings within a single account are maintained.
//
// Note, this is not as trivial as it seems from the first look as there are three
// different criteria that need to be taken into account (price, nonce, account
// match), which cannot be done with any plain sorting method, as certain items
// cannot be compared without context.
//
// This method first sorts the separates the list of transactions into individual
// sender accounts and sorts them by nonce. After the account nonce ordering is
// satisfied, the results are merged back together by price, always comparing only
// the head transaction from each account. This is done via a heap to keep it fast.
func SortByPriceAndNonce(txs []*Transaction) {
// Separate the transactions by account and sort by nonce
byNonce := make(map[common.Address][]*Transaction)
for _, tx := range txs {
acc, _ := tx.From() // we only sort valid txs so this cannot fail
byNonce[acc] = append(byNonce[acc], tx)
}
for _, accTxs := range byNonce {
sort.Sort(TxByNonce(accTxs))
}
// Initialize a price based heap with the head transactions
byPrice := make(TxByPrice, 0, len(byNonce))
for acc, accTxs := range byNonce {
byPrice = append(byPrice, accTxs[0])
byNonce[acc] = accTxs[1:]
}
heap.Init(&byPrice)
// Merge by replacing the best with the next from the same account
txs = txs[:0]
for len(byPrice) > 0 {
// Retrieve the next best transaction by price
best := heap.Pop(&byPrice).(*Transaction)
// Push in its place the next transaction from the same account
acc, _ := best.From() // we only sort valid txs so this cannot fail
if accTxs, ok := byNonce[acc]; ok && len(accTxs) > 0 {
heap.Push(&byPrice, accTxs[0])
byNonce[acc] = accTxs[1:]
}
// Accumulate the best priced transaction
txs = append(txs, best)
}
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
}

View File

@ -117,3 +117,60 @@ func TestRecipientNormal(t *testing.T) {
t.Error("derived address doesn't match")
}
}
// Tests that transactions can be correctly sorted according to their price in
// decreasing order, but at the same time with increasing nonces when issued by
// the same account.
func TestTransactionPriceNonceSort(t *testing.T) {
// Generate a batch of accounts to start with
keys := make([]*ecdsa.PrivateKey, 25)
for i := 0; i < len(keys); i++ {
keys[i], _ = crypto.GenerateKey()
}
// Generate a batch of transactions with overlapping values, but shifted nonces
txs := []*Transaction{}
for start, key := range keys {
for i := 0; i < 25; i++ {
tx, _ := NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+i)), nil).SignECDSA(key)
txs = append(txs, tx)
}
}
// Sort the transactions and cross check the nonce ordering
SortByPriceAndNonce(txs)
for i, txi := range txs {
fromi, _ := txi.From()
// Make sure the nonce order is valid
for j, txj := range txs[i+1:] {
fromj, _ := txj.From()
if fromi == fromj && txi.Nonce() > txj.Nonce() {
t.Errorf("invalid nonce ordering: tx #%d (A=%x N=%v) < tx #%d (A=%x N=%v)", i, fromi[:4], txi.Nonce(), i+j, fromj[:4], txj.Nonce())
}
}
// Find the previous and next nonce of this account
prev, next := i-1, i+1
for j := i - 1; j >= 0; j-- {
if fromj, _ := txs[j].From(); fromi == fromj {
prev = j
break
}
}
for j := i + 1; j < len(txs); j++ {
if fromj, _ := txs[j].From(); fromi == fromj {
next = j
break
}
}
// Make sure that in between the neighbor nonces, the transaction is correctly positioned price wise
for j := prev + 1; j < next; j++ {
fromj, _ := txs[j].From()
if j < i && txs[j].GasPrice().Cmp(txi.GasPrice()) < 0 {
t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)", j, fromj[:4], txs[j].GasPrice(), i, fromi[:4], txi.GasPrice())
}
if j > i && txs[j].GasPrice().Cmp(txi.GasPrice()) > 0 {
t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) > tx #%d (A=%x P=%v)", j, fromj[:4], txs[j].GasPrice(), i, fromi[:4], txi.GasPrice())
}
}
}
}

View File

@ -26,14 +26,19 @@ import (
type ContractRef interface {
ReturnGas(*big.Int, *big.Int)
Address() common.Address
Value() *big.Int
SetCode([]byte)
}
// Contract represents an ethereum contract in the state database. It contains
// the the contract code, calling arguments. Contract implements ContractReg
// the the contract code, calling arguments. Contract implements ContractRef
type Contract struct {
caller ContractRef
self ContractRef
// CallerAddress is the result of the caller which initialised this
// contract. However when the "call method" is delegated this value
// needs to be initialised to that of the caller's caller.
CallerAddress common.Address
caller ContractRef
self ContractRef
jumpdests destinations // result of JUMPDEST analysis.
@ -44,11 +49,13 @@ type Contract struct {
value, Gas, UsedGas, Price *big.Int
Args []byte
DelegateCall bool
}
// Create a new context for the given data items.
// NewContract returns a new contract environment for the execution of EVM.
func NewContract(caller ContractRef, object ContractRef, value, gas, price *big.Int) *Contract {
c := &Contract{caller: caller, self: object, Args: nil}
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
if parent, ok := caller.(*Contract); ok {
// Reuse JUMPDEST analysis from parent context if available.
@ -69,6 +76,16 @@ func NewContract(caller ContractRef, object ContractRef, value, gas, price *big.
return c
}
// AsDelegate sets the contract to be a delegate call and returns the current
// contract (for chaining calls)
func (c *Contract) AsDelegate() *Contract {
c.DelegateCall = true
// NOTE: caller must, at all times be a contract. It should never happen
// that caller is something other than a Contract.
c.CallerAddress = c.caller.(*Contract).CallerAddress
return c
}
// GetOp returns the n'th element in the contract's byte array
func (c *Contract) GetOp(n uint64) OpCode {
return OpCode(c.GetByte(n))
@ -83,13 +100,19 @@ func (c *Contract) GetByte(n uint64) byte {
return 0
}
// Return returns the given ret argument and returns any remaining gas to the
// caller
func (c *Contract) Return(ret []byte) []byte {
// Caller returns the caller of the contract.
//
// Caller will recursively call caller when the contract is a delegate
// call, including that of caller's caller.
func (c *Contract) Caller() common.Address {
return c.CallerAddress
}
// Finalise finalises the contract and returning any remaining gas to the original
// caller.
func (c *Contract) Finalise() {
// Return the remaining gas to the caller
c.caller.ReturnGas(c.Gas, c.Price)
return ret
}
// UseGas attempts the use gas and subtracts it and returns true on success
@ -113,6 +136,11 @@ func (c *Contract) Address() common.Address {
return c.self.Address()
}
// Value returns the contracts value (sent to it from it's caller)
func (c *Contract) Value() *big.Int {
return c.value
}
// SetCode sets the code to the contract
func (self *Contract) SetCode(code []byte) {
self.Code = code

View File

@ -93,7 +93,8 @@ func ecrecoverFunc(in []byte) []byte {
vbig := common.Bytes2Big(in[32:64])
v := byte(vbig.Uint64())
if !crypto.ValidateSignatureValues(v, r, s) {
// tighter sig s values in homestead only apply to tx sigs
if !crypto.ValidateSignatureValues(v, r, s, false) {
glog.V(logger.Debug).Infof("EC RECOVER FAIL: v, r or s value invalid")
return nil
}

View File

@ -70,6 +70,8 @@ type Environment interface {
Call(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
// Take another's contract code and execute within our own context
CallCode(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
// Same as CallCode except sender and value is propagated from parent to child scope
DelegateCall(me ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error)
// Create a new contract
Create(me ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error)
}
@ -121,4 +123,6 @@ type Account interface {
Address() common.Address
ReturnGas(*big.Int, *big.Int)
SetCode([]byte)
EachStorage(cb func(key, value []byte))
Value() *big.Int
}

View File

@ -24,4 +24,5 @@ import (
)
var OutOfGasError = errors.New("Out of gas")
var CodeStoreOutOfGasError = errors.New("Contract creation code storage out of gas")
var DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth)

View File

@ -136,6 +136,7 @@ var _baseCheck = map[OpCode]req{
CREATE: {3, params.CreateGas, 1},
CALL: {7, params.CallGas, 1},
CALLCODE: {7, params.CallGas, 1},
DELEGATECALL: {6, params.CallGas, 1},
JUMPDEST: {0, params.JumpdestGas, 0},
SUICIDE: {1, Zero, 0},
RETURN: {2, Zero, 0},

View File

@ -337,7 +337,7 @@ func opOrigin(instr instruction, pc *uint64, env Environment, contract *Contract
}
func opCaller(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
stack.push(common.Bytes2Big(contract.caller.Address().Bytes()))
stack.push(contract.Caller().Big())
}
func opCallValue(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
@ -485,7 +485,6 @@ func opSload(instr instruction, pc *uint64, env Environment, contract *Contract,
func opSstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
loc := common.BigToHash(stack.pop())
val := stack.pop()
env.Db().SetState(contract.Address(), loc, common.BigToHash(val))
}
@ -514,25 +513,19 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
offset, size = stack.pop(), stack.pop()
input = memory.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(contract.Gas)
addr common.Address
ret []byte
suberr error
)
contract.UseGas(contract.Gas)
ret, addr, suberr = env.Create(contract, input, gas, contract.Price, value)
if suberr != nil {
_, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
// Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must
// ignore this error and pretend the operation was successful.
if params.IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
stack.push(new(big.Int))
} else if suberr != nil && suberr != CodeStoreOutOfGasError {
stack.push(new(big.Int))
} else {
// gas < len(ret) * Createinstr.dataGas == NO_CODE
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
if contract.UseGas(dataGas) {
env.Db().SetCode(addr, ret)
}
stack.push(addr.Big())
}
}
@ -598,6 +591,21 @@ func opCallCode(instr instruction, pc *uint64, env Environment, contract *Contra
}
}
func opDelegateCall(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
gas, to, inOffset, inSize, outOffset, outSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
toAddr := common.BigToAddress(to)
args := memory.Get(inOffset.Int64(), inSize.Int64())
ret, err := env.DelegateCall(contract, toAddr, args, gas, contract.Price)
if err != nil {
stack.push(new(big.Int))
} else {
stack.push(big.NewInt(1))
memory.Set(outOffset.Uint64(), outSize.Uint64(), ret)
}
}
func opReturn(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
}
func opStop(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {

View File

@ -275,6 +275,11 @@ func CompileProgram(program *Program) (err error) {
program.addInstr(op, pc, opGas, nil)
case CREATE:
program.addInstr(op, pc, opCreate, nil)
case DELEGATECALL:
// Instruction added regardless of homestead phase.
// Homestead (and execution of the opcode) is checked during
// runtime.
program.addInstr(op, pc, opDelegateCall, nil)
case CALL:
program.addInstr(op, pc, opCall, nil)
case CALLCODE:
@ -317,10 +322,14 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
}()
}
homestead := params.IsHomestead(env.BlockNumber())
for pc < uint64(len(program.instructions)) {
instrCount++
instr := program.instructions[pc]
if instr.Op() == DELEGATECALL && !homestead {
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
}
ret, err := instr.do(program, &pc, env, contract, mem, stack)
if err != nil {
@ -328,13 +337,13 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
}
if instr.halts() {
return contract.Return(ret), nil
return ret, nil
}
}
contract.Input = nil
return contract.Return(nil), nil
return nil, nil
}
// validDest checks if the given distination is a valid one given the
@ -457,7 +466,6 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
gas.Add(gas, stack.data[stack.len()-1])
if op == CALL {
//if env.Db().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
gas.Add(gas, params.CallNewAccountGas)
}
@ -470,6 +478,13 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
newMemSize = common.BigMax(x, y)
case DELEGATECALL:
gas.Add(gas, stack.data[stack.len()-1])
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
newMemSize = common.BigMax(x, y)
}
quadMemGas(mem, newMemSize, gas)

View File

@ -125,14 +125,17 @@ type vmBench struct {
type account struct{}
func (account) SubBalance(amount *big.Int) {}
func (account) AddBalance(amount *big.Int) {}
func (account) SetBalance(*big.Int) {}
func (account) SetNonce(uint64) {}
func (account) Balance() *big.Int { return nil }
func (account) Address() common.Address { return common.Address{} }
func (account) ReturnGas(*big.Int, *big.Int) {}
func (account) SetCode([]byte) {}
func (account) SubBalance(amount *big.Int) {}
func (account) AddBalance(amount *big.Int) {}
func (account) SetAddress(common.Address) {}
func (account) Value() *big.Int { return nil }
func (account) SetBalance(*big.Int) {}
func (account) SetNonce(uint64) {}
func (account) Balance() *big.Int { return nil }
func (account) Address() common.Address { return common.Address{} }
func (account) ReturnGas(*big.Int, *big.Int) {}
func (account) SetCode([]byte) {}
func (account) EachStorage(cb func(key, value []byte)) {}
func runVmBench(test vmBench, b *testing.B) {
var sender account
@ -205,3 +208,6 @@ func (self *Env) CallCode(caller ContractRef, addr common.Address, data []byte,
func (self *Env) Create(caller ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
return nil, common.Address{}, nil
}
func (self *Env) DelegateCall(me ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
return nil, nil
}

View File

@ -1,13 +1,29 @@
package vm
import "math/big"
import (
"math/big"
"github.com/ethereum/go-ethereum/params"
)
type jumpPtr struct {
fn instrFn
valid bool
}
var jumpTable [256]jumpPtr
type vmJumpTable [256]jumpPtr
func (jt vmJumpTable) init(blockNumber *big.Int) {
// when initialising a new VM execution we must first check the homestead
// changes.
if params.IsHomestead(blockNumber) {
jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
} else {
jumpTable[DELEGATECALL] = jumpPtr{nil, false}
}
}
var jumpTable vmJumpTable
func init() {
jumpTable[ADD] = jumpPtr{opAdd, true}

View 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)
}
}
}

View File

@ -200,6 +200,7 @@ const (
CALL
CALLCODE
RETURN
DELEGATECALL
SUICIDE = 0xff
)
@ -349,11 +350,12 @@ var opCodeToString = map[OpCode]string{
LOG4: "LOG4",
// 0xf0 range
CREATE: "CREATE",
CALL: "CALL",
RETURN: "RETURN",
CALLCODE: "CALLCODE",
SUICIDE: "SUICIDE",
CREATE: "CREATE",
CALL: "CALL",
RETURN: "RETURN",
CALLCODE: "CALLCODE",
DELEGATECALL: "DELEGATECALL",
SUICIDE: "SUICIDE",
PUSH: "PUSH",
DUP: "DUP",
@ -402,6 +404,7 @@ var stringToOp = map[string]OpCode{
"CALLDATALOAD": CALLDATALOAD,
"CALLDATASIZE": CALLDATASIZE,
"CALLDATACOPY": CALLDATACOPY,
"DELEGATECALL": DELEGATECALL,
"CODESIZE": CODESIZE,
"CODECOPY": CODECOPY,
"GASPRICE": GASPRICE,

View File

@ -101,6 +101,10 @@ func (self *Env) CallCode(caller vm.ContractRef, addr common.Address, data []byt
return core.CallCode(self, caller, addr, data, gas, price, value)
}
func (self *Env) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
return core.DelegateCall(self, me, addr, data, gas, price)
}
func (self *Env) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
return core.Create(self, caller, data, gas, price, value)
}

View File

@ -35,6 +35,9 @@ type Vm struct {
// New returns a new Vm
func New(env Environment) *Vm {
// init the jump table. Also prepares the homestead changes
jumpTable.init(env.BlockNumber())
return &Vm{env: env}
}
@ -43,16 +46,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
self.env.SetDepth(self.env.Depth() + 1)
defer self.env.SetDepth(self.env.Depth() - 1)
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
defer func() {
if err != nil {
// In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
contract.UseGas(contract.Gas)
ret = contract.Return(nil)
}
}()
if contract.CodeAddr != nil {
if p := Precompiled[contract.CodeAddr.Str()]; p != nil {
return self.RunPrecompiled(p, input, contract)
@ -61,7 +54,7 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
// Don't bother with the execution if there's no code.
if len(contract.Code) == 0 {
return contract.Return(nil), nil
return nil, nil
}
var (
@ -160,7 +153,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
// Get the memory location of pc
op = contract.GetOp(pc)
// calculate the new memory size and gas price for the current executing opcode
newMemSize, cost, err = calculateGasAndSize(self.env, contract, caller, op, statedb, mem, stack)
if err != nil {
@ -177,7 +169,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
mem.Resize(newMemSize.Uint64())
// Add a log message
self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil)
if opPtr := jumpTable[op]; opPtr.valid {
if opPtr.fn != nil {
opPtr.fn(instruction{}, &pc, self.env, contract, mem, stack)
@ -205,13 +196,13 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
offset, size := stack.pop(), stack.pop()
ret := mem.GetPtr(offset.Int64(), size.Int64())
return contract.Return(ret), nil
return ret, nil
case SUICIDE:
opSuicide(instruction{}, nil, self.env, contract, mem, stack)
fallthrough
case STOP: // Stop the contract
return contract.Return(nil), nil
return nil, nil
}
}
} else {
@ -332,7 +323,6 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
gas.Add(gas, stack.data[stack.len()-1])
if op == CALL {
//if env.Db().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
gas.Add(gas, params.CallNewAccountGas)
}
@ -345,6 +335,13 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
newMemSize = common.BigMax(x, y)
case DELEGATECALL:
gas.Add(gas, stack.data[stack.len()-1])
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
newMemSize = common.BigMax(x, y)
}
quadMemGas(mem, newMemSize, gas)
@ -358,7 +355,7 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Co
if contract.UseGas(gas) {
ret = p.Call(input)
return contract.Return(ret), nil
return ret, nil
} else {
return nil, OutOfGasError
}

View File

@ -94,6 +94,10 @@ func (self *VMEnv) CallCode(me vm.ContractRef, addr common.Address, data []byte,
return CallCode(self, me, addr, data, gas, price, value)
}
func (self *VMEnv) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
return DelegateCall(self, me, addr, data, gas, price)
}
func (self *VMEnv) Create(me vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
return Create(self, me, data, gas, price, value)
}

View File

@ -171,12 +171,21 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(S256(), rand.Reader)
}
func ValidateSignatureValues(v byte, r, s *big.Int) bool {
func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
return false
}
vint := uint32(v)
if r.Cmp(secp256k1n) < 0 && s.Cmp(secp256k1n) < 0 && (vint == 27 || vint == 28) {
// reject upper range of s values (ECDSA malleability)
// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
if homestead && s.Cmp(secp256k1.HalfN) > 0 {
return false
}
// Frontier: allow s to be in full N range
if s.Cmp(secp256k1.N) >= 0 {
return false
}
if r.Cmp(secp256k1.N) < 0 && (vint == 27 || vint == 28) {
return true
} else {
return false

View File

@ -174,7 +174,7 @@ func TestLoadECDSAFile(t *testing.T) {
func TestValidateSignatureValues(t *testing.T) {
check := func(expected bool, v byte, r, s *big.Int) {
if ValidateSignatureValues(v, r, s) != expected {
if ValidateSignatureValues(v, r, s, false) != expected {
t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected)
}
}

View File

@ -191,11 +191,9 @@ func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
// messageTag computes the MAC of a message (called the tag) as per
// SEC 1, 3.5.
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
if shared == nil {
shared = make([]byte, 0)
}
mac := hmac.New(hash, km)
mac.Write(msg)
mac.Write(shared)
tag := mac.Sum(nil)
return tag
}
@ -242,9 +240,11 @@ func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte,
return
}
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
// the shared information parameters aren't being used, they should be
// nil.
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1.
//
// s1 and s2 contain shared information that is not part of the resulting
// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the
// shared information parameters aren't being used, they should be nil.
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
params := pub.Params
if params == nil {

View File

@ -353,6 +353,36 @@ func TestEncryptDecrypt(t *testing.T) {
}
}
func TestDecryptShared2(t *testing.T) {
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
if err != nil {
t.Fatal(err)
}
message := []byte("Hello, world.")
shared2 := []byte("shared data 2")
ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2)
if err != nil {
t.Fatal(err)
}
// Check that decrypting with correct shared data works.
pt, err := prv.Decrypt(rand.Reader, ct, nil, shared2)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(pt, message) {
t.Fatal("ecies: plaintext doesn't match message")
}
// Decrypting without shared data or incorrect shared data fails.
if _, err = prv.Decrypt(rand.Reader, ct, nil, nil); err == nil {
t.Fatal("ecies: decrypting without shared data didn't fail")
}
if _, err = prv.Decrypt(rand.Reader, ct, nil, []byte("garbage")); err == nil {
t.Fatal("ecies: decrypting with incorrect shared data didn't fail")
}
}
// TestMarshalEncryption validates the encode/decode produces a valid
// ECIES encryption key.
func TestMarshalEncryption(t *testing.T) {

View File

@ -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
```

View File

@ -20,14 +20,8 @@ package secp256k1
/*
#cgo CFLAGS: -I./libsecp256k1
#cgo darwin CFLAGS: -I/usr/local/include
#cgo freebsd CFLAGS: -I/usr/local/include
#cgo linux,arm CFLAGS: -I/usr/local/arm/include
#cgo LDFLAGS: -lgmp
#cgo darwin LDFLAGS: -L/usr/local/lib
#cgo freebsd LDFLAGS: -L/usr/local/lib
#cgo linux,arm LDFLAGS: -L/usr/local/arm/lib
#define USE_NUM_GMP
#cgo CFLAGS: -I./libsecp256k1/src/
#define USE_NUM_NONE
#define USE_FIELD_10X26
#define USE_FIELD_INV_BUILTIN
#define USE_SCALAR_8X32
@ -44,6 +38,7 @@ import "C"
import (
"errors"
"math/big"
"unsafe"
"github.com/ethereum/go-ethereum/crypto/randentropy"
@ -60,9 +55,17 @@ import (
*/
// holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
var context *C.secp256k1_context
var (
context *C.secp256k1_context
N *big.Int
HalfN *big.Int
)
func init() {
N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
// N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168
HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16)
// around 20 ms on a modern CPU.
context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)

View File

@ -112,20 +112,20 @@ type Downloader struct {
syncStatsLock sync.RWMutex // Lock protecting the sync stats fields
// Callbacks
hasHeader headerCheckFn // Checks if a header is present in the chain
hasBlock blockCheckFn // Checks if a block is present in the chain
getHeader headerRetrievalFn // Retrieves a header from the chain
getBlock blockRetrievalFn // Retrieves a block from the chain
headHeader headHeaderRetrievalFn // Retrieves the head header from the chain
headBlock headBlockRetrievalFn // Retrieves the head block from the chain
headFastBlock headFastBlockRetrievalFn // Retrieves the head fast-sync block from the chain
commitHeadBlock headBlockCommitterFn // Commits a manually assembled block as the chain head
getTd tdRetrievalFn // Retrieves the TD of a block from the chain
insertHeaders headerChainInsertFn // Injects a batch of headers into the chain
insertBlocks blockChainInsertFn // Injects a batch of blocks into the chain
insertReceipts receiptChainInsertFn // Injects a batch of blocks and their receipts into the chain
rollback chainRollbackFn // Removes a batch of recently added chain links
dropPeer peerDropFn // Drops a peer for misbehaving
hasHeader headerCheckFn // Checks if a header is present in the chain
hasBlockAndState blockAndStateCheckFn // Checks if a block and associated state is present in the chain
getHeader headerRetrievalFn // Retrieves a header from the chain
getBlock blockRetrievalFn // Retrieves a block from the chain
headHeader headHeaderRetrievalFn // Retrieves the head header from the chain
headBlock headBlockRetrievalFn // Retrieves the head block from the chain
headFastBlock headFastBlockRetrievalFn // Retrieves the head fast-sync block from the chain
commitHeadBlock headBlockCommitterFn // Commits a manually assembled block as the chain head
getTd tdRetrievalFn // Retrieves the TD of a block from the chain
insertHeaders headerChainInsertFn // Injects a batch of headers into the chain
insertBlocks blockChainInsertFn // Injects a batch of blocks into the chain
insertReceipts receiptChainInsertFn // Injects a batch of blocks and their receipts into the chain
rollback chainRollbackFn // Removes a batch of recently added chain links
dropPeer peerDropFn // Drops a peer for misbehaving
// Status
synchroniseMock func(id string, hash common.Hash) error // Replacement for synchronise during testing
@ -156,41 +156,41 @@ type Downloader struct {
}
// New creates a new downloader to fetch hashes and blocks from remote peers.
func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, hasBlock blockCheckFn, getHeader headerRetrievalFn,
getBlock blockRetrievalFn, headHeader headHeaderRetrievalFn, headBlock headBlockRetrievalFn, headFastBlock headFastBlockRetrievalFn,
commitHeadBlock headBlockCommitterFn, getTd tdRetrievalFn, insertHeaders headerChainInsertFn, insertBlocks blockChainInsertFn,
insertReceipts receiptChainInsertFn, rollback chainRollbackFn, dropPeer peerDropFn) *Downloader {
func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, hasBlockAndState blockAndStateCheckFn,
getHeader headerRetrievalFn, getBlock blockRetrievalFn, headHeader headHeaderRetrievalFn, headBlock headBlockRetrievalFn,
headFastBlock headFastBlockRetrievalFn, commitHeadBlock headBlockCommitterFn, getTd tdRetrievalFn, insertHeaders headerChainInsertFn,
insertBlocks blockChainInsertFn, insertReceipts receiptChainInsertFn, rollback chainRollbackFn, dropPeer peerDropFn) *Downloader {
return &Downloader{
mode: FullSync,
mux: mux,
queue: newQueue(stateDb),
peers: newPeerSet(),
hasHeader: hasHeader,
hasBlock: hasBlock,
getHeader: getHeader,
getBlock: getBlock,
headHeader: headHeader,
headBlock: headBlock,
headFastBlock: headFastBlock,
commitHeadBlock: commitHeadBlock,
getTd: getTd,
insertHeaders: insertHeaders,
insertBlocks: insertBlocks,
insertReceipts: insertReceipts,
rollback: rollback,
dropPeer: dropPeer,
newPeerCh: make(chan *peer, 1),
hashCh: make(chan dataPack, 1),
blockCh: make(chan dataPack, 1),
headerCh: make(chan dataPack, 1),
bodyCh: make(chan dataPack, 1),
receiptCh: make(chan dataPack, 1),
stateCh: make(chan dataPack, 1),
blockWakeCh: make(chan bool, 1),
bodyWakeCh: make(chan bool, 1),
receiptWakeCh: make(chan bool, 1),
stateWakeCh: make(chan bool, 1),
mode: FullSync,
mux: mux,
queue: newQueue(stateDb),
peers: newPeerSet(),
hasHeader: hasHeader,
hasBlockAndState: hasBlockAndState,
getHeader: getHeader,
getBlock: getBlock,
headHeader: headHeader,
headBlock: headBlock,
headFastBlock: headFastBlock,
commitHeadBlock: commitHeadBlock,
getTd: getTd,
insertHeaders: insertHeaders,
insertBlocks: insertBlocks,
insertReceipts: insertReceipts,
rollback: rollback,
dropPeer: dropPeer,
newPeerCh: make(chan *peer, 1),
hashCh: make(chan dataPack, 1),
blockCh: make(chan dataPack, 1),
headerCh: make(chan dataPack, 1),
bodyCh: make(chan dataPack, 1),
receiptCh: make(chan dataPack, 1),
stateCh: make(chan dataPack, 1),
blockWakeCh: make(chan bool, 1),
bodyWakeCh: make(chan bool, 1),
receiptWakeCh: make(chan bool, 1),
stateWakeCh: make(chan bool, 1),
}
}
@ -564,7 +564,7 @@ func (d *Downloader) findAncestor61(p *peer) (uint64, error) {
// Check if a common ancestor was found
finished = true
for i := len(hashes) - 1; i >= 0; i-- {
if d.hasBlock(hashes[i]) {
if d.hasBlockAndState(hashes[i]) {
number, hash = uint64(from)+uint64(i), hashes[i]
break
}
@ -620,11 +620,11 @@ func (d *Downloader) findAncestor61(p *peer) (uint64, error) {
arrived = true
// Modify the search interval based on the response
block := d.getBlock(hashes[0])
if block == nil {
if !d.hasBlockAndState(hashes[0]) {
end = check
break
}
block := d.getBlock(hashes[0]) // this doesn't check state, hence the above explicit check
if block.NumberU64() != check {
glog.V(logger.Debug).Infof("%v: non requested hash #%d [%x…], instead of #%d", p, block.NumberU64(), block.Hash().Bytes()[:4], check)
return 0, errBadPeer
@ -989,7 +989,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
// Check if a common ancestor was found
finished = true
for i := len(headers) - 1; i >= 0; i-- {
if (d.mode != LightSync && d.hasBlock(headers[i].Hash())) || (d.mode == LightSync && d.hasHeader(headers[i].Hash())) {
if (d.mode != LightSync && d.hasBlockAndState(headers[i].Hash())) || (d.mode == LightSync && d.hasHeader(headers[i].Hash())) {
number, hash = headers[i].Number.Uint64(), headers[i].Hash()
break
}
@ -1045,7 +1045,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
arrived = true
// Modify the search interval based on the response
if (d.mode == FullSync && !d.hasBlock(headers[0].Hash())) || (d.mode != FullSync && !d.hasHeader(headers[0].Hash())) {
if (d.mode == FullSync && !d.hasBlockAndState(headers[0].Hash())) || (d.mode != FullSync && !d.hasHeader(headers[0].Hash())) {
end = check
break
}
@ -1216,7 +1216,7 @@ func (d *Downloader) fetchHeaders(p *peer, td *big.Int, from uint64) error {
}
}
// Notify the content fetchers of new headers, but stop if queue is full
cont := d.queue.PendingBlocks() < maxQueuedHeaders || d.queue.PendingReceipts() < maxQueuedHeaders
cont := d.queue.PendingBlocks() < maxQueuedHeaders && d.queue.PendingReceipts() < maxQueuedHeaders
for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh, d.stateWakeCh} {
if cont {
// We still have headers to fetch, send continuation wake signal (potential)
@ -1230,9 +1230,11 @@ func (d *Downloader) fetchHeaders(p *peer, td *big.Int, from uint64) error {
case ch <- false:
case <-d.cancelCh:
}
return nil
}
}
if !cont {
return nil
}
// Queue not yet full, fetch the next batch
from += uint64(len(headers))
getHeaders(from)

View File

@ -150,6 +150,8 @@ func newTester() *downloadTester {
peerChainTds: make(map[string]map[common.Hash]*big.Int),
}
tester.stateDb, _ = ethdb.NewMemDatabase()
tester.stateDb.Put(genesis.Root().Bytes(), []byte{0x00})
tester.downloader = New(tester.stateDb, new(event.TypeMux), tester.hasHeader, tester.hasBlock, tester.getHeader,
tester.getBlock, tester.headHeader, tester.headBlock, tester.headFastBlock, tester.commitHeadBlock, tester.getTd,
tester.insertHeaders, tester.insertBlocks, tester.insertReceipts, tester.rollback, tester.dropPeer)
@ -177,9 +179,14 @@ func (dl *downloadTester) hasHeader(hash common.Hash) bool {
return dl.getHeader(hash) != nil
}
// hasBlock checks if a block is present in the testers canonical chain.
// hasBlock checks if a block and associated state is present in the testers canonical chain.
func (dl *downloadTester) hasBlock(hash common.Hash) bool {
return dl.getBlock(hash) != nil
block := dl.getBlock(hash)
if block == nil {
return false
}
_, err := dl.stateDb.Get(block.Root().Bytes())
return err == nil
}
// getHeader retrieves a header from the testers canonical chain.
@ -292,8 +299,10 @@ func (dl *downloadTester) insertBlocks(blocks types.Blocks) (int, error) {
defer dl.lock.Unlock()
for i, block := range blocks {
if _, ok := dl.ownBlocks[block.ParentHash()]; !ok {
if parent, ok := dl.ownBlocks[block.ParentHash()]; !ok {
return i, errors.New("unknown parent")
} else if _, err := dl.stateDb.Get(parent.Root().Bytes()); err != nil {
return i, fmt.Errorf("unknown parent state %x: %v", parent.Root(), err)
}
if _, ok := dl.ownHeaders[block.Hash()]; !ok {
dl.ownHashes = append(dl.ownHashes, block.Hash())
@ -1102,6 +1111,8 @@ func testShiftedHeaderAttack(t *testing.T, protocol int, mode SyncMode) {
}
// Tests that upon detecting an invalid header, the recent ones are rolled back
// for various failure scenarios. Afterwards a full sync is attempted to make
// sure no state was corrupted.
func TestInvalidHeaderRollback63Fast(t *testing.T) { testInvalidHeaderRollback(t, 63, FastSync) }
func TestInvalidHeaderRollback64Fast(t *testing.T) { testInvalidHeaderRollback(t, 64, FastSync) }
func TestInvalidHeaderRollback64Light(t *testing.T) { testInvalidHeaderRollback(t, 64, LightSync) }

View File

@ -27,8 +27,8 @@ import (
// headerCheckFn is a callback type for verifying a header's presence in the local chain.
type headerCheckFn func(common.Hash) bool
// blockCheckFn is a callback type for verifying a block's presence in the local chain.
type blockCheckFn func(common.Hash) bool
// blockAndStateCheckFn is a callback type for verifying block and associated states' presence in the local chain.
type blockAndStateCheckFn func(common.Hash) bool
// headerRetrievalFn is a callback type for retrieving a header from the local chain.
type headerRetrievalFn func(common.Hash) *types.Header

View File

@ -138,9 +138,10 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
return nil, errIncompatibleConfig
}
// Construct the different synchronisation mechanisms
manager.downloader = downloader.New(chaindb, manager.eventMux, blockchain.HasHeader, blockchain.HasBlock, blockchain.GetHeader, blockchain.GetBlock,
blockchain.CurrentHeader, blockchain.CurrentBlock, blockchain.CurrentFastBlock, blockchain.FastSyncCommitHead, blockchain.GetTd,
blockchain.InsertHeaderChain, blockchain.InsertChain, blockchain.InsertReceiptChain, blockchain.Rollback, manager.removePeer)
manager.downloader = downloader.New(chaindb, manager.eventMux, blockchain.HasHeader, blockchain.HasBlockAndState, blockchain.GetHeader,
blockchain.GetBlock, blockchain.CurrentHeader, blockchain.CurrentBlock, blockchain.CurrentFastBlock, blockchain.FastSyncCommitHead,
blockchain.GetTd, blockchain.InsertHeaderChain, blockchain.InsertChain, blockchain.InsertReceiptChain, blockchain.Rollback,
manager.removePeer)
validator := func(block *types.Block, parent *types.Block) error {
return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false)
@ -490,7 +491,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
uncles[i] = body.Uncles
}
// Filter out any explicitly requested bodies, deliver the rest to the downloader
if trasactions, uncles := pm.fetcher.FilterBodies(trasactions, uncles, time.Now()); len(trasactions) > 0 || len(uncles) > 0 {
filter := len(trasactions) > 0 || len(uncles) > 0
if filter {
trasactions, uncles = pm.fetcher.FilterBodies(trasactions, uncles, time.Now())
}
if len(trasactions) > 0 || len(uncles) > 0 || !filter {
err := pm.downloader.DeliverBodies(p.id, trasactions, uncles)
if err != nil {
glog.V(logger.Debug).Infoln(err)

View File

@ -19,7 +19,6 @@ package miner
import (
"fmt"
"math/big"
"sort"
"sync"
"sync/atomic"
"time"
@ -495,12 +494,12 @@ func (self *worker) commitNewWork() {
/* //approach 1
transactions := self.eth.TxPool().GetTransactions()
sort.Sort(types.TxByNonce{transactions})
sort.Sort(types.TxByNonce(transactions))
*/
//approach 2
transactions := self.eth.TxPool().GetTransactions()
sort.Sort(types.TxByPriceAndNonce{transactions})
types.SortByPriceAndNonce(transactions)
/* // approach 3
// commit transactions for this run.
@ -524,8 +523,8 @@ func (self *worker) commitNewWork() {
multiTxOwner = append(multiTxOwner, txs...)
}
}
sort.Sort(types.TxByPrice{singleTxOwner})
sort.Sort(types.TxByNonce{multiTxOwner})
sort.Sort(types.TxByPrice(singleTxOwner))
sort.Sort(types.TxByNonce(multiTxOwner))
transactions := append(singleTxOwner, multiTxOwner...)
*/
@ -591,7 +590,8 @@ func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
func (env *Work) commitTransactions(transactions types.Transactions, gasPrice *big.Int, bc *core.BlockChain) {
gp := new(core.GasPool).AddGas(env.header.GasLimit)
for _, tx := range transactions {
// We can skip err. It has already been validated in the tx pool
// Error may be ignored here. The error has already been checked
// during transaction acceptance is the transaction pool.
from, _ := tx.From()
// Check if it falls within margin. Txs from owned accounts are always processed.

View File

@ -67,6 +67,8 @@ type (
Version uint
From, To rpcEndpoint
Expiration uint64
// Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"`
}
// pong is the reply to ping.
@ -78,18 +80,24 @@ type (
ReplyTok []byte // This contains the hash of the ping packet.
Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
// Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"`
}
// findnode is a query for nodes close to the given target.
findnode struct {
Target NodeID // doesn't need to be an actual public key
Expiration uint64
// Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"`
}
// reply to findnode
neighbors struct {
Nodes []rpcNode
Expiration uint64
// Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"`
}
rpcNode struct {
@ -447,8 +455,11 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte,
return packet, nil
}
type tempError interface {
Temporary() bool
func isTemporaryError(err error) bool {
tempErr, ok := err.(interface {
Temporary() bool
})
return ok && tempErr.Temporary() || isPacketTooBig(err)
}
// readLoop runs in its own goroutine. it handles incoming UDP packets.
@ -460,7 +471,7 @@ func (t *udp) readLoop() {
buf := make([]byte, 1280)
for {
nbytes, from, err := t.conn.ReadFromUDP(buf)
if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
if isTemporaryError(err) {
// Ignore temporary read errors.
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
continue
@ -513,7 +524,8 @@ func decodePacket(buf []byte) (packet, NodeID, []byte, error) {
default:
return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype)
}
err = rlp.DecodeBytes(sigdata[1:], req)
s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0)
err = s.Decode(req)
return req, fromID, hash, err
}

View 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
}

View File

@ -20,13 +20,12 @@ import (
"bytes"
"crypto/ecdsa"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io"
logpkg "log"
"math/rand"
"net"
"os"
"path/filepath"
"reflect"
"runtime"
@ -34,12 +33,64 @@ import (
"testing"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rlp"
)
func init() {
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel))
spew.Config.DisableMethods = true
}
// This test checks that isPacketTooBig correctly identifies
// errors that result from receiving a UDP packet larger
// than the supplied receive buffer.
func TestIsPacketTooBig(t *testing.T) {
listener, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer listener.Close()
sender, err := net.Dial("udp", listener.LocalAddr().String())
if err != nil {
t.Fatal(err)
}
defer sender.Close()
sendN := 1800
recvN := 300
for i := 0; i < 20; i++ {
go func() {
buf := make([]byte, sendN)
for i := range buf {
buf[i] = byte(i)
}
sender.Write(buf)
}()
buf := make([]byte, recvN)
listener.SetDeadline(time.Now().Add(1 * time.Second))
n, _, err := listener.ReadFrom(buf)
if err != nil {
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
continue
}
if !isPacketTooBig(err) {
t.Fatal("unexpected read error:", spew.Sdump(err))
}
continue
}
if n != recvN {
t.Fatalf("short read: %d, want %d", n, recvN)
}
for i := range buf {
if buf[i] != byte(i) {
t.Fatalf("error in pattern")
break
}
}
}
}
// shared test variables
@ -385,6 +436,115 @@ func TestUDP_successfulPing(t *testing.T) {
}
}
var testPackets = []struct {
input string
wantPacket interface{}
}{
{
input: "71dbda3a79554728d4f94411e42ee1f8b0d561c10e1e5f5893367948c6a7d70bb87b235fa28a77070271b6c164a2dce8c7e13a5739b53b5e96f2e5acb0e458a02902f5965d55ecbeb2ebb6cabb8b2b232896a36b737666c55265ad0a68412f250001ea04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a355",
wantPacket: &ping{
Version: 4,
From: rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
To: rpcEndpoint{net.ParseIP("::1"), 2222, 3333},
Expiration: 1136239445,
Rest: []rlp.RawValue{},
},
},
{
input: "e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663aaa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a3550102",
wantPacket: &ping{
Version: 4,
From: rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
To: rpcEndpoint{net.ParseIP("::1"), 2222, 3333},
Expiration: 1136239445,
Rest: []rlp.RawValue{{0x01}, {0x02}},
},
},
{
input: "577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3",
wantPacket: &ping{
Version: 555,
From: rpcEndpoint{net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 3322, 5544},
To: rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
Expiration: 1136239445,
Rest: []rlp.RawValue{{0xC5, 0x01, 0x02, 0x03, 0x04, 0x05}},
},
},
{
input: "09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b2069869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e",
wantPacket: &pong{
To: rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
ReplyTok: common.Hex2Bytes("fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954"),
Expiration: 1136239445,
Rest: []rlp.RawValue{{0xC6, 0x01, 0x02, 0x03, 0xC2, 0x04, 0x05}, {0x06}},
},
},
{
input: "c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396",
wantPacket: &findnode{
Target: MustHexID("ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f"),
Expiration: 1136239445,
Rest: []rlp.RawValue{{0x82, 0x99, 0x99}, {0x83, 0x99, 0x99, 0x99}},
},
},
{
input: "c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df738443b9a355010203b525a138aa34383fec3d2719a0",
wantPacket: &neighbors{
Nodes: []rpcNode{
{
ID: MustHexID("3155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32"),
IP: net.ParseIP("99.33.22.55").To4(),
UDP: 4444,
TCP: 4445,
},
{
ID: MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069db"),
IP: net.ParseIP("1.2.3.4").To4(),
UDP: 1,
TCP: 1,
},
{
ID: MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aac"),
IP: net.ParseIP("2001:db8:3c4d:15::abcd:ef12"),
UDP: 3333,
TCP: 3333,
},
{
ID: MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73"),
IP: net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"),
UDP: 999,
TCP: 1000,
},
},
Expiration: 1136239445,
Rest: []rlp.RawValue{{0x01}, {0x02}, {0x03}},
},
},
}
func TestForwardCompatibility(t *testing.T) {
testkey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
wantNodeID := PubkeyID(&testkey.PublicKey)
for _, test := range testPackets {
input, err := hex.DecodeString(test.input)
if err != nil {
t.Fatalf("invalid hex: %s", test.input)
}
packet, nodeid, _, err := decodePacket(input)
if err != nil {
t.Errorf("did not accept packet %s\n%v", test.input, err)
continue
}
if !reflect.DeepEqual(packet, test.wantPacket) {
t.Errorf("got %s\nwant %s", spew.Sdump(packet), spew.Sdump(test.wantPacket))
}
if nodeid != wantNodeID {
t.Errorf("got id %v\nwant id %v", nodeid, wantNodeID)
}
}
}
// dgramPipe is a fake UDP socket. It queues all sent datagrams.
type dgramPipe struct {
mu *sync.Mutex

View 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
}

View File

@ -143,7 +143,8 @@ func TestEOFSignal(t *testing.T) {
}
func unhex(str string) []byte {
b, err := hex.DecodeString(strings.Replace(str, "\n", "", -1))
r := strings.NewReplacer("\t", "", " ", "", "\n", "")
b, err := hex.DecodeString(r.Replace(str))
if err != nil {
panic(fmt.Sprintf("invalid hex string: %q", str))
}

View File

@ -56,6 +56,9 @@ type protoHandshake struct {
Caps []Cap
ListenPort uint64
ID discover.NodeID
// Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"`
}
// Peer represents a connected remote node.

View File

@ -24,11 +24,14 @@ import (
"crypto/elliptic"
"crypto/hmac"
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"hash"
"io"
mrand "math/rand"
"net"
"os"
"sync"
"time"
@ -51,9 +54,10 @@ const (
authMsgLen = sigLen + shaLen + pubLen + shaLen + 1
authRespLen = pubLen + shaLen + 1
eciesBytes = 65 + 16 + 32
encAuthMsgLen = authMsgLen + eciesBytes // size of the final ECIES payload sent as initiator's handshake
encAuthRespLen = authRespLen + eciesBytes // size of the final ECIES payload sent as receiver's handshake
eciesOverhead = 65 /* pubkey */ + 16 /* IV */ + 32 /* MAC */
encAuthMsgLen = authMsgLen + eciesOverhead // size of encrypted pre-EIP-8 initiator handshake
encAuthRespLen = authRespLen + eciesOverhead // size of encrypted pre-EIP-8 handshake reply
// total timeout for encryption handshake and protocol
// handshake in both directions.
@ -151,10 +155,6 @@ func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake,
if err := msg.Decode(&hs); err != nil {
return nil, err
}
// validate handshake info
if hs.Version != our.Version {
return nil, DiscIncompatibleVersion
}
if (hs.ID == discover.NodeID{}) {
return nil, DiscInvalidIdentity
}
@ -200,6 +200,29 @@ type secrets struct {
Token []byte
}
// RLPx v4 handshake auth (defined in EIP-8).
type authMsgV4 struct {
gotPlain bool // whether read packet had plain format.
Signature [sigLen]byte
InitiatorPubkey [pubLen]byte
Nonce [shaLen]byte
Version uint
// Ignore additional fields (forward-compatibility)
Rest []rlp.RawValue `rlp:"tail"`
}
// RLPx v4 handshake response (defined in EIP-8).
type authRespV4 struct {
RandomPubkey [pubLen]byte
Nonce [shaLen]byte
Version uint
// Ignore additional fields (forward-compatibility)
Rest []rlp.RawValue `rlp:"tail"`
}
// secrets is called after the handshake is completed.
// It extracts the connection secrets from the handshake values.
func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
@ -215,7 +238,6 @@ func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
RemoteID: h.remoteID,
AES: aesSecret,
MAC: crypto.Sha3(ecdheSecret, aesSecret),
Token: crypto.Sha3(sharedSecret),
}
// setup sha3 instances for the MACs
@ -234,114 +256,89 @@ func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) {
return s, nil
}
func (h *encHandshake) ecdhShared(prv *ecdsa.PrivateKey) ([]byte, error) {
// staticSharedSecret returns the static shared secret, the result
// of key agreement between the local and remote static node key.
func (h *encHandshake) staticSharedSecret(prv *ecdsa.PrivateKey) ([]byte, error) {
return ecies.ImportECDSA(prv).GenerateShared(h.remotePub, sskLen, sskLen)
}
var configSendEIP = os.Getenv("RLPX_EIP8") != ""
// initiatorEncHandshake negotiates a session token on conn.
// it should be called on the dialing side of the connection.
//
// prv is the local client's private key.
// token is the token from a previous session with this node.
func initiatorEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, remoteID discover.NodeID, token []byte) (s secrets, err error) {
h, err := newInitiatorHandshake(remoteID)
h := &encHandshake{initiator: true, remoteID: remoteID}
authMsg, err := h.makeAuthMsg(prv, token)
if err != nil {
return s, err
}
auth, err := h.authMsg(prv, token)
var authPacket []byte
if configSendEIP {
authPacket, err = sealEIP8(authMsg, h)
} else {
authPacket, err = authMsg.sealPlain(h)
}
if err != nil {
return s, err
}
if _, err = conn.Write(auth); err != nil {
if _, err = conn.Write(authPacket); err != nil {
return s, err
}
response := make([]byte, encAuthRespLen)
if _, err = io.ReadFull(conn, response); err != nil {
authRespMsg := new(authRespV4)
authRespPacket, err := readHandshakeMsg(authRespMsg, encAuthRespLen, prv, conn)
if err != nil {
return s, err
}
if err := h.decodeAuthResp(response, prv); err != nil {
if err := h.handleAuthResp(authRespMsg); err != nil {
return s, err
}
return h.secrets(auth, response)
return h.secrets(authPacket, authRespPacket)
}
func newInitiatorHandshake(remoteID discover.NodeID) (*encHandshake, error) {
rpub, err := remoteID.Pubkey()
// makeAuthMsg creates the initiator handshake message.
func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey, token []byte) (*authMsgV4, error) {
rpub, err := h.remoteID.Pubkey()
if err != nil {
return nil, fmt.Errorf("bad remoteID: %v", err)
}
// generate random initiator nonce
n := make([]byte, shaLen)
if _, err := rand.Read(n); err != nil {
h.remotePub = ecies.ImportECDSAPublic(rpub)
// Generate random initiator nonce.
h.initNonce = make([]byte, shaLen)
if _, err := rand.Read(h.initNonce); err != nil {
return nil, err
}
// generate random keypair to use for signing
randpriv, err := ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
// Generate random keypair to for ECDH.
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
if err != nil {
return nil, err
}
h := &encHandshake{
initiator: true,
remoteID: remoteID,
remotePub: ecies.ImportECDSAPublic(rpub),
initNonce: n,
randomPrivKey: randpriv,
}
return h, nil
}
// authMsg creates an encrypted initiator handshake message.
func (h *encHandshake) authMsg(prv *ecdsa.PrivateKey, token []byte) ([]byte, error) {
var tokenFlag byte
if token == nil {
// no session token found means we need to generate shared secret.
// ecies shared secret is used as initial session token for new peers
// generate shared key from prv and remote pubkey
var err error
if token, err = h.ecdhShared(prv); err != nil {
return nil, err
}
} else {
// for known peers, we use stored token from the previous session
tokenFlag = 0x01
// Sign known message: static-shared-secret ^ nonce
token, err = h.staticSharedSecret(prv)
if err != nil {
return nil, err
}
// sign known message:
// ecdh-shared-secret^nonce for new peers
// token^nonce for old peers
signed := xor(token, h.initNonce)
signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
if err != nil {
return nil, err
}
// encode auth message
// signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag
msg := make([]byte, authMsgLen)
n := copy(msg, signature)
n += copy(msg[n:], crypto.Sha3(exportPubkey(&h.randomPrivKey.PublicKey)))
n += copy(msg[n:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
n += copy(msg[n:], h.initNonce)
msg[n] = tokenFlag
// encrypt auth message using remote-pubk
return ecies.Encrypt(rand.Reader, h.remotePub, msg, nil, nil)
msg := new(authMsgV4)
copy(msg.Signature[:], signature)
copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
copy(msg.Nonce[:], h.initNonce)
msg.Version = 4
return msg, nil
}
// decodeAuthResp decode an encrypted authentication response message.
func (h *encHandshake) decodeAuthResp(auth []byte, prv *ecdsa.PrivateKey) error {
msg, err := crypto.Decrypt(prv, auth)
if err != nil {
return fmt.Errorf("could not decrypt auth response (%v)", err)
}
h.respNonce = msg[pubLen : pubLen+shaLen]
h.remoteRandomPub, err = importPublicKey(msg[:pubLen])
if err != nil {
return err
}
// ignore token flag for now
return nil
func (h *encHandshake) handleAuthResp(msg *authRespV4) (err error) {
h.respNonce = msg.Nonce[:]
h.remoteRandomPub, err = importPublicKey(msg.RandomPubkey[:])
return err
}
// receiverEncHandshake negotiates a session token on conn.
@ -350,99 +347,165 @@ func (h *encHandshake) decodeAuthResp(auth []byte, prv *ecdsa.PrivateKey) error
// prv is the local client's private key.
// token is the token from a previous session with this node.
func receiverEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, token []byte) (s secrets, err error) {
// read remote auth sent by initiator.
auth := make([]byte, encAuthMsgLen)
if _, err := io.ReadFull(conn, auth); err != nil {
return s, err
}
h, err := decodeAuthMsg(prv, token, auth)
authMsg := new(authMsgV4)
authPacket, err := readHandshakeMsg(authMsg, encAuthMsgLen, prv, conn)
if err != nil {
return s, err
}
h := new(encHandshake)
if err := h.handleAuthMsg(authMsg, prv); err != nil {
return s, err
}
// send auth response
resp, err := h.authResp(prv, token)
authRespMsg, err := h.makeAuthResp()
if err != nil {
return s, err
}
if _, err = conn.Write(resp); err != nil {
var authRespPacket []byte
if authMsg.gotPlain {
authRespPacket, err = authRespMsg.sealPlain(h)
} else {
authRespPacket, err = sealEIP8(authRespMsg, h)
}
if err != nil {
return s, err
}
return h.secrets(auth, resp)
if _, err = conn.Write(authRespPacket); err != nil {
return s, err
}
return h.secrets(authPacket, authRespPacket)
}
func decodeAuthMsg(prv *ecdsa.PrivateKey, token []byte, auth []byte) (*encHandshake, error) {
var err error
h := new(encHandshake)
// generate random keypair for session
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error {
// Import the remote identity.
h.initNonce = msg.Nonce[:]
h.remoteID = msg.InitiatorPubkey
rpub, err := h.remoteID.Pubkey()
if err != nil {
return nil, err
return fmt.Errorf("bad remoteID: %#v", err)
}
// generate random nonce
h.remotePub = ecies.ImportECDSAPublic(rpub)
// Generate random keypair for ECDH.
// If a private key is already set, use it instead of generating one (for testing).
if h.randomPrivKey == nil {
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
if err != nil {
return err
}
}
// Check the signature.
token, err := h.staticSharedSecret(prv)
if err != nil {
return err
}
signedMsg := xor(token, h.initNonce)
remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg.Signature[:])
if err != nil {
return err
}
h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
return nil
}
func (h *encHandshake) makeAuthResp() (msg *authRespV4, err error) {
// Generate random nonce.
h.respNonce = make([]byte, shaLen)
if _, err = rand.Read(h.respNonce); err != nil {
return nil, err
}
msg, err := crypto.Decrypt(prv, auth)
if err != nil {
return nil, fmt.Errorf("could not decrypt auth message (%v)", err)
}
// decode message parameters
// signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag
h.initNonce = msg[authMsgLen-shaLen-1 : authMsgLen-1]
copy(h.remoteID[:], msg[sigLen+shaLen:sigLen+shaLen+pubLen])
rpub, err := h.remoteID.Pubkey()
if err != nil {
return nil, fmt.Errorf("bad remoteID: %#v", err)
}
h.remotePub = ecies.ImportECDSAPublic(rpub)
// recover remote random pubkey from signed message.
if token == nil {
// TODO: it is an error if the initiator has a token and we don't. check that.
// no session token means we need to generate shared secret.
// ecies shared secret is used as initial session token for new peers.
// generate shared key from prv and remote pubkey.
if token, err = h.ecdhShared(prv); err != nil {
return nil, err
}
}
signedMsg := xor(token, h.initNonce)
remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg[:sigLen])
if err != nil {
return nil, err
}
// validate the sha3 of recovered pubkey
remoteRandomPubMAC := msg[sigLen : sigLen+shaLen]
shaRemoteRandomPub := crypto.Sha3(remoteRandomPub[1:])
if !bytes.Equal(remoteRandomPubMAC, shaRemoteRandomPub) {
return nil, fmt.Errorf("sha3 of recovered ephemeral pubkey does not match checksum in auth message")
}
h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
return h, nil
msg = new(authRespV4)
copy(msg.Nonce[:], h.respNonce)
copy(msg.RandomPubkey[:], exportPubkey(&h.randomPrivKey.PublicKey))
msg.Version = 4
return msg, nil
}
// authResp generates the encrypted authentication response message.
func (h *encHandshake) authResp(prv *ecdsa.PrivateKey, token []byte) ([]byte, error) {
// responder auth message
// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
resp := make([]byte, authRespLen)
n := copy(resp, exportPubkey(&h.randomPrivKey.PublicKey))
n += copy(resp[n:], h.respNonce)
if token == nil {
resp[n] = 0
} else {
resp[n] = 1
func (msg *authMsgV4) sealPlain(h *encHandshake) ([]byte, error) {
buf := make([]byte, authMsgLen)
n := copy(buf, msg.Signature[:])
n += copy(buf[n:], crypto.Sha3(exportPubkey(&h.randomPrivKey.PublicKey)))
n += copy(buf[n:], msg.InitiatorPubkey[:])
n += copy(buf[n:], msg.Nonce[:])
buf[n] = 0 // token-flag
return ecies.Encrypt(rand.Reader, h.remotePub, buf, nil, nil)
}
func (msg *authMsgV4) decodePlain(input []byte) {
n := copy(msg.Signature[:], input)
n += shaLen // skip sha3(initiator-ephemeral-pubk)
n += copy(msg.InitiatorPubkey[:], input[n:])
n += copy(msg.Nonce[:], input[n:])
msg.Version = 4
msg.gotPlain = true
}
func (msg *authRespV4) sealPlain(hs *encHandshake) ([]byte, error) {
buf := make([]byte, authRespLen)
n := copy(buf, msg.RandomPubkey[:])
n += copy(buf[n:], msg.Nonce[:])
return ecies.Encrypt(rand.Reader, hs.remotePub, buf, nil, nil)
}
func (msg *authRespV4) decodePlain(input []byte) {
n := copy(msg.RandomPubkey[:], input)
n += copy(msg.Nonce[:], input[n:])
msg.Version = 4
}
var padSpace = make([]byte, 300)
func sealEIP8(msg interface{}, h *encHandshake) ([]byte, error) {
buf := new(bytes.Buffer)
if err := rlp.Encode(buf, msg); err != nil {
return nil, err
}
// encrypt using remote-pubk
return ecies.Encrypt(rand.Reader, h.remotePub, resp, nil, nil)
// pad with random amount of data. the amount needs to be at least 100 bytes to make
// the message distinguishable from pre-EIP-8 handshakes.
pad := padSpace[:mrand.Intn(len(padSpace)-100)+100]
buf.Write(pad)
prefix := make([]byte, 2)
binary.BigEndian.PutUint16(prefix, uint16(buf.Len()+eciesOverhead))
enc, err := ecies.Encrypt(rand.Reader, h.remotePub, buf.Bytes(), nil, prefix)
return append(prefix, enc...), err
}
type plainDecoder interface {
decodePlain([]byte)
}
func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r io.Reader) ([]byte, error) {
buf := make([]byte, plainSize)
if _, err := io.ReadFull(r, buf); err != nil {
return buf, err
}
// Attempt decoding pre-EIP-8 "plain" format.
key := ecies.ImportECDSA(prv)
if dec, err := key.Decrypt(rand.Reader, buf, nil, nil); err == nil {
msg.decodePlain(dec)
return buf, nil
}
// Could be EIP-8 format, try that.
prefix := buf[:2]
size := binary.BigEndian.Uint16(prefix)
if size < uint16(plainSize) {
return buf, fmt.Errorf("size underflow, need at least %d bytes", plainSize)
}
buf = append(buf, make([]byte, size-uint16(plainSize)+2)...)
if _, err := io.ReadFull(r, buf[plainSize:]); err != nil {
return buf, err
}
dec, err := key.Decrypt(rand.Reader, buf[2:], nil, prefix)
if err != nil {
return buf, err
}
// Can't use rlp.DecodeBytes here because it rejects
// trailing data (forward-compatibility).
s := rlp.NewStream(bytes.NewReader(dec), 0)
return buf, s.Decode(msg)
}
// importPublicKey unmarshals 512 bit public keys.
@ -458,7 +521,11 @@ func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) {
return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey))
}
// TODO: fewer pointless conversions
return ecies.ImportECDSAPublic(crypto.ToECDSAPub(pubKey65)), nil
pub := crypto.ToECDSAPub(pubKey65)
if pub.X == nil {
return nil, fmt.Errorf("invalid public key")
}
return ecies.ImportECDSAPublic(pub), nil
}
func exportPubkey(pub *ecies.PublicKey) []byte {

View File

@ -21,6 +21,7 @@ import (
"crypto/rand"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"reflect"
@ -160,6 +161,7 @@ func TestProtocolHandshake(t *testing.T) {
wg.Add(2)
go func() {
defer wg.Done()
defer fd1.Close()
rlpx := newRLPX(fd0)
remid, err := rlpx.doEncHandshake(prv0, node1)
if err != nil {
@ -176,6 +178,7 @@ func TestProtocolHandshake(t *testing.T) {
t.Errorf("dial side proto handshake error: %v", err)
return
}
phs.Rest = nil
if !reflect.DeepEqual(phs, hs1) {
t.Errorf("dial side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs1))
return
@ -184,6 +187,7 @@ func TestProtocolHandshake(t *testing.T) {
}()
go func() {
defer wg.Done()
defer fd1.Close()
rlpx := newRLPX(fd1)
remid, err := rlpx.doEncHandshake(prv1, nil)
if err != nil {
@ -200,6 +204,7 @@ func TestProtocolHandshake(t *testing.T) {
t.Errorf("listen side proto handshake error: %v", err)
return
}
phs.Rest = nil
if !reflect.DeepEqual(phs, hs0) {
t.Errorf("listen side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs0))
return
@ -214,7 +219,6 @@ func TestProtocolHandshake(t *testing.T) {
func TestProtocolHandshakeErrors(t *testing.T) {
our := &protoHandshake{Version: 3, Caps: []Cap{{"foo", 2}, {"bar", 3}}, Name: "quux"}
id := randomID()
tests := []struct {
code uint64
msg interface{}
@ -240,11 +244,6 @@ func TestProtocolHandshakeErrors(t *testing.T) {
msg: []byte{1, 2, 3},
err: newPeerError(errInvalidMsg, "(code 0) (size 4) rlp: expected input list for p2p.protoHandshake"),
},
{
code: handshakeMsg,
msg: &protoHandshake{Version: 9944, ID: id},
err: DiscIncompatibleVersion,
},
{
code: handshakeMsg,
msg: &protoHandshake{Version: 3},
@ -372,3 +371,227 @@ func TestRLPXFrameRW(t *testing.T) {
}
}
}
type handshakeAuthTest struct {
input string
isPlain bool
wantVersion uint
wantRest []rlp.RawValue
}
var eip8HandshakeAuthTests = []handshakeAuthTest{
// (Auth₁) RLPx v4 plain encoding
{
input: `
048ca79ad18e4b0659fab4853fe5bc58eb83992980f4c9cc147d2aa31532efd29a3d3dc6a3d89eaf
913150cfc777ce0ce4af2758bf4810235f6e6ceccfee1acc6b22c005e9e3a49d6448610a58e98744
ba3ac0399e82692d67c1f58849050b3024e21a52c9d3b01d871ff5f210817912773e610443a9ef14
2e91cdba0bd77b5fdf0769b05671fc35f83d83e4d3b0b000c6b2a1b1bba89e0fc51bf4e460df3105
c444f14be226458940d6061c296350937ffd5e3acaceeaaefd3c6f74be8e23e0f45163cc7ebd7622
0f0128410fd05250273156d548a414444ae2f7dea4dfca2d43c057adb701a715bf59f6fb66b2d1d2
0f2c703f851cbf5ac47396d9ca65b6260bd141ac4d53e2de585a73d1750780db4c9ee4cd4d225173
a4592ee77e2bd94d0be3691f3b406f9bba9b591fc63facc016bfa8
`,
isPlain: true,
wantVersion: 4,
},
// (Auth₂) EIP-8 encoding
{
input: `
01b304ab7578555167be8154d5cc456f567d5ba302662433674222360f08d5f1534499d3678b513b
0fca474f3a514b18e75683032eb63fccb16c156dc6eb2c0b1593f0d84ac74f6e475f1b8d56116b84
9634a8c458705bf83a626ea0384d4d7341aae591fae42ce6bd5c850bfe0b999a694a49bbbaf3ef6c
da61110601d3b4c02ab6c30437257a6e0117792631a4b47c1d52fc0f8f89caadeb7d02770bf999cc
147d2df3b62e1ffb2c9d8c125a3984865356266bca11ce7d3a688663a51d82defaa8aad69da39ab6
d5470e81ec5f2a7a47fb865ff7cca21516f9299a07b1bc63ba56c7a1a892112841ca44b6e0034dee
70c9adabc15d76a54f443593fafdc3b27af8059703f88928e199cb122362a4b35f62386da7caad09
c001edaeb5f8a06d2b26fb6cb93c52a9fca51853b68193916982358fe1e5369e249875bb8d0d0ec3
6f917bc5e1eafd5896d46bd61ff23f1a863a8a8dcd54c7b109b771c8e61ec9c8908c733c0263440e
2aa067241aaa433f0bb053c7b31a838504b148f570c0ad62837129e547678c5190341e4f1693956c
3bf7678318e2d5b5340c9e488eefea198576344afbdf66db5f51204a6961a63ce072c8926c
`,
wantVersion: 4,
wantRest: []rlp.RawValue{},
},
// (Auth₃) RLPx v4 EIP-8 encoding with version 56, additional list elements
{
input: `
01b8044c6c312173685d1edd268aa95e1d495474c6959bcdd10067ba4c9013df9e40ff45f5bfd6f7
2471f93a91b493f8e00abc4b80f682973de715d77ba3a005a242eb859f9a211d93a347fa64b597bf
280a6b88e26299cf263b01b8dfdb712278464fd1c25840b995e84d367d743f66c0e54a586725b7bb
f12acca27170ae3283c1073adda4b6d79f27656993aefccf16e0d0409fe07db2dc398a1b7e8ee93b
cd181485fd332f381d6a050fba4c7641a5112ac1b0b61168d20f01b479e19adf7fdbfa0905f63352
bfc7e23cf3357657455119d879c78d3cf8c8c06375f3f7d4861aa02a122467e069acaf513025ff19
6641f6d2810ce493f51bee9c966b15c5043505350392b57645385a18c78f14669cc4d960446c1757
1b7c5d725021babbcd786957f3d17089c084907bda22c2b2675b4378b114c601d858802a55345a15
116bc61da4193996187ed70d16730e9ae6b3bb8787ebcaea1871d850997ddc08b4f4ea668fbf3740
7ac044b55be0908ecb94d4ed172ece66fd31bfdadf2b97a8bc690163ee11f5b575a4b44e36e2bfb2
f0fce91676fd64c7773bac6a003f481fddd0bae0a1f31aa27504e2a533af4cef3b623f4791b2cca6
d490
`,
wantVersion: 56,
wantRest: []rlp.RawValue{{0x01}, {0x02}, {0xC2, 0x04, 0x05}},
},
}
type handshakeAckTest struct {
input string
wantVersion uint
wantRest []rlp.RawValue
}
var eip8HandshakeRespTests = []handshakeAckTest{
// (Ack₁) RLPx v4 plain encoding
{
input: `
049f8abcfa9c0dc65b982e98af921bc0ba6e4243169348a236abe9df5f93aa69d99cadddaa387662
b0ff2c08e9006d5a11a278b1b3331e5aaabf0a32f01281b6f4ede0e09a2d5f585b26513cb794d963
5a57563921c04a9090b4f14ee42be1a5461049af4ea7a7f49bf4c97a352d39c8d02ee4acc416388c
1c66cec761d2bc1c72da6ba143477f049c9d2dde846c252c111b904f630ac98e51609b3b1f58168d
dca6505b7196532e5f85b259a20c45e1979491683fee108e9660edbf38f3add489ae73e3dda2c71b
d1497113d5c755e942d1
`,
wantVersion: 4,
},
// (Ack₂) EIP-8 encoding
{
input: `
01ea0451958701280a56482929d3b0757da8f7fbe5286784beead59d95089c217c9b917788989470
b0e330cc6e4fb383c0340ed85fab836ec9fb8a49672712aeabbdfd1e837c1ff4cace34311cd7f4de
05d59279e3524ab26ef753a0095637ac88f2b499b9914b5f64e143eae548a1066e14cd2f4bd7f814
c4652f11b254f8a2d0191e2f5546fae6055694aed14d906df79ad3b407d94692694e259191cde171
ad542fc588fa2b7333313d82a9f887332f1dfc36cea03f831cb9a23fea05b33deb999e85489e645f
6aab1872475d488d7bd6c7c120caf28dbfc5d6833888155ed69d34dbdc39c1f299be1057810f34fb
e754d021bfca14dc989753d61c413d261934e1a9c67ee060a25eefb54e81a4d14baff922180c395d
3f998d70f46f6b58306f969627ae364497e73fc27f6d17ae45a413d322cb8814276be6ddd13b885b
201b943213656cde498fa0e9ddc8e0b8f8a53824fbd82254f3e2c17e8eaea009c38b4aa0a3f306e8
797db43c25d68e86f262e564086f59a2fc60511c42abfb3057c247a8a8fe4fb3ccbadde17514b7ac
8000cdb6a912778426260c47f38919a91f25f4b5ffb455d6aaaf150f7e5529c100ce62d6d92826a7
1778d809bdf60232ae21ce8a437eca8223f45ac37f6487452ce626f549b3b5fdee26afd2072e4bc7
5833c2464c805246155289f4
`,
wantVersion: 4,
wantRest: []rlp.RawValue{},
},
// (Ack₃) EIP-8 encoding with version 57, additional list elements
{
input: `
01f004076e58aae772bb101ab1a8e64e01ee96e64857ce82b1113817c6cdd52c09d26f7b90981cd7
ae835aeac72e1573b8a0225dd56d157a010846d888dac7464baf53f2ad4e3d584531fa203658fab0
3a06c9fd5e35737e417bc28c1cbf5e5dfc666de7090f69c3b29754725f84f75382891c561040ea1d
dc0d8f381ed1b9d0d4ad2a0ec021421d847820d6fa0ba66eaf58175f1b235e851c7e2124069fbc20
2888ddb3ac4d56bcbd1b9b7eab59e78f2e2d400905050f4a92dec1c4bdf797b3fc9b2f8e84a482f3
d800386186712dae00d5c386ec9387a5e9c9a1aca5a573ca91082c7d68421f388e79127a5177d4f8
590237364fd348c9611fa39f78dcdceee3f390f07991b7b47e1daa3ebcb6ccc9607811cb17ce51f1
c8c2c5098dbdd28fca547b3f58c01a424ac05f869f49c6a34672ea2cbbc558428aa1fe48bbfd6115
8b1b735a65d99f21e70dbc020bfdface9f724a0d1fb5895db971cc81aa7608baa0920abb0a565c9c
436e2fd13323428296c86385f2384e408a31e104670df0791d93e743a3a5194ee6b076fb6323ca59
3011b7348c16cf58f66b9633906ba54a2ee803187344b394f75dd2e663a57b956cb830dd7a908d4f
39a2336a61ef9fda549180d4ccde21514d117b6c6fd07a9102b5efe710a32af4eeacae2cb3b1dec0
35b9593b48b9d3ca4c13d245d5f04169b0b1
`,
wantVersion: 57,
wantRest: []rlp.RawValue{{0x06}, {0xC2, 0x07, 0x08}, {0x81, 0xFA}},
},
}
func TestHandshakeForwardCompatibility(t *testing.T) {
var (
keyA, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
keyB, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
pubA = crypto.FromECDSAPub(&keyA.PublicKey)[1:]
pubB = crypto.FromECDSAPub(&keyB.PublicKey)[1:]
ephA, _ = crypto.HexToECDSA("869d6ecf5211f1cc60418a13b9d870b22959d0c16f02bec714c960dd2298a32d")
ephB, _ = crypto.HexToECDSA("e238eb8e04fee6511ab04c6dd3c89ce097b11f25d584863ac2b6d5b35b1847e4")
ephPubA = crypto.FromECDSAPub(&ephA.PublicKey)[1:]
ephPubB = crypto.FromECDSAPub(&ephB.PublicKey)[1:]
nonceA = unhex("7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6")
nonceB = unhex("559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd")
_, _, _, _ = pubA, pubB, ephPubA, ephPubB
authSignature = unhex("299ca6acfd35e3d72d8ba3d1e2b60b5561d5af5218eb5bc182045769eb4226910a301acae3b369fffc4a4899d6b02531e89fd4fe36a2cf0d93607ba470b50f7800")
_ = authSignature
)
makeAuth := func(test handshakeAuthTest) *authMsgV4 {
msg := &authMsgV4{Version: test.wantVersion, Rest: test.wantRest, gotPlain: test.isPlain}
copy(msg.Signature[:], authSignature)
copy(msg.InitiatorPubkey[:], pubA)
copy(msg.Nonce[:], nonceA)
return msg
}
makeAck := func(test handshakeAckTest) *authRespV4 {
msg := &authRespV4{Version: test.wantVersion, Rest: test.wantRest}
copy(msg.RandomPubkey[:], ephPubB)
copy(msg.Nonce[:], nonceB)
return msg
}
// check auth msg parsing
for _, test := range eip8HandshakeAuthTests {
r := bytes.NewReader(unhex(test.input))
msg := new(authMsgV4)
ciphertext, err := readHandshakeMsg(msg, encAuthMsgLen, keyB, r)
if err != nil {
t.Errorf("error for input %x:\n %v", unhex(test.input), err)
continue
}
if !bytes.Equal(ciphertext, unhex(test.input)) {
t.Errorf("wrong ciphertext for input %x:\n %x", unhex(test.input), ciphertext)
}
want := makeAuth(test)
if !reflect.DeepEqual(msg, want) {
t.Errorf("wrong msg for input %x:\ngot %s\nwant %s", unhex(test.input), spew.Sdump(msg), spew.Sdump(want))
}
}
// check auth resp parsing
for _, test := range eip8HandshakeRespTests {
input := unhex(test.input)
r := bytes.NewReader(input)
msg := new(authRespV4)
ciphertext, err := readHandshakeMsg(msg, encAuthRespLen, keyA, r)
if err != nil {
t.Errorf("error for input %x:\n %v", input, err)
continue
}
if !bytes.Equal(ciphertext, input) {
t.Errorf("wrong ciphertext for input %x:\n %x", input, err)
}
want := makeAck(test)
if !reflect.DeepEqual(msg, want) {
t.Errorf("wrong msg for input %x:\ngot %s\nwant %s", input, spew.Sdump(msg), spew.Sdump(want))
}
}
// check derivation for (Auth₂, Ack₂) on recipient side
var (
hs = &encHandshake{
initiator: false,
respNonce: nonceB,
randomPrivKey: ecies.ImportECDSA(ephB),
}
authCiphertext = unhex(eip8HandshakeAuthTests[1].input)
authRespCiphertext = unhex(eip8HandshakeRespTests[1].input)
authMsg = makeAuth(eip8HandshakeAuthTests[1])
wantAES = unhex("80e8632c05fed6fc2a13b0f8d31a3cf645366239170ea067065aba8e28bac487")
wantMAC = unhex("2ea74ec5dae199227dff1af715362700e989d889d7a493cb0639691efb8e5f98")
wantFooIngressHash = unhex("0c7ec6340062cc46f5e9f1e3cf86f8c8c403c5a0964f5df0ebd34a75ddc86db5")
)
if err := hs.handleAuthMsg(authMsg, keyB); err != nil {
t.Fatalf("handleAuthMsg: %v", err)
}
derived, err := hs.secrets(authCiphertext, authRespCiphertext)
if err != nil {
t.Fatalf("secrets: %v", err)
}
if !bytes.Equal(derived.AES, wantAES) {
t.Errorf("aes-secret mismatch:\ngot %x\nwant %x", derived.AES, wantAES)
}
if !bytes.Equal(derived.MAC, wantMAC) {
t.Errorf("mac-secret mismatch:\ngot %x\nwant %x", derived.MAC, wantMAC)
}
io.WriteString(derived.IngressMAC, "foo")
fooIngressHash := derived.IngressMAC.Sum(nil)
if !bytes.Equal(fooIngressHash, wantFooIngressHash) {
t.Errorf("ingress-mac('foo') mismatch:\ngot %x\nwant %x", fooIngressHash, wantFooIngressHash)
}
}

View File

@ -25,9 +25,10 @@ var (
MaximumExtraDataSize = big.NewInt(32) // Maximum size extra data may be after Genesis.
ExpByteGas = big.NewInt(10) // Times ceil(log256(exponent)) for the EXP instruction.
SloadGas = big.NewInt(50) // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfor is non-zero.
CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfer is non-zero.
CallNewAccountGas = big.NewInt(25000) // Paid for CALL when the destination address didn't exist prior.
TxGas = big.NewInt(21000) // Per transaction. NOTE: Not payable on data of calls between transactions.
TxGas = big.NewInt(21000) // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
TxGasContractCreation = big.NewInt(53000) // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
TxDataZeroGas = big.NewInt(4) // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.
QuadCoeffDiv = big.NewInt(512) // Divisor for the quadratic particle of the memory cost equation.
@ -40,7 +41,7 @@ var (
Sha256WordGas = big.NewInt(12) //
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block.
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
Sha256Gas = big.NewInt(60) //

33
params/util.go Normal file
View 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
}

View File

@ -63,11 +63,12 @@ type Decoder interface {
// must contain an element for each decoded field. Decode returns an
// error if there are too few or too many elements.
//
// The decoding of struct fields honours one particular struct tag,
// "nil". This tag applies to pointer-typed fields and changes the
// The decoding of struct fields honours two struct tags, "tail" and
// "nil". For an explanation of "tail", see the example.
// The "nil" tag applies to pointer-typed fields and changes the
// decoding rules for the field such that input values of size zero
// decode as a nil pointer. This tag can be useful when decoding recursive
// types.
// decode as a nil pointer. This tag can be useful when decoding
// recursive types.
//
// type StructWithEmptyOK struct {
// Foo *[20]byte `rlp:"nil"`
@ -190,7 +191,7 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
case kind == reflect.String:
return decodeString, nil
case kind == reflect.Slice || kind == reflect.Array:
return makeListDecoder(typ)
return makeListDecoder(typ, tags)
case kind == reflect.Struct:
return makeStructDecoder(typ)
case kind == reflect.Ptr:
@ -264,7 +265,7 @@ func decodeBigInt(s *Stream, val reflect.Value) error {
return nil
}
func makeListDecoder(typ reflect.Type) (decoder, error) {
func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) {
etype := typ.Elem()
if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) {
if typ.Kind() == reflect.Array {
@ -277,15 +278,26 @@ func makeListDecoder(typ reflect.Type) (decoder, error) {
if err != nil {
return nil, err
}
isArray := typ.Kind() == reflect.Array
return func(s *Stream, val reflect.Value) error {
if isArray {
var dec decoder
switch {
case typ.Kind() == reflect.Array:
dec = func(s *Stream, val reflect.Value) error {
return decodeListArray(s, val, etypeinfo.decoder)
} else {
}
case tag.tail:
// A slice with "tail" tag can occur as the last field
// of a struct and is upposed to swallow all remaining
// list elements. The struct decoder already called s.List,
// proceed directly to decoding the elements.
dec = func(s *Stream, val reflect.Value) error {
return decodeSliceElems(s, val, etypeinfo.decoder)
}
default:
dec = func(s *Stream, val reflect.Value) error {
return decodeListSlice(s, val, etypeinfo.decoder)
}
}, nil
}
return dec, nil
}
func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
@ -297,7 +309,13 @@ func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
val.Set(reflect.MakeSlice(val.Type(), 0, 0))
return s.ListEnd()
}
if err := decodeSliceElems(s, val, elemdec); err != nil {
return err
}
return s.ListEnd()
}
func decodeSliceElems(s *Stream, val reflect.Value, elemdec decoder) error {
i := 0
for ; ; i++ {
// grow slice if necessary
@ -323,12 +341,11 @@ func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
if i < val.Len() {
val.SetLen(i)
}
return s.ListEnd()
return nil
}
func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error {
_, err := s.List()
if err != nil {
if _, err := s.List(); err != nil {
return wrapStreamError(err, val.Type())
}
vlen := val.Len()
@ -398,11 +415,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) {
return nil, err
}
dec := func(s *Stream, val reflect.Value) (err error) {
if _, err = s.List(); err != nil {
if _, err := s.List(); err != nil {
return wrapStreamError(err, typ)
}
for _, f := range fields {
err = f.info.decoder(s, val.Field(f.index))
err := f.info.decoder(s, val.Field(f.index))
if err == EOL {
return &decodeError{msg: "too few elements", typ: typ}
} else if err != nil {

33
rlp/decode_tail_test.go Normal file
View 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"
}

View File

@ -312,6 +312,26 @@ type recstruct struct {
Child *recstruct `rlp:"nil"`
}
type invalidTail1 struct {
A uint `rlp:"tail"`
B string
}
type invalidTail2 struct {
A uint
B string `rlp:"tail"`
}
type tailRaw struct {
A uint
Tail []RawValue `rlp:"tail"`
}
type tailUint struct {
A uint
Tail []uint `rlp:"tail"`
}
var (
veryBigInt = big.NewInt(0).Add(
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
@ -437,6 +457,38 @@ var decodeTests = []decodeTest{
ptr: new(recstruct),
error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I",
},
{
input: "C0",
ptr: new(invalidTail1),
error: "rlp: invalid struct tag \"tail\" for rlp.invalidTail1.A (must be on last field)",
},
{
input: "C0",
ptr: new(invalidTail2),
error: "rlp: invalid struct tag \"tail\" for rlp.invalidTail2.B (field type is not slice)",
},
{
input: "C50102C20102",
ptr: new(tailUint),
error: "rlp: expected input string or byte for uint, decoding into (rlp.tailUint).Tail[1]",
},
// struct tag "tail"
{
input: "C3010203",
ptr: new(tailRaw),
value: tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}},
},
{
input: "C20102",
ptr: new(tailRaw),
value: tailRaw{A: 1, Tail: []RawValue{unhex("02")}},
},
{
input: "C101",
ptr: new(tailRaw),
value: tailRaw{A: 1, Tail: []RawValue{}},
},
// RawValue
{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},

View File

@ -345,7 +345,7 @@ var (
)
// makeWriter creates a writer function for the given type.
func makeWriter(typ reflect.Type) (writer, error) {
func makeWriter(typ reflect.Type, ts tags) (writer, error) {
kind := typ.Kind()
switch {
case typ == rawValueType:
@ -371,7 +371,7 @@ func makeWriter(typ reflect.Type) (writer, error) {
case kind == reflect.Array && isByte(typ.Elem()):
return writeByteArray, nil
case kind == reflect.Slice || kind == reflect.Array:
return makeSliceWriter(typ)
return makeSliceWriter(typ, ts)
case kind == reflect.Struct:
return makeStructWriter(typ)
case kind == reflect.Ptr:
@ -507,20 +507,21 @@ func writeInterface(val reflect.Value, w *encbuf) error {
return ti.writer(eval, w)
}
func makeSliceWriter(typ reflect.Type) (writer, error) {
func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) {
etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{})
if err != nil {
return nil, err
}
writer := func(val reflect.Value, w *encbuf) error {
lh := w.list()
if !ts.tail {
defer w.listEnd(w.list())
}
vlen := val.Len()
for i := 0; i < vlen; i++ {
if err := etypeinfo.writer(val.Index(i), w); err != nil {
return err
}
}
w.listEnd(lh)
return nil
}
return writer, nil

View File

@ -214,6 +214,10 @@ var encTests = []encTest{
{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
{val: &recstruct{5, nil}, output: "C205C0"},
{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"},
{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
// nil
{val: (*uint)(nil), output: "80"},

View File

@ -17,7 +17,9 @@
package rlp
import (
"fmt"
"reflect"
"strings"
"sync"
)
@ -33,7 +35,13 @@ type typeinfo struct {
// represents struct tags
type tags struct {
// rlp:"nil" controls whether empty input results in a nil pointer.
nilOK bool
// rlp:"tail" controls whether this field swallows additional list
// elements. It can only be set for the last field, which must be
// of slice type.
tail bool
}
type typekey struct {
@ -89,7 +97,10 @@ type field struct {
func structFields(typ reflect.Type) (fields []field, err error) {
for i := 0; i < typ.NumField(); i++ {
if f := typ.Field(i); f.PkgPath == "" { // exported
tags := parseStructTag(f.Tag.Get("rlp"))
tags, err := parseStructTag(typ, i)
if err != nil {
return nil, err
}
info, err := cachedTypeInfo1(f.Type, tags)
if err != nil {
return nil, err
@ -100,8 +111,27 @@ func structFields(typ reflect.Type) (fields []field, err error) {
return fields, nil
}
func parseStructTag(tag string) tags {
return tags{nilOK: tag == "nil"}
func parseStructTag(typ reflect.Type, fi int) (tags, error) {
f := typ.Field(fi)
var ts tags
for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
switch t = strings.TrimSpace(t); t {
case "":
case "nil":
ts.nilOK = true
case "tail":
ts.tail = true
if fi != typ.NumField()-1 {
return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name)
}
if f.Type.Kind() != reflect.Slice {
return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name)
}
default:
return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name)
}
}
return ts, nil
}
func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) {
@ -109,7 +139,7 @@ func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) {
if info.decoder, err = makeDecoder(typ, tags); err != nil {
return nil, err
}
if info.writer, err = makeWriter(typ); err != nil {
if info.writer, err = makeWriter(typ, tags); err != nil {
return nil, err
}
return info, nil

View File

@ -661,7 +661,7 @@ func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
pending := self.ethereum.TxPool().GetTransactions()
for _, p := range pending {
if pFrom, err := p.From(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
if pFrom, err := p.FromFrontier(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
self.ethereum.TxPool().RemoveTx(common.HexToHash(args.Tx.Hash))
return self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data)
}
@ -688,7 +688,7 @@ func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error
var ltxs []*tx
for _, tx := range txs {
if from, _ := tx.From(); accountSet.Has(from) {
if from, _ := tx.FromFrontier(); accountSet.Has(from) {
ltxs = append(ltxs, newTx(tx))
}
}

View File

@ -349,7 +349,7 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes {
// v.BlockHash =
// v.BlockNumber =
// v.TxIndex =
from, _ := tx.From()
from, _ := tx.FromFrontier()
v.From = newHexData(from)
v.To = newHexData(tx.To())
v.Value = newHexNum(tx.Value())

View File

@ -17,11 +17,15 @@
package tests
import (
"math/big"
"path/filepath"
"testing"
"github.com/ethereum/go-ethereum/params"
)
func TestBcValidBlockTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -29,6 +33,7 @@ func TestBcValidBlockTests(t *testing.T) {
}
func TestBcUncleHeaderValidityTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -36,6 +41,7 @@ func TestBcUncleHeaderValidityTests(t *testing.T) {
}
func TestBcUncleTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -43,6 +49,7 @@ func TestBcUncleTests(t *testing.T) {
}
func TestBcForkUncleTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -50,6 +57,7 @@ func TestBcForkUncleTests(t *testing.T) {
}
func TestBcInvalidHeaderTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -57,6 +65,7 @@ func TestBcInvalidHeaderTests(t *testing.T) {
}
func TestBcInvalidRLPTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -64,6 +73,7 @@ func TestBcInvalidRLPTests(t *testing.T) {
}
func TestBcRPCAPITests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -71,6 +81,7 @@ func TestBcRPCAPITests(t *testing.T) {
}
func TestBcForkBlockTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -78,6 +89,7 @@ func TestBcForkBlockTests(t *testing.T) {
}
func TestBcForkStress(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -85,6 +97,10 @@ func TestBcForkStress(t *testing.T) {
}
func TestBcTotalDifficulty(t *testing.T) {
// skip because these will fail due to selfish mining fix
t.Skip()
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -92,6 +108,7 @@ func TestBcTotalDifficulty(t *testing.T) {
}
func TestBcWallet(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -99,6 +116,7 @@ func TestBcWallet(t *testing.T) {
}
func TestBcGasPricer(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -107,6 +125,7 @@ func TestBcGasPricer(t *testing.T) {
// TODO: iterate over files once we got more than a few
func TestBcRandom(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -114,6 +133,10 @@ func TestBcRandom(t *testing.T) {
}
func TestBcMultiChain(t *testing.T) {
// skip due to selfish mining
t.Skip()
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
@ -121,8 +144,98 @@ func TestBcMultiChain(t *testing.T) {
}
func TestBcState(t *testing.T) {
params.HomesteadBlock = big.NewInt(1000000)
err := RunBlockTest(filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
// Homestead tests
func TestHomesteadBcValidBlockTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcUncleTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcRPCAPITests(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcForkStress(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcTotalDifficulty(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcWallet(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcGasPricer(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcMultiChain(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcState(t *testing.T) {
params.HomesteadBlock = big.NewInt(0)
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}

View File

@ -146,7 +146,6 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
}
for name, test := range bt {
// if the test should be skipped, return
if skipTest[name] {
glog.Infoln("Skipping block test", name)
continue
@ -192,6 +191,7 @@ func runBlockTest(test *BlockTest) error {
}
cm := ethereum.BlockChain()
//vm.Debug = true
validBlocks, err := test.TryBlocksInsert(cm)
if err != nil {
return err
@ -292,12 +292,13 @@ func (t *BlockTest) TryBlocksInsert(blockchain *core.BlockChain) ([]btBlock, err
}
}
// RLP decoding worked, try to insert into chain:
_, err = blockchain.InsertChain(types.Blocks{cb})
blocks := types.Blocks{cb}
i, err := blockchain.InsertChain(blocks)
if err != nil {
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, fmt.Errorf("Block insertion into chain failed: %v", err)
return nil, fmt.Errorf("Block #%v insertion into chain failed: %v", blocks[i].Number(), err)
}
}
if b.BlockHeader == nil {

0
tests/files/ABITests/basic_abi_tests.json Normal file → Executable file
View File

0
tests/files/BasicTests/blockgenesistest.json Normal file → Executable file
View File

0
tests/files/BasicTests/crypto.json Normal file → Executable file
View File

0
tests/files/BasicTests/difficulty.json Normal file → Executable file
View File

View 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"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

0
tests/files/BasicTests/genesishashestest.json Normal file → Executable file
View File

0
tests/files/BasicTests/hexencodetest.json Normal file → Executable file
View File

0
tests/files/BasicTests/keyaddrtest.json Normal file → Executable file
View File

0
tests/files/BasicTests/txtest.json Normal file → Executable file
View File

View 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" : {
}
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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" : {
}
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

View 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