parent
0b979c507d
commit
15c72f3c6b
|
@ -47,7 +47,6 @@
|
||||||
revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8"
|
revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "develop"
|
|
||||||
name = "github.com/ethereum/go-ethereum"
|
name = "github.com/ethereum/go-ethereum"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -89,7 +88,6 @@
|
||||||
"internal/ethapi",
|
"internal/ethapi",
|
||||||
"les",
|
"les",
|
||||||
"les/flowcontrol",
|
"les/flowcontrol",
|
||||||
"les/status",
|
|
||||||
"light",
|
"light",
|
||||||
"log",
|
"log",
|
||||||
"log/term",
|
"log/term",
|
||||||
|
@ -106,11 +104,10 @@
|
||||||
"rpc",
|
"rpc",
|
||||||
"trie",
|
"trie",
|
||||||
"whisper/mailserver",
|
"whisper/mailserver",
|
||||||
"whisper/notifications",
|
|
||||||
"whisper/whisperv5"
|
"whisper/whisperv5"
|
||||||
]
|
]
|
||||||
revision = "5b2cc44bf2b32bb482def02d7c8fa32ba08d0bf4"
|
revision = "4bb3c89d44e372e6a9ab85a8be0c9345265c763a"
|
||||||
source = "https://github.com/status-im/go-ethereum.git"
|
version = "v1.7.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/go-playground/locales"
|
name = "github.com/go-playground/locales"
|
||||||
|
@ -415,6 +412,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "1e24f8d3adca6619451ee4406b8064268631ad03c06fdc6323abc00a974797ac"
|
inputs-digest = "15f735a948b26a34148ed3fa3a1d21cb1a3c45d0b87eb490a2ca1a514e4b1250"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
ignored = ["github.com/ethereum/go-ethereum/whisper/notifications"]
|
||||||
|
|
||||||
[prune]
|
[prune]
|
||||||
unused-packages = true
|
unused-packages = true
|
||||||
go-tests = true
|
go-tests = true
|
||||||
|
@ -21,10 +23,8 @@
|
||||||
revision = "dcd4997b0664bcfd6ef48e4ae9da8396e08b1cd9"
|
revision = "dcd4997b0664bcfd6ef48e4ae9da8396e08b1cd9"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
# fork of `go-ethereum` with Status patches
|
|
||||||
name = "github.com/ethereum/go-ethereum"
|
name = "github.com/ethereum/go-ethereum"
|
||||||
branch = "develop"
|
branch = "release/1.7"
|
||||||
source = "https://github.com/status-im/go-ethereum.git"
|
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
|
|
17
Makefile
17
Makefile
|
@ -157,12 +157,19 @@ clean: ##@other Cleanup
|
||||||
deep-clean: clean
|
deep-clean: clean
|
||||||
rm -Rdf .ethereumtest/StatusChain
|
rm -Rdf .ethereumtest/StatusChain
|
||||||
|
|
||||||
vendor-check:
|
vendor-check: ##@dependencies Require all new patches and disallow other changes
|
||||||
@dep ensure
|
./_assets/patches/patcher -c
|
||||||
./_assets/ci/validate-vendor.sh
|
./_assets/ci/isolate-vendor-check.sh
|
||||||
|
|
||||||
dep-install:
|
dep-ensure: ##@dependencies Dep ensure and apply all patches
|
||||||
|
@dep ensure
|
||||||
|
./_assets/patches/patcher
|
||||||
|
|
||||||
|
dep-install: ##@dependencies Install vendoring tool
|
||||||
go get -u github.com/golang/dep/cmd/dep
|
go get -u github.com/golang/dep/cmd/dep
|
||||||
|
|
||||||
patch:
|
patch: ##@patching Revert and apply all patches
|
||||||
./_assets/patches/patcher
|
./_assets/patches/patcher
|
||||||
|
|
||||||
|
patch-revert: ##@patching Revert all patches only
|
||||||
|
./_assets/patches/patcher -r
|
||||||
|
|
|
@ -14,7 +14,7 @@ It's written in Go and requires Go 1.8 or above.
|
||||||
|
|
||||||
It uses Makefile to do most common actions. See `make help` output for available commands.
|
It uses Makefile to do most common actions. See `make help` output for available commands.
|
||||||
|
|
||||||
status-go uses [forked ethereum-go](https://github.com/status-im/go-ethereum) with [some patches applied](./geth-patches/) in it, located under [`vendor/`](./vendor/github.com/ethereum/go-ethereum) directory. See [geth-patches README](./geth-patches/README.md) for more info.
|
status-go uses [ethereum-go](https://github.com/status-im/go-ethereum) with [some patches applied](./_assets/patches/geth) in it, located under [`vendor/`](./vendor/github.com/ethereum/go-ethereum) directory. See [geth patches README](./_assets/patches/geth/README.md) for more info.
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
There are two main modes status-go can be built:
|
There are two main modes status-go can be built:
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This is a hack to isolate vendor check in a
|
||||||
|
# separate clean state. Without this, validate-vendor.sh
|
||||||
|
# doesn't like our workflow with patches.
|
||||||
|
#
|
||||||
|
# How it works:
|
||||||
|
# 1) Stashes all changes and checks out to a temporary branch.
|
||||||
|
# 2) Reverts all patches and commits changes.
|
||||||
|
# 3) Runs "dep ensure" and validate-vendor.sh. Saves exit code and message.
|
||||||
|
# 4) Commits any changes.
|
||||||
|
# 5) Goes back to previous branch and removes the temporary branch.
|
||||||
|
# 6) Applies stashed changes.
|
||||||
|
# 7) Prints the message and exits with the exit code.
|
||||||
|
|
||||||
|
timestamp() {
|
||||||
|
date +"%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
tempBranchName="isolated-vendor-check-$(timestamp)"
|
||||||
|
|
||||||
|
# Stash current changes first, apply later before exiting.
|
||||||
|
hasChanges=0
|
||||||
|
changes=($(git status --porcelain))
|
||||||
|
if [ "$changes" ]; then
|
||||||
|
git stash
|
||||||
|
hasChanges=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
branchName="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
|
||||||
|
git checkout -b $tempBranchName
|
||||||
|
|
||||||
|
# Revert all patches.
|
||||||
|
$(pwd)/_assets/patches/patcher -r
|
||||||
|
git add .
|
||||||
|
git commit -m "vendor check - auto"
|
||||||
|
|
||||||
|
# Do vendor check.
|
||||||
|
dep ensure
|
||||||
|
msg=$("$(pwd)/_assets/ci/validate-vendor.sh")
|
||||||
|
failed=$?
|
||||||
|
git add .
|
||||||
|
git commit -m "vendor check - auto"
|
||||||
|
|
||||||
|
# Go back to previous branch, clean and apply stashed.
|
||||||
|
git checkout "$branchName"
|
||||||
|
git branch -D $tempBranchName
|
||||||
|
if [ $hasChanges -eq 1 ]; then
|
||||||
|
git stash apply > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $msg
|
||||||
|
exit $failed
|
|
@ -25,6 +25,7 @@
|
||||||
## Checking-out all dependencies
|
## Checking-out all dependencies
|
||||||
|
|
||||||
`dep ensure` - download all the dependencies based on `Gopkg.lock`.
|
`dep ensure` - download all the dependencies based on `Gopkg.lock`.
|
||||||
|
`make dep-ensure` - ensure all patches are applied, too. **(Recommended)**
|
||||||
|
|
||||||
`Gopkg.lock` is kept inact if it is in-sync with `Gopkg.toml`. If the `toml`
|
`Gopkg.lock` is kept inact if it is in-sync with `Gopkg.toml`. If the `toml`
|
||||||
file is changed, `dep ensure` will re-generate `Gopkg.lock` as well.
|
file is changed, `dep ensure` will re-generate `Gopkg.lock` as well.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Status-go uses [go-ethereum](https://github.com/ethereum/go-ethereum) (**upstream**) as its dependency. As any other Go dependency `go-ethereum` code is vendored and stored in `vendor/` folder.
|
Status-go uses [go-ethereum](https://github.com/ethereum/go-ethereum) (**upstream**) as its dependency. As any other Go dependency `go-ethereum` code is vendored and stored in `vendor/` folder.
|
||||||
|
|
||||||
However, there are a few changes has been made to the upstream, that are specific to Status and should not be merged to the upstream. We keep those changes as a set of patches, that can be applied upon each next release of `go-ethereum`. Patched version of `go-ethereum` is available in the [status-im/go-ethereum](https://github.com/status/go-ethereum) repo.
|
However, there are a few changes has been made to the upstream, that are specific to Status and should not be merged to the upstream. We keep those changes as a set of patches, that can be applied upon each next release of `go-ethereum`. Patched version of `go-ethereum` is available in vendor folder.
|
||||||
|
|
||||||
We try to minimize number and amount of changes in those patches as much as possible, and whereas possible, to contribute changes into the upstream.
|
We try to minimize number and amount of changes in those patches as much as possible, and whereas possible, to contribute changes into the upstream.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ We try to minimize number and amount of changes in those patches as much as poss
|
||||||
|
|
||||||
Instructions for creating a patch from the command line:
|
Instructions for creating a patch from the command line:
|
||||||
|
|
||||||
1. Enter the command line at the status-im/go-ethereum repo root
|
1. Enter the command line at the go-ethereum dependency root in vendor folder.
|
||||||
1. Create the patch:
|
1. Create the patch:
|
||||||
1. If you already have a commit that represents the change, find its SHA1 (e.g. `$COMMIT_SHA1`) and do `git diff $COMMIT_SHA1 > file.patch`
|
1. If you already have a commit that represents the change, find its SHA1 (e.g. `$COMMIT_SHA1`) and do `git diff $COMMIT_SHA1 > file.patch`
|
||||||
1. If the files are staged, do `git diff --cached > file.patch`
|
1. If the files are staged, do `git diff --cached > file.patch`
|
||||||
|
@ -31,64 +31,12 @@ Instructions for creating a patch from the command line:
|
||||||
- [`0014-whisperv6-notifications.patch`](./0014-whisperv6-notifications.patch) — adds Whisper v6 notifications (need to be reviewed and documented)
|
- [`0014-whisperv6-notifications.patch`](./0014-whisperv6-notifications.patch) — adds Whisper v6 notifications (need to be reviewed and documented)
|
||||||
- [`0015-whisperv6-envelopes-tracing.patch`](./0015-whisperv6-envelopes-tracing.patch) — adds Whisper v6 envelope tracing (need to be reviewed and documented)
|
- [`0015-whisperv6-envelopes-tracing.patch`](./0015-whisperv6-envelopes-tracing.patch) — adds Whisper v6 envelope tracing (need to be reviewed and documented)
|
||||||
|
|
||||||
# Updating upstream version
|
# Updating
|
||||||
|
|
||||||
When a new stable release of `go-ethereum` comes out, we need to upgrade our fork and vendored copy.
|
When a new stable release of `go-ethereum` comes out, we need to upgrade our vendored copy. We use `dep` for vendoring, so for upgrading:
|
||||||
|
|
||||||
**Note: The process is completely repeatable, so it's safe to remove current `go-ethereum` directory, clone latest upstream version and apply patches from scratch.**
|
- Change target branch for `go-ethereum` in `Gopkg.toml`.
|
||||||
|
- `dep ensure -update github.com/ethereum/go-ethereum`
|
||||||
|
- `make dep-ensure`
|
||||||
|
|
||||||
### Using existing fork repo (recommended)
|
This will ensure that dependency is upgraded and fully patched. Upon success, you can do `make vendor-check` after committing all the changes, in order to ensure that all changes are valid.
|
||||||
|
|
||||||
#### I. In our fork at /status-im/go-ethereum.
|
|
||||||
|
|
||||||
1. Remove the local `develop` branch.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch -D develop
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Pull upstream release branch into `develop` branch.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git pull git@github.com:ethereum/go-ethereum.git <release_branch>:develop
|
|
||||||
```
|
|
||||||
In our case `<release_branch>` would be `release/1.7` because the current stable version is
|
|
||||||
1.7.x.
|
|
||||||
|
|
||||||
1. Apply patches
|
|
||||||
|
|
||||||
```bash
|
|
||||||
for patch in $GOPATH/src/github.com/status-im/status-go/_assets/patches/geth/*.patch;
|
|
||||||
do
|
|
||||||
patch -p1 < $patch;
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
Once patches applied, you might want to inspect changes between current vendored version and newly patched version by this command:
|
|
||||||
```bash
|
|
||||||
diff -Nru -x "*_test.go" -x "vendor" -x ".git" -x "tests" -x "build" --brief $GOPATH/src/github.com/status-im/go-ethereum $GOPATH/src/github.com/status-im/status-go/vendor/github.com/ethereum/go-ethereum
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Push `develop` branch to our remote, rewriting history
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git push -f origin develop
|
|
||||||
```
|
|
||||||
|
|
||||||
#### II. In status-go repository
|
|
||||||
|
|
||||||
1. Update vendored `go-ethereum` (note that we use upstream's address there, we override the download link to our fork address in `Gopkg.toml`)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dep ensure --update github.com/ethereum/go-ethereum
|
|
||||||
```
|
|
||||||
|
|
||||||
`Gopkg.lock` will change and files within `vendor/ethereum/go-ethereum`.
|
|
||||||
|
|
||||||
1. Run tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make ci
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Commit & push changes, create a PR
|
|
||||||
|
|
|
@ -9,17 +9,25 @@
|
||||||
# Usage: ./patcher -p <base_path> -r -v
|
# Usage: ./patcher -p <base_path> -r -v
|
||||||
# -p: <base_path> is where to apply to (a go-ethereum package)
|
# -p: <base_path> is where to apply to (a go-ethereum package)
|
||||||
# -r: reverts all and exit if this flag is present
|
# -r: reverts all and exit if this flag is present
|
||||||
|
# -c: reverts all to see what's applied, applies all previously applied back again,
|
||||||
|
# reports unapplied patches in this branch by comparing with "develop" including
|
||||||
|
# uncommitted ones and exits (with 1 if there are any)
|
||||||
# -v: verbose error reporting about failed patch
|
# -v: verbose error reporting about failed patch
|
||||||
#
|
#
|
||||||
# If -p is not present, default path is as below ($basepath).
|
# If -p is not present, default path is as below ($basepath).
|
||||||
|
|
||||||
patches=($( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/geth/*.patch)
|
dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
patches=("$dir"/geth/*.patch)
|
||||||
|
|
||||||
|
# Use this branch as a reference for comparing patches
|
||||||
|
# in current branch (-c option).
|
||||||
|
baseBranch="develop"
|
||||||
|
|
||||||
# Base path is vendor/github.com/ethereum/go-ethereum
|
# Base path is vendor/github.com/ethereum/go-ethereum
|
||||||
# unless specified.
|
# unless specified.
|
||||||
basepath="vendor/github.com/ethereum/go-ethereum"
|
basepath="vendor/github.com/ethereum/go-ethereum"
|
||||||
verbose=0
|
verbose=0
|
||||||
while getopts :prv opt; do
|
while getopts :prcv opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
p)
|
p)
|
||||||
basepath=$OPTARG
|
basepath=$OPTARG
|
||||||
|
@ -32,6 +40,54 @@ while getopts :prv opt; do
|
||||||
echo "Reverted all."
|
echo "Reverted all."
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
|
c)
|
||||||
|
applied=()
|
||||||
|
unapplied=()
|
||||||
|
# Finds applied patches using reverse order and
|
||||||
|
# notes them down.
|
||||||
|
for ((i=${#patches[@]}-1; i>=0; i--)); do
|
||||||
|
f=${patches[$i]}
|
||||||
|
git apply "$f" --directory="$basepath" -R > /dev/null 2>&1
|
||||||
|
if [ $? -eq 1 ]; then
|
||||||
|
unapplied+=("$f")
|
||||||
|
else
|
||||||
|
applied+=("$f")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# Applies reverted patches back again.
|
||||||
|
for ((i=${#applied[@]}-1; i>=0; i--)); do
|
||||||
|
f=${applied[$i]}
|
||||||
|
git apply "$f" --directory="$basepath" > /dev/null 2>&1
|
||||||
|
done
|
||||||
|
# Sorts out new patches' paths by comparing with base branch.
|
||||||
|
fromBaseBranch=($(git diff $baseBranch --stat | grep "\\.patch" |
|
||||||
|
while IFS=" " read -r -a line; do
|
||||||
|
path="$(pwd)/${line[0]}"
|
||||||
|
echo "$path"
|
||||||
|
done
|
||||||
|
))
|
||||||
|
# Also does the same with uncommitted.
|
||||||
|
uncommitted=($(git status -u --porcelain | grep "\\.patch" |
|
||||||
|
while IFS=" " read -r -a line; do
|
||||||
|
length=${#line[@]}
|
||||||
|
path="$(pwd)/${line[$((length - 1))]}"
|
||||||
|
echo "$path"
|
||||||
|
done
|
||||||
|
))
|
||||||
|
newPatches=( "${fromBaseBranch[@]}" "${uncommitted[@]}" )
|
||||||
|
# Checks new patches and exits with 1 if there are unapplied.
|
||||||
|
hasUnapplied=0
|
||||||
|
for newPatch in "${newPatches[@]}"; do
|
||||||
|
for unapp in "${unapplied[@]}"; do
|
||||||
|
if [ "$unapp" == "$newPatch" ]; then
|
||||||
|
echo "Recently added/changed but not applied: $unapp"
|
||||||
|
hasUnapplied=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
exit $hasUnapplied
|
||||||
|
;;
|
||||||
v)
|
v)
|
||||||
verbose=1
|
verbose=1
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -98,8 +98,6 @@ var (
|
||||||
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
|
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
|
||||||
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
|
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
|
||||||
argSaveDir = flag.String("savedir", "", "directory where incoming messages will be saved as files")
|
argSaveDir = flag.String("savedir", "", "directory where incoming messages will be saved as files")
|
||||||
argSymPass = flag.String("sympass", "", "SymKey password")
|
|
||||||
argMsPass = flag.String("mspass", "", "Mailserver password")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -148,13 +146,6 @@ func processArgs() {
|
||||||
} else if *fileExMode {
|
} else if *fileExMode {
|
||||||
utils.Fatalf("Parameter 'savedir' is mandatory for file exchange mode")
|
utils.Fatalf("Parameter 'savedir' is mandatory for file exchange mode")
|
||||||
}
|
}
|
||||||
if len(*argSymPass) > 0 {
|
|
||||||
symPass = *argSymPass
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*argMsPass) > 0 {
|
|
||||||
msPassword = *argMsPass
|
|
||||||
}
|
|
||||||
|
|
||||||
if *echoMode {
|
if *echoMode {
|
||||||
echo()
|
echo()
|
||||||
|
@ -424,24 +415,10 @@ func run() {
|
||||||
} else if *fileExMode {
|
} else if *fileExMode {
|
||||||
sendFilesLoop()
|
sendFilesLoop()
|
||||||
} else {
|
} else {
|
||||||
pingLoop() // instead of sendLoop()
|
sendLoop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pingLoop() {
|
|
||||||
ticker := time.NewTicker(time.Second * 120)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
fmt.Println("I am alive: ", time.Now())
|
|
||||||
case <-done:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendLoop() {
|
func sendLoop() {
|
||||||
for {
|
for {
|
||||||
s := scanLine("")
|
s := scanLine("")
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
// 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 tests implements execution of Ethereum JSON tests.
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A BlockTest checks handling of entire blocks.
|
||||||
|
type BlockTest struct {
|
||||||
|
json btJSON
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *BlockTest) UnmarshalJSON(in []byte) error {
|
||||||
|
return json.Unmarshal(in, &t.json)
|
||||||
|
}
|
||||||
|
|
||||||
|
type btJSON struct {
|
||||||
|
Blocks []btBlock `json:"blocks"`
|
||||||
|
Genesis btHeader `json:"genesisBlockHeader"`
|
||||||
|
Pre core.GenesisAlloc `json:"pre"`
|
||||||
|
Post core.GenesisAlloc `json:"postState"`
|
||||||
|
BestBlock common.UnprefixedHash `json:"lastblockhash"`
|
||||||
|
Network string `json:"network"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type btBlock struct {
|
||||||
|
BlockHeader *btHeader
|
||||||
|
Rlp string
|
||||||
|
UncleHeaders []*btHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
|
||||||
|
|
||||||
|
type btHeader struct {
|
||||||
|
Bloom types.Bloom
|
||||||
|
Coinbase common.Address
|
||||||
|
MixHash common.Hash
|
||||||
|
Nonce types.BlockNonce
|
||||||
|
Number *big.Int
|
||||||
|
Hash common.Hash
|
||||||
|
ParentHash common.Hash
|
||||||
|
ReceiptTrie common.Hash
|
||||||
|
StateRoot common.Hash
|
||||||
|
TransactionsTrie common.Hash
|
||||||
|
UncleHash common.Hash
|
||||||
|
ExtraData []byte
|
||||||
|
Difficulty *big.Int
|
||||||
|
GasLimit *big.Int
|
||||||
|
GasUsed *big.Int
|
||||||
|
Timestamp *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type btHeaderMarshaling struct {
|
||||||
|
ExtraData hexutil.Bytes
|
||||||
|
Number *math.HexOrDecimal256
|
||||||
|
Difficulty *math.HexOrDecimal256
|
||||||
|
GasLimit *math.HexOrDecimal256
|
||||||
|
GasUsed *math.HexOrDecimal256
|
||||||
|
Timestamp *math.HexOrDecimal256
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *BlockTest) Run() error {
|
||||||
|
config, ok := Forks[t.json.Network]
|
||||||
|
if !ok {
|
||||||
|
return UnsupportedForkError{t.json.Network}
|
||||||
|
}
|
||||||
|
|
||||||
|
// import pre accounts & construct test genesis block & state root
|
||||||
|
db, _ := ethdb.NewMemDatabase()
|
||||||
|
gblock, err := t.genesis(config).Commit(db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if gblock.Hash() != t.json.Genesis.Hash {
|
||||||
|
return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x\n", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
|
||||||
|
}
|
||||||
|
if gblock.Root() != t.json.Genesis.StateRoot {
|
||||||
|
return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
|
||||||
|
}
|
||||||
|
|
||||||
|
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), vm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer chain.Stop()
|
||||||
|
|
||||||
|
validBlocks, err := t.insertBlocks(chain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmlast := chain.LastBlockHash()
|
||||||
|
if common.Hash(t.json.BestBlock) != cmlast {
|
||||||
|
return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
|
||||||
|
}
|
||||||
|
newDB, err := chain.State()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = t.validatePostState(newDB); err != nil {
|
||||||
|
return fmt.Errorf("post state validation failed: %v", err)
|
||||||
|
}
|
||||||
|
return t.validateImportedHeaders(chain, validBlocks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||||
|
return &core.Genesis{
|
||||||
|
Config: config,
|
||||||
|
Nonce: t.json.Genesis.Nonce.Uint64(),
|
||||||
|
Timestamp: t.json.Genesis.Timestamp.Uint64(),
|
||||||
|
ParentHash: t.json.Genesis.ParentHash,
|
||||||
|
ExtraData: t.json.Genesis.ExtraData,
|
||||||
|
GasLimit: t.json.Genesis.GasLimit.Uint64(),
|
||||||
|
GasUsed: t.json.Genesis.GasUsed.Uint64(),
|
||||||
|
Difficulty: t.json.Genesis.Difficulty,
|
||||||
|
Mixhash: t.json.Genesis.MixHash,
|
||||||
|
Coinbase: t.json.Genesis.Coinbase,
|
||||||
|
Alloc: t.json.Pre,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
|
||||||
|
|
||||||
|
Whether a block is valid or not is a bit subtle, it's defined by presence of
|
||||||
|
blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
|
||||||
|
invalid and we must verify that we do not accept it.
|
||||||
|
|
||||||
|
Since some tests mix valid and invalid blocks we need to check this for every block.
|
||||||
|
|
||||||
|
If a block is invalid it does not necessarily fail the test, if it's invalidness is
|
||||||
|
expected we are expected to ignore it and continue processing and then validate the
|
||||||
|
post state.
|
||||||
|
*/
|
||||||
|
func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
|
||||||
|
validBlocks := make([]btBlock, 0)
|
||||||
|
// insert the test blocks, which will execute all transactions
|
||||||
|
for _, b := range t.json.Blocks {
|
||||||
|
cb, err := b.decode()
|
||||||
|
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 RLP decoding failed when expected to succeed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// RLP decoding worked, try to insert into chain:
|
||||||
|
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 #%v insertion into chain failed: %v", blocks[i].Number(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b.BlockHeader == nil {
|
||||||
|
return nil, fmt.Errorf("Block insertion should have failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate RLP decoding by checking all values against test file JSON
|
||||||
|
if err = validateHeader(b.BlockHeader, cb.Header()); err != nil {
|
||||||
|
return nil, fmt.Errorf("Deserialised block header validation failed: %v", err)
|
||||||
|
}
|
||||||
|
validBlocks = append(validBlocks, b)
|
||||||
|
}
|
||||||
|
return validBlocks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateHeader(h *btHeader, h2 *types.Header) error {
|
||||||
|
if h.Bloom != h2.Bloom {
|
||||||
|
return fmt.Errorf("Bloom: want: %x have: %x", h.Bloom, h2.Bloom)
|
||||||
|
}
|
||||||
|
if h.Coinbase != h2.Coinbase {
|
||||||
|
return fmt.Errorf("Coinbase: want: %x have: %x", h.Coinbase, h2.Coinbase)
|
||||||
|
}
|
||||||
|
if h.MixHash != h2.MixDigest {
|
||||||
|
return fmt.Errorf("MixHash: want: %x have: %x", h.MixHash, h2.MixDigest)
|
||||||
|
}
|
||||||
|
if h.Nonce != h2.Nonce {
|
||||||
|
return fmt.Errorf("Nonce: want: %x have: %x", h.Nonce, h2.Nonce)
|
||||||
|
}
|
||||||
|
if h.Number.Cmp(h2.Number) != 0 {
|
||||||
|
return fmt.Errorf("Number: want: %v have: %v", h.Number, h2.Number)
|
||||||
|
}
|
||||||
|
if h.ParentHash != h2.ParentHash {
|
||||||
|
return fmt.Errorf("Parent hash: want: %x have: %x", h.ParentHash, h2.ParentHash)
|
||||||
|
}
|
||||||
|
if h.ReceiptTrie != h2.ReceiptHash {
|
||||||
|
return fmt.Errorf("Receipt hash: want: %x have: %x", h.ReceiptTrie, h2.ReceiptHash)
|
||||||
|
}
|
||||||
|
if h.TransactionsTrie != h2.TxHash {
|
||||||
|
return fmt.Errorf("Tx hash: want: %x have: %x", h.TransactionsTrie, h2.TxHash)
|
||||||
|
}
|
||||||
|
if h.StateRoot != h2.Root {
|
||||||
|
return fmt.Errorf("State hash: want: %x have: %x", h.StateRoot, h2.Root)
|
||||||
|
}
|
||||||
|
if h.UncleHash != h2.UncleHash {
|
||||||
|
return fmt.Errorf("Uncle hash: want: %x have: %x", h.UncleHash, h2.UncleHash)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(h.ExtraData, h2.Extra) {
|
||||||
|
return fmt.Errorf("Extra data: want: %x have: %x", h.ExtraData, h2.Extra)
|
||||||
|
}
|
||||||
|
if h.Difficulty.Cmp(h2.Difficulty) != 0 {
|
||||||
|
return fmt.Errorf("Difficulty: want: %v have: %v", h.Difficulty, h2.Difficulty)
|
||||||
|
}
|
||||||
|
if h.GasLimit.Cmp(h2.GasLimit) != 0 {
|
||||||
|
return fmt.Errorf("GasLimit: want: %v have: %v", h.GasLimit, h2.GasLimit)
|
||||||
|
}
|
||||||
|
if h.GasUsed.Cmp(h2.GasUsed) != 0 {
|
||||||
|
return fmt.Errorf("GasUsed: want: %v have: %v", h.GasUsed, h2.GasUsed)
|
||||||
|
}
|
||||||
|
if h.Timestamp.Cmp(h2.Time) != 0 {
|
||||||
|
return fmt.Errorf("Timestamp: want: %v have: %v", h.Timestamp, h2.Time)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
|
||||||
|
// validate post state accounts in test file against what we have in state db
|
||||||
|
for addr, acct := range t.json.Post {
|
||||||
|
// address is indirectly verified by the other fields, as it's the db key
|
||||||
|
code2 := statedb.GetCode(addr)
|
||||||
|
balance2 := statedb.GetBalance(addr)
|
||||||
|
nonce2 := statedb.GetNonce(addr)
|
||||||
|
if !bytes.Equal(code2, acct.Code) {
|
||||||
|
return fmt.Errorf("account code mismatch for addr: %s want: %v have: %s", addr, acct.Code, hex.EncodeToString(code2))
|
||||||
|
}
|
||||||
|
if balance2.Cmp(acct.Balance) != 0 {
|
||||||
|
return fmt.Errorf("account balance mismatch for addr: %s, want: %d, have: %d", addr, acct.Balance, balance2)
|
||||||
|
}
|
||||||
|
if nonce2 != acct.Nonce {
|
||||||
|
return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addr, acct.Nonce, nonce2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []btBlock) error {
|
||||||
|
// to get constant lookup when verifying block headers by hash (some tests have many blocks)
|
||||||
|
bmap := make(map[common.Hash]btBlock, len(t.json.Blocks))
|
||||||
|
for _, b := range validBlocks {
|
||||||
|
bmap[b.BlockHeader.Hash] = b
|
||||||
|
}
|
||||||
|
// iterate over blocks backwards from HEAD and validate imported
|
||||||
|
// headers vs test file. some tests have reorgs, and we import
|
||||||
|
// block-by-block, so we can only validate imported headers after
|
||||||
|
// all blocks have been processed by BlockChain, as they may not
|
||||||
|
// be part of the longest chain until last block is imported.
|
||||||
|
for b := cm.CurrentBlock(); b != nil && b.NumberU64() != 0; b = cm.GetBlockByHash(b.Header().ParentHash) {
|
||||||
|
if err := validateHeader(bmap[b.Hash()].BlockHeader, b.Header()); err != nil {
|
||||||
|
return fmt.Errorf("Imported block header validation failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bb *btBlock) decode() (*types.Block, error) {
|
||||||
|
data, err := hexutil.Decode(bb.Rlp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var b types.Block
|
||||||
|
err = rlp.DecodeBytes(data, &b)
|
||||||
|
return &b, err
|
||||||
|
}
|
70
vendor/github.com/ethereum/go-ethereum/tests/difficulty_test_util.go
generated
vendored
Normal file
70
vendor/github.com/ethereum/go-ethereum/tests/difficulty_test_util.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright 2017 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 tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate gencodec -type DifficultyTest -field-override difficultyTestMarshaling -out gen_difficultytest.go
|
||||||
|
|
||||||
|
type DifficultyTest struct {
|
||||||
|
ParentTimestamp *big.Int `json:"parentTimestamp"`
|
||||||
|
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
||||||
|
UncleHash common.Hash `json:"parentUncles"`
|
||||||
|
CurrentTimestamp *big.Int `json:"currentTimestamp"`
|
||||||
|
CurrentBlockNumber uint64 `json:"currentBlockNumber"`
|
||||||
|
CurrentDifficulty *big.Int `json:"currentDifficulty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type difficultyTestMarshaling struct {
|
||||||
|
ParentTimestamp *math.HexOrDecimal256
|
||||||
|
ParentDifficulty *math.HexOrDecimal256
|
||||||
|
CurrentTimestamp *math.HexOrDecimal256
|
||||||
|
CurrentDifficulty *math.HexOrDecimal256
|
||||||
|
UncleHash common.Hash
|
||||||
|
CurrentBlockNumber math.HexOrDecimal64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (test *DifficultyTest) Run(config *params.ChainConfig) error {
|
||||||
|
parentNumber := big.NewInt(int64(test.CurrentBlockNumber - 1))
|
||||||
|
parent := &types.Header{
|
||||||
|
Difficulty: test.ParentDifficulty,
|
||||||
|
Time: test.ParentTimestamp,
|
||||||
|
Number: parentNumber,
|
||||||
|
UncleHash: test.UncleHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := ethash.CalcDifficulty(config, test.CurrentTimestamp.Uint64(), parent)
|
||||||
|
exp := test.CurrentDifficulty
|
||||||
|
|
||||||
|
if actual.Cmp(exp) != 0 {
|
||||||
|
return fmt.Errorf("parent[time %v diff %v unclehash:%x] child[time %v number %v] diff %v != expected %v",
|
||||||
|
test.ParentTimestamp, test.ParentDifficulty, test.UncleHash,
|
||||||
|
test.CurrentTimestamp, test.CurrentBlockNumber, actual, exp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*btHeaderMarshaling)(nil)
|
||||||
|
|
||||||
|
func (b btHeader) MarshalJSON() ([]byte, error) {
|
||||||
|
type btHeader struct {
|
||||||
|
Bloom types.Bloom
|
||||||
|
Coinbase common.Address
|
||||||
|
MixHash common.Hash
|
||||||
|
Nonce types.BlockNonce
|
||||||
|
Number *math.HexOrDecimal256
|
||||||
|
Hash common.Hash
|
||||||
|
ParentHash common.Hash
|
||||||
|
ReceiptTrie common.Hash
|
||||||
|
StateRoot common.Hash
|
||||||
|
TransactionsTrie common.Hash
|
||||||
|
UncleHash common.Hash
|
||||||
|
ExtraData hexutil.Bytes
|
||||||
|
Difficulty *math.HexOrDecimal256
|
||||||
|
GasLimit *math.HexOrDecimal256
|
||||||
|
GasUsed *math.HexOrDecimal256
|
||||||
|
Timestamp *math.HexOrDecimal256
|
||||||
|
}
|
||||||
|
var enc btHeader
|
||||||
|
enc.Bloom = b.Bloom
|
||||||
|
enc.Coinbase = b.Coinbase
|
||||||
|
enc.MixHash = b.MixHash
|
||||||
|
enc.Nonce = b.Nonce
|
||||||
|
enc.Number = (*math.HexOrDecimal256)(b.Number)
|
||||||
|
enc.Hash = b.Hash
|
||||||
|
enc.ParentHash = b.ParentHash
|
||||||
|
enc.ReceiptTrie = b.ReceiptTrie
|
||||||
|
enc.StateRoot = b.StateRoot
|
||||||
|
enc.TransactionsTrie = b.TransactionsTrie
|
||||||
|
enc.UncleHash = b.UncleHash
|
||||||
|
enc.ExtraData = b.ExtraData
|
||||||
|
enc.Difficulty = (*math.HexOrDecimal256)(b.Difficulty)
|
||||||
|
enc.GasLimit = (*math.HexOrDecimal256)(b.GasLimit)
|
||||||
|
enc.GasUsed = (*math.HexOrDecimal256)(b.GasUsed)
|
||||||
|
enc.Timestamp = (*math.HexOrDecimal256)(b.Timestamp)
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *btHeader) UnmarshalJSON(input []byte) error {
|
||||||
|
type btHeader struct {
|
||||||
|
Bloom *types.Bloom
|
||||||
|
Coinbase *common.Address
|
||||||
|
MixHash *common.Hash
|
||||||
|
Nonce *types.BlockNonce
|
||||||
|
Number *math.HexOrDecimal256
|
||||||
|
Hash *common.Hash
|
||||||
|
ParentHash *common.Hash
|
||||||
|
ReceiptTrie *common.Hash
|
||||||
|
StateRoot *common.Hash
|
||||||
|
TransactionsTrie *common.Hash
|
||||||
|
UncleHash *common.Hash
|
||||||
|
ExtraData hexutil.Bytes
|
||||||
|
Difficulty *math.HexOrDecimal256
|
||||||
|
GasLimit *math.HexOrDecimal256
|
||||||
|
GasUsed *math.HexOrDecimal256
|
||||||
|
Timestamp *math.HexOrDecimal256
|
||||||
|
}
|
||||||
|
var dec btHeader
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.Bloom != nil {
|
||||||
|
b.Bloom = *dec.Bloom
|
||||||
|
}
|
||||||
|
if dec.Coinbase != nil {
|
||||||
|
b.Coinbase = *dec.Coinbase
|
||||||
|
}
|
||||||
|
if dec.MixHash != nil {
|
||||||
|
b.MixHash = *dec.MixHash
|
||||||
|
}
|
||||||
|
if dec.Nonce != nil {
|
||||||
|
b.Nonce = *dec.Nonce
|
||||||
|
}
|
||||||
|
if dec.Number != nil {
|
||||||
|
b.Number = (*big.Int)(dec.Number)
|
||||||
|
}
|
||||||
|
if dec.Hash != nil {
|
||||||
|
b.Hash = *dec.Hash
|
||||||
|
}
|
||||||
|
if dec.ParentHash != nil {
|
||||||
|
b.ParentHash = *dec.ParentHash
|
||||||
|
}
|
||||||
|
if dec.ReceiptTrie != nil {
|
||||||
|
b.ReceiptTrie = *dec.ReceiptTrie
|
||||||
|
}
|
||||||
|
if dec.StateRoot != nil {
|
||||||
|
b.StateRoot = *dec.StateRoot
|
||||||
|
}
|
||||||
|
if dec.TransactionsTrie != nil {
|
||||||
|
b.TransactionsTrie = *dec.TransactionsTrie
|
||||||
|
}
|
||||||
|
if dec.UncleHash != nil {
|
||||||
|
b.UncleHash = *dec.UncleHash
|
||||||
|
}
|
||||||
|
if dec.ExtraData != nil {
|
||||||
|
b.ExtraData = dec.ExtraData
|
||||||
|
}
|
||||||
|
if dec.Difficulty != nil {
|
||||||
|
b.Difficulty = (*big.Int)(dec.Difficulty)
|
||||||
|
}
|
||||||
|
if dec.GasLimit != nil {
|
||||||
|
b.GasLimit = (*big.Int)(dec.GasLimit)
|
||||||
|
}
|
||||||
|
if dec.GasUsed != nil {
|
||||||
|
b.GasUsed = (*big.Int)(dec.GasUsed)
|
||||||
|
}
|
||||||
|
if dec.Timestamp != nil {
|
||||||
|
b.Timestamp = (*big.Int)(dec.Timestamp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
66
vendor/github.com/ethereum/go-ethereum/tests/gen_difficultytest.go
generated
vendored
Normal file
66
vendor/github.com/ethereum/go-ethereum/tests/gen_difficultytest.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*difficultyTestMarshaling)(nil)
|
||||||
|
|
||||||
|
func (d DifficultyTest) MarshalJSON() ([]byte, error) {
|
||||||
|
type DifficultyTest struct {
|
||||||
|
ParentTimestamp *math.HexOrDecimal256 `json:"parentTimestamp"`
|
||||||
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
|
UncleHash common.Hash `json:"parentUncles"`
|
||||||
|
CurrentTimestamp *math.HexOrDecimal256 `json:"currentTimestamp"`
|
||||||
|
CurrentBlockNumber math.HexOrDecimal64 `json:"currentBlockNumber"`
|
||||||
|
CurrentDifficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
|
}
|
||||||
|
var enc DifficultyTest
|
||||||
|
enc.ParentTimestamp = (*math.HexOrDecimal256)(d.ParentTimestamp)
|
||||||
|
enc.ParentDifficulty = (*math.HexOrDecimal256)(d.ParentDifficulty)
|
||||||
|
enc.UncleHash = d.UncleHash
|
||||||
|
enc.CurrentTimestamp = (*math.HexOrDecimal256)(d.CurrentTimestamp)
|
||||||
|
enc.CurrentBlockNumber = math.HexOrDecimal64(d.CurrentBlockNumber)
|
||||||
|
enc.CurrentDifficulty = (*math.HexOrDecimal256)(d.CurrentDifficulty)
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DifficultyTest) UnmarshalJSON(input []byte) error {
|
||||||
|
type DifficultyTest struct {
|
||||||
|
ParentTimestamp *math.HexOrDecimal256 `json:"parentTimestamp"`
|
||||||
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
|
UncleHash *common.Hash `json:"parentUncles"`
|
||||||
|
CurrentTimestamp *math.HexOrDecimal256 `json:"currentTimestamp"`
|
||||||
|
CurrentBlockNumber *math.HexOrDecimal64 `json:"currentBlockNumber"`
|
||||||
|
CurrentDifficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
|
}
|
||||||
|
var dec DifficultyTest
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.ParentTimestamp != nil {
|
||||||
|
d.ParentTimestamp = (*big.Int)(dec.ParentTimestamp)
|
||||||
|
}
|
||||||
|
if dec.ParentDifficulty != nil {
|
||||||
|
d.ParentDifficulty = (*big.Int)(dec.ParentDifficulty)
|
||||||
|
}
|
||||||
|
if dec.UncleHash != nil {
|
||||||
|
d.UncleHash = *dec.UncleHash
|
||||||
|
}
|
||||||
|
if dec.CurrentTimestamp != nil {
|
||||||
|
d.CurrentTimestamp = (*big.Int)(dec.CurrentTimestamp)
|
||||||
|
}
|
||||||
|
if dec.CurrentBlockNumber != nil {
|
||||||
|
d.CurrentBlockNumber = uint64(*dec.CurrentBlockNumber)
|
||||||
|
}
|
||||||
|
if dec.CurrentDifficulty != nil {
|
||||||
|
d.CurrentDifficulty = (*big.Int)(dec.CurrentDifficulty)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*stEnvMarshaling)(nil)
|
||||||
|
|
||||||
|
func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
|
type stEnv struct {
|
||||||
|
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||||
|
GasLimit *math.HexOrDecimal256 `json:"currentGasLimit" gencodec:"required"`
|
||||||
|
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
|
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
|
}
|
||||||
|
var enc stEnv
|
||||||
|
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||||
|
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
|
||||||
|
enc.GasLimit = (*math.HexOrDecimal256)(s.GasLimit)
|
||||||
|
enc.Number = math.HexOrDecimal64(s.Number)
|
||||||
|
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
|
type stEnv struct {
|
||||||
|
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||||
|
GasLimit *math.HexOrDecimal256 `json:"currentGasLimit" gencodec:"required"`
|
||||||
|
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
|
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
|
}
|
||||||
|
var dec stEnv
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.Coinbase == nil {
|
||||||
|
return errors.New("missing required field 'currentCoinbase' for stEnv")
|
||||||
|
}
|
||||||
|
s.Coinbase = common.Address(*dec.Coinbase)
|
||||||
|
if dec.Difficulty == nil {
|
||||||
|
return errors.New("missing required field 'currentDifficulty' for stEnv")
|
||||||
|
}
|
||||||
|
s.Difficulty = (*big.Int)(dec.Difficulty)
|
||||||
|
if dec.GasLimit == nil {
|
||||||
|
return errors.New("missing required field 'currentGasLimit' for stEnv")
|
||||||
|
}
|
||||||
|
s.GasLimit = (*big.Int)(dec.GasLimit)
|
||||||
|
if dec.Number == nil {
|
||||||
|
return errors.New("missing required field 'currentNumber' for stEnv")
|
||||||
|
}
|
||||||
|
s.Number = uint64(*dec.Number)
|
||||||
|
if dec.Timestamp == nil {
|
||||||
|
return errors.New("missing required field 'currentTimestamp' for stEnv")
|
||||||
|
}
|
||||||
|
s.Timestamp = uint64(*dec.Timestamp)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*stTransactionMarshaling)(nil)
|
||||||
|
|
||||||
|
func (s stTransaction) MarshalJSON() ([]byte, error) {
|
||||||
|
type stTransaction struct {
|
||||||
|
GasPrice *math.HexOrDecimal256 `json:"gasPrice"`
|
||||||
|
Nonce math.HexOrDecimal64 `json:"nonce"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Data []string `json:"data"`
|
||||||
|
GasLimit []math.HexOrDecimal64 `json:"gasLimit"`
|
||||||
|
Value []string `json:"value"`
|
||||||
|
PrivateKey hexutil.Bytes `json:"secretKey"`
|
||||||
|
}
|
||||||
|
var enc stTransaction
|
||||||
|
enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice)
|
||||||
|
enc.Nonce = math.HexOrDecimal64(s.Nonce)
|
||||||
|
enc.To = s.To
|
||||||
|
enc.Data = s.Data
|
||||||
|
if s.GasLimit != nil {
|
||||||
|
enc.GasLimit = make([]math.HexOrDecimal64, len(s.GasLimit))
|
||||||
|
for k, v := range s.GasLimit {
|
||||||
|
enc.GasLimit[k] = math.HexOrDecimal64(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc.Value = s.Value
|
||||||
|
enc.PrivateKey = s.PrivateKey
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stTransaction) UnmarshalJSON(input []byte) error {
|
||||||
|
type stTransaction struct {
|
||||||
|
GasPrice *math.HexOrDecimal256 `json:"gasPrice"`
|
||||||
|
Nonce *math.HexOrDecimal64 `json:"nonce"`
|
||||||
|
To *string `json:"to"`
|
||||||
|
Data []string `json:"data"`
|
||||||
|
GasLimit []math.HexOrDecimal64 `json:"gasLimit"`
|
||||||
|
Value []string `json:"value"`
|
||||||
|
PrivateKey hexutil.Bytes `json:"secretKey"`
|
||||||
|
}
|
||||||
|
var dec stTransaction
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.GasPrice != nil {
|
||||||
|
s.GasPrice = (*big.Int)(dec.GasPrice)
|
||||||
|
}
|
||||||
|
if dec.Nonce != nil {
|
||||||
|
s.Nonce = uint64(*dec.Nonce)
|
||||||
|
}
|
||||||
|
if dec.To != nil {
|
||||||
|
s.To = *dec.To
|
||||||
|
}
|
||||||
|
if dec.Data != nil {
|
||||||
|
s.Data = dec.Data
|
||||||
|
}
|
||||||
|
if dec.GasLimit != nil {
|
||||||
|
s.GasLimit = make([]uint64, len(dec.GasLimit))
|
||||||
|
for k, v := range dec.GasLimit {
|
||||||
|
s.GasLimit[k] = uint64(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dec.Value != nil {
|
||||||
|
s.Value = dec.Value
|
||||||
|
}
|
||||||
|
if dec.PrivateKey != nil {
|
||||||
|
s.PrivateKey = dec.PrivateKey
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*ttTransactionMarshaling)(nil)
|
||||||
|
|
||||||
|
func (t ttTransaction) MarshalJSON() ([]byte, error) {
|
||||||
|
type ttTransaction struct {
|
||||||
|
Data hexutil.Bytes `gencodec:"required"`
|
||||||
|
GasLimit *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
GasPrice *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
Nonce math.HexOrDecimal64 `gencodec:"required"`
|
||||||
|
Value *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
R *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
S *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
V *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
To common.Address `gencodec:"required"`
|
||||||
|
}
|
||||||
|
var enc ttTransaction
|
||||||
|
enc.Data = t.Data
|
||||||
|
enc.GasLimit = (*math.HexOrDecimal256)(t.GasLimit)
|
||||||
|
enc.GasPrice = (*math.HexOrDecimal256)(t.GasPrice)
|
||||||
|
enc.Nonce = math.HexOrDecimal64(t.Nonce)
|
||||||
|
enc.Value = (*math.HexOrDecimal256)(t.Value)
|
||||||
|
enc.R = (*math.HexOrDecimal256)(t.R)
|
||||||
|
enc.S = (*math.HexOrDecimal256)(t.S)
|
||||||
|
enc.V = (*math.HexOrDecimal256)(t.V)
|
||||||
|
enc.To = t.To
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ttTransaction) UnmarshalJSON(input []byte) error {
|
||||||
|
type ttTransaction struct {
|
||||||
|
Data hexutil.Bytes `gencodec:"required"`
|
||||||
|
GasLimit *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
GasPrice *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
Nonce *math.HexOrDecimal64 `gencodec:"required"`
|
||||||
|
Value *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
R *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
S *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
V *math.HexOrDecimal256 `gencodec:"required"`
|
||||||
|
To *common.Address `gencodec:"required"`
|
||||||
|
}
|
||||||
|
var dec ttTransaction
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.Data == nil {
|
||||||
|
return errors.New("missing required field 'data' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.Data = dec.Data
|
||||||
|
if dec.GasLimit == nil {
|
||||||
|
return errors.New("missing required field 'gasLimit' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.GasLimit = (*big.Int)(dec.GasLimit)
|
||||||
|
if dec.GasPrice == nil {
|
||||||
|
return errors.New("missing required field 'gasPrice' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.GasPrice = (*big.Int)(dec.GasPrice)
|
||||||
|
if dec.Nonce == nil {
|
||||||
|
return errors.New("missing required field 'nonce' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.Nonce = uint64(*dec.Nonce)
|
||||||
|
if dec.Value == nil {
|
||||||
|
return errors.New("missing required field 'value' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.Value = (*big.Int)(dec.Value)
|
||||||
|
if dec.R == nil {
|
||||||
|
return errors.New("missing required field 'r' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.R = (*big.Int)(dec.R)
|
||||||
|
if dec.S == nil {
|
||||||
|
return errors.New("missing required field 's' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.S = (*big.Int)(dec.S)
|
||||||
|
if dec.V == nil {
|
||||||
|
return errors.New("missing required field 'v' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.V = (*big.Int)(dec.V)
|
||||||
|
if dec.To == nil {
|
||||||
|
return errors.New("missing required field 'to' for ttTransaction")
|
||||||
|
}
|
||||||
|
t.To = *dec.To
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*vmExecMarshaling)(nil)
|
||||||
|
|
||||||
|
func (v vmExec) MarshalJSON() ([]byte, error) {
|
||||||
|
type vmExec struct {
|
||||||
|
Address common.UnprefixedAddress `json:"address" gencodec:"required"`
|
||||||
|
Caller common.UnprefixedAddress `json:"caller" gencodec:"required"`
|
||||||
|
Origin common.UnprefixedAddress `json:"origin" gencodec:"required"`
|
||||||
|
Code hexutil.Bytes `json:"code" gencodec:"required"`
|
||||||
|
Data hexutil.Bytes `json:"data" gencodec:"required"`
|
||||||
|
Value *math.HexOrDecimal256 `json:"value" gencodec:"required"`
|
||||||
|
GasLimit math.HexOrDecimal64 `json:"gas" gencodec:"required"`
|
||||||
|
GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"`
|
||||||
|
}
|
||||||
|
var enc vmExec
|
||||||
|
enc.Address = common.UnprefixedAddress(v.Address)
|
||||||
|
enc.Caller = common.UnprefixedAddress(v.Caller)
|
||||||
|
enc.Origin = common.UnprefixedAddress(v.Origin)
|
||||||
|
enc.Code = v.Code
|
||||||
|
enc.Data = v.Data
|
||||||
|
enc.Value = (*math.HexOrDecimal256)(v.Value)
|
||||||
|
enc.GasLimit = math.HexOrDecimal64(v.GasLimit)
|
||||||
|
enc.GasPrice = (*math.HexOrDecimal256)(v.GasPrice)
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *vmExec) UnmarshalJSON(input []byte) error {
|
||||||
|
type vmExec struct {
|
||||||
|
Address *common.UnprefixedAddress `json:"address" gencodec:"required"`
|
||||||
|
Caller *common.UnprefixedAddress `json:"caller" gencodec:"required"`
|
||||||
|
Origin *common.UnprefixedAddress `json:"origin" gencodec:"required"`
|
||||||
|
Code hexutil.Bytes `json:"code" gencodec:"required"`
|
||||||
|
Data hexutil.Bytes `json:"data" gencodec:"required"`
|
||||||
|
Value *math.HexOrDecimal256 `json:"value" gencodec:"required"`
|
||||||
|
GasLimit *math.HexOrDecimal64 `json:"gas" gencodec:"required"`
|
||||||
|
GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"`
|
||||||
|
}
|
||||||
|
var dec vmExec
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.Address == nil {
|
||||||
|
return errors.New("missing required field 'address' for vmExec")
|
||||||
|
}
|
||||||
|
v.Address = common.Address(*dec.Address)
|
||||||
|
if dec.Caller == nil {
|
||||||
|
return errors.New("missing required field 'caller' for vmExec")
|
||||||
|
}
|
||||||
|
v.Caller = common.Address(*dec.Caller)
|
||||||
|
if dec.Origin == nil {
|
||||||
|
return errors.New("missing required field 'origin' for vmExec")
|
||||||
|
}
|
||||||
|
v.Origin = common.Address(*dec.Origin)
|
||||||
|
if dec.Code == nil {
|
||||||
|
return errors.New("missing required field 'code' for vmExec")
|
||||||
|
}
|
||||||
|
v.Code = dec.Code
|
||||||
|
if dec.Data == nil {
|
||||||
|
return errors.New("missing required field 'data' for vmExec")
|
||||||
|
}
|
||||||
|
v.Data = dec.Data
|
||||||
|
if dec.Value == nil {
|
||||||
|
return errors.New("missing required field 'value' for vmExec")
|
||||||
|
}
|
||||||
|
v.Value = (*big.Int)(dec.Value)
|
||||||
|
if dec.GasLimit == nil {
|
||||||
|
return errors.New("missing required field 'gas' for vmExec")
|
||||||
|
}
|
||||||
|
v.GasLimit = uint64(*dec.GasLimit)
|
||||||
|
if dec.GasPrice == nil {
|
||||||
|
return errors.New("missing required field 'gasPrice' for vmExec")
|
||||||
|
}
|
||||||
|
v.GasPrice = (*big.Int)(dec.GasPrice)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright 2017 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 tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This table defines supported forks and their chain config.
|
||||||
|
var Forks = map[string]*params.ChainConfig{
|
||||||
|
"Frontier": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
},
|
||||||
|
"Homestead": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
},
|
||||||
|
"EIP150": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
},
|
||||||
|
"EIP158": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
},
|
||||||
|
"Byzantium": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
DAOForkBlock: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
},
|
||||||
|
"FrontierToHomesteadAt5": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(5),
|
||||||
|
},
|
||||||
|
"HomesteadToEIP150At5": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(5),
|
||||||
|
},
|
||||||
|
"HomesteadToDaoAt5": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
DAOForkBlock: big.NewInt(5),
|
||||||
|
DAOForkSupport: true,
|
||||||
|
},
|
||||||
|
"EIP158ToByzantiumAt5": {
|
||||||
|
ChainId: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(5),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsupportedForkError is returned when a test requests a fork that isn't implemented.
|
||||||
|
type UnsupportedForkError struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e UnsupportedForkError) Error() string {
|
||||||
|
return fmt.Sprintf("unsupported fork %q", e.Name)
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
// 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 tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RLPTest is the JSON structure of a single RLP test.
|
||||||
|
type RLPTest struct {
|
||||||
|
// If the value of In is "INVALID" or "VALID", the test
|
||||||
|
// checks whether Out can be decoded into a value of
|
||||||
|
// type interface{}.
|
||||||
|
//
|
||||||
|
// For other JSON values, In is treated as a driver for
|
||||||
|
// calls to rlp.Stream. The test also verifies that encoding
|
||||||
|
// In produces the bytes in Out.
|
||||||
|
In interface{}
|
||||||
|
|
||||||
|
// Out is a hex-encoded RLP value.
|
||||||
|
Out string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the test.
|
||||||
|
func (t *RLPTest) Run() error {
|
||||||
|
outb, err := hex.DecodeString(t.Out)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid hex in Out")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle simple decoding tests with no actual In value.
|
||||||
|
if t.In == "VALID" || t.In == "INVALID" {
|
||||||
|
return checkDecodeInterface(outb, t.In == "VALID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether encoding the value produces the same bytes.
|
||||||
|
in := translateJSON(t.In)
|
||||||
|
b, err := rlp.EncodeToBytes(in)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("encode failed: %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b, outb) {
|
||||||
|
return fmt.Errorf("encode produced %x, want %x", b, outb)
|
||||||
|
}
|
||||||
|
// Test stream decoding.
|
||||||
|
s := rlp.NewStream(bytes.NewReader(outb), 0)
|
||||||
|
return checkDecodeFromJSON(s, in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkDecodeInterface(b []byte, isValid bool) error {
|
||||||
|
err := rlp.DecodeBytes(b, new(interface{}))
|
||||||
|
switch {
|
||||||
|
case isValid && err != nil:
|
||||||
|
return fmt.Errorf("decoding failed: %v", err)
|
||||||
|
case !isValid && err == nil:
|
||||||
|
return fmt.Errorf("decoding of invalid value succeeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// translateJSON makes test json values encodable with RLP.
|
||||||
|
func translateJSON(v interface{}) interface{} {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case float64:
|
||||||
|
return uint64(v)
|
||||||
|
case string:
|
||||||
|
if len(v) > 0 && v[0] == '#' { // # starts a faux big int.
|
||||||
|
big, ok := new(big.Int).SetString(v[1:], 10)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("bad test: bad big int: %q", v))
|
||||||
|
}
|
||||||
|
return big
|
||||||
|
}
|
||||||
|
return []byte(v)
|
||||||
|
case []interface{}:
|
||||||
|
new := make([]interface{}, len(v))
|
||||||
|
for i := range v {
|
||||||
|
new[i] = translateJSON(v[i])
|
||||||
|
}
|
||||||
|
return new
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("can't handle %T", v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkDecodeFromJSON decodes from s guided by exp. exp drives the
|
||||||
|
// Stream by invoking decoding operations (Uint, Big, List, ...) based
|
||||||
|
// on the type of each value. The value decoded from the RLP stream
|
||||||
|
// must match the JSON value.
|
||||||
|
func checkDecodeFromJSON(s *rlp.Stream, exp interface{}) error {
|
||||||
|
switch exp := exp.(type) {
|
||||||
|
case uint64:
|
||||||
|
i, err := s.Uint()
|
||||||
|
if err != nil {
|
||||||
|
return addStack("Uint", exp, err)
|
||||||
|
}
|
||||||
|
if i != exp {
|
||||||
|
return addStack("Uint", exp, fmt.Errorf("result mismatch: got %d", i))
|
||||||
|
}
|
||||||
|
case *big.Int:
|
||||||
|
big := new(big.Int)
|
||||||
|
if err := s.Decode(&big); err != nil {
|
||||||
|
return addStack("Big", exp, err)
|
||||||
|
}
|
||||||
|
if big.Cmp(exp) != 0 {
|
||||||
|
return addStack("Big", exp, fmt.Errorf("result mismatch: got %d", big))
|
||||||
|
}
|
||||||
|
case []byte:
|
||||||
|
b, err := s.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
return addStack("Bytes", exp, err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b, exp) {
|
||||||
|
return addStack("Bytes", exp, fmt.Errorf("result mismatch: got %x", b))
|
||||||
|
}
|
||||||
|
case []interface{}:
|
||||||
|
if _, err := s.List(); err != nil {
|
||||||
|
return addStack("List", exp, err)
|
||||||
|
}
|
||||||
|
for i, v := range exp {
|
||||||
|
if err := checkDecodeFromJSON(s, v); err != nil {
|
||||||
|
return addStack(fmt.Sprintf("[%d]", i), exp, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := s.ListEnd(); err != nil {
|
||||||
|
return addStack("ListEnd", exp, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unhandled type: %T", exp))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addStack(op string, val interface{}, err error) error {
|
||||||
|
lines := strings.Split(err.Error(), "\n")
|
||||||
|
lines = append(lines, fmt.Sprintf("\t%s: %v", op, val))
|
||||||
|
return errors.New(strings.Join(lines, "\n"))
|
||||||
|
}
|
|
@ -0,0 +1,245 @@
|
||||||
|
// Copyright 2017 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 tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StateTest checks transaction processing without block context.
|
||||||
|
// See https://github.com/ethereum/EIPs/issues/176 for the test format specification.
|
||||||
|
type StateTest struct {
|
||||||
|
json stJSON
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateSubtest selects a specific configuration of a General State Test.
|
||||||
|
type StateSubtest struct {
|
||||||
|
Fork string
|
||||||
|
Index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *StateTest) UnmarshalJSON(in []byte) error {
|
||||||
|
return json.Unmarshal(in, &t.json)
|
||||||
|
}
|
||||||
|
|
||||||
|
type stJSON struct {
|
||||||
|
Env stEnv `json:"env"`
|
||||||
|
Pre core.GenesisAlloc `json:"pre"`
|
||||||
|
Tx stTransaction `json:"transaction"`
|
||||||
|
Out hexutil.Bytes `json:"out"`
|
||||||
|
Post map[string][]stPostState `json:"post"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type stPostState struct {
|
||||||
|
Root common.UnprefixedHash `json:"hash"`
|
||||||
|
Logs common.UnprefixedHash `json:"logs"`
|
||||||
|
Indexes struct {
|
||||||
|
Data int `json:"data"`
|
||||||
|
Gas int `json:"gas"`
|
||||||
|
Value int `json:"value"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
|
||||||
|
|
||||||
|
type stEnv struct {
|
||||||
|
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
||||||
|
Difficulty *big.Int `json:"currentDifficulty" gencodec:"required"`
|
||||||
|
GasLimit *big.Int `json:"currentGasLimit" gencodec:"required"`
|
||||||
|
Number uint64 `json:"currentNumber" gencodec:"required"`
|
||||||
|
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type stEnvMarshaling struct {
|
||||||
|
Coinbase common.UnprefixedAddress
|
||||||
|
Difficulty *math.HexOrDecimal256
|
||||||
|
GasLimit *math.HexOrDecimal256
|
||||||
|
Number math.HexOrDecimal64
|
||||||
|
Timestamp math.HexOrDecimal64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
|
||||||
|
|
||||||
|
type stTransaction struct {
|
||||||
|
GasPrice *big.Int `json:"gasPrice"`
|
||||||
|
Nonce uint64 `json:"nonce"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Data []string `json:"data"`
|
||||||
|
GasLimit []uint64 `json:"gasLimit"`
|
||||||
|
Value []string `json:"value"`
|
||||||
|
PrivateKey []byte `json:"secretKey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type stTransactionMarshaling struct {
|
||||||
|
GasPrice *math.HexOrDecimal256
|
||||||
|
Nonce math.HexOrDecimal64
|
||||||
|
GasLimit []math.HexOrDecimal64
|
||||||
|
PrivateKey hexutil.Bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtests returns all valid subtests of the test.
|
||||||
|
func (t *StateTest) Subtests() []StateSubtest {
|
||||||
|
var sub []StateSubtest
|
||||||
|
for fork, pss := range t.json.Post {
|
||||||
|
for i := range pss {
|
||||||
|
sub = append(sub, StateSubtest{fork, i})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sub
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes a specific subtest.
|
||||||
|
func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateDB, error) {
|
||||||
|
config, ok := Forks[subtest.Fork]
|
||||||
|
if !ok {
|
||||||
|
return nil, UnsupportedForkError{subtest.Fork}
|
||||||
|
}
|
||||||
|
block, _ := t.genesis(config).ToBlock()
|
||||||
|
db, _ := ethdb.NewMemDatabase()
|
||||||
|
statedb := makePreState(db, t.json.Pre)
|
||||||
|
|
||||||
|
post := t.json.Post[subtest.Fork][subtest.Index]
|
||||||
|
msg, err := t.json.Tx.toMessage(post)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
context := core.NewEVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase)
|
||||||
|
context.GetHash = vmTestBlockHash
|
||||||
|
evm := vm.NewEVM(context, statedb, config, vmconfig)
|
||||||
|
|
||||||
|
gaspool := new(core.GasPool)
|
||||||
|
gaspool.AddGas(block.GasLimit())
|
||||||
|
snapshot := statedb.Snapshot()
|
||||||
|
if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
|
||||||
|
statedb.RevertToSnapshot(snapshot)
|
||||||
|
}
|
||||||
|
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
|
||||||
|
return statedb, fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
|
||||||
|
}
|
||||||
|
root, _ := statedb.CommitTo(db, config.IsEIP158(block.Number()))
|
||||||
|
if root != common.Hash(post.Root) {
|
||||||
|
return statedb, fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
|
||||||
|
}
|
||||||
|
return statedb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
|
||||||
|
return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
|
||||||
|
sdb := state.NewDatabase(db)
|
||||||
|
statedb, _ := state.New(common.Hash{}, sdb)
|
||||||
|
for addr, a := range accounts {
|
||||||
|
statedb.SetCode(addr, a.Code)
|
||||||
|
statedb.SetNonce(addr, a.Nonce)
|
||||||
|
statedb.SetBalance(addr, a.Balance)
|
||||||
|
for k, v := range a.Storage {
|
||||||
|
statedb.SetState(addr, k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Commit and re-open to start with a clean state.
|
||||||
|
root, _ := statedb.CommitTo(db, false)
|
||||||
|
statedb, _ = state.New(root, sdb)
|
||||||
|
return statedb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||||
|
return &core.Genesis{
|
||||||
|
Config: config,
|
||||||
|
Coinbase: t.json.Env.Coinbase,
|
||||||
|
Difficulty: t.json.Env.Difficulty,
|
||||||
|
GasLimit: t.json.Env.GasLimit.Uint64(),
|
||||||
|
Number: t.json.Env.Number,
|
||||||
|
Timestamp: t.json.Env.Timestamp,
|
||||||
|
Alloc: t.json.Pre,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) {
|
||||||
|
// Derive sender from private key if present.
|
||||||
|
var from common.Address
|
||||||
|
if len(tx.PrivateKey) > 0 {
|
||||||
|
key, err := crypto.ToECDSA(tx.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid private key: %v", err)
|
||||||
|
}
|
||||||
|
from = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
}
|
||||||
|
// Parse recipient if present.
|
||||||
|
var to *common.Address
|
||||||
|
if tx.To != "" {
|
||||||
|
to = new(common.Address)
|
||||||
|
if err := to.UnmarshalText([]byte(tx.To)); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid to address: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get values specific to this post state.
|
||||||
|
if ps.Indexes.Data > len(tx.Data) {
|
||||||
|
return nil, fmt.Errorf("tx data index %d out of bounds", ps.Indexes.Data)
|
||||||
|
}
|
||||||
|
if ps.Indexes.Value > len(tx.Value) {
|
||||||
|
return nil, fmt.Errorf("tx value index %d out of bounds", ps.Indexes.Value)
|
||||||
|
}
|
||||||
|
if ps.Indexes.Gas > len(tx.GasLimit) {
|
||||||
|
return nil, fmt.Errorf("tx gas limit index %d out of bounds", ps.Indexes.Gas)
|
||||||
|
}
|
||||||
|
dataHex := tx.Data[ps.Indexes.Data]
|
||||||
|
valueHex := tx.Value[ps.Indexes.Value]
|
||||||
|
gasLimit := tx.GasLimit[ps.Indexes.Gas]
|
||||||
|
// Value, Data hex encoding is messy: https://github.com/ethereum/tests/issues/203
|
||||||
|
value := new(big.Int)
|
||||||
|
if valueHex != "0x" {
|
||||||
|
v, ok := math.ParseBig256(valueHex)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid tx value %q", valueHex)
|
||||||
|
}
|
||||||
|
value = v
|
||||||
|
}
|
||||||
|
data, err := hex.DecodeString(strings.TrimPrefix(dataHex, "0x"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid tx data %q", dataHex)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := types.NewMessage(from, to, tx.Nonce, value, new(big.Int).SetUint64(gasLimit), tx.GasPrice, data, true)
|
||||||
|
return msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rlpHash(x interface{}) (h common.Hash) {
|
||||||
|
hw := sha3.NewKeccak256()
|
||||||
|
rlp.Encode(hw, x)
|
||||||
|
hw.Sum(h[:0])
|
||||||
|
return h
|
||||||
|
}
|
133
vendor/github.com/ethereum/go-ethereum/tests/transaction_test_util.go
generated
vendored
Normal file
133
vendor/github.com/ethereum/go-ethereum/tests/transaction_test_util.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
// 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 tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TransactionTest checks RLP decoding and sender derivation of transactions.
|
||||||
|
type TransactionTest struct {
|
||||||
|
json ttJSON
|
||||||
|
}
|
||||||
|
|
||||||
|
type ttJSON struct {
|
||||||
|
BlockNumber math.HexOrDecimal64 `json:"blockNumber"`
|
||||||
|
RLP hexutil.Bytes `json:"rlp"`
|
||||||
|
Sender hexutil.Bytes `json:"sender"`
|
||||||
|
Transaction *ttTransaction `json:"transaction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate gencodec -type ttTransaction -field-override ttTransactionMarshaling -out gen_tttransaction.go
|
||||||
|
|
||||||
|
type ttTransaction struct {
|
||||||
|
Data []byte `gencodec:"required"`
|
||||||
|
GasLimit *big.Int `gencodec:"required"`
|
||||||
|
GasPrice *big.Int `gencodec:"required"`
|
||||||
|
Nonce uint64 `gencodec:"required"`
|
||||||
|
Value *big.Int `gencodec:"required"`
|
||||||
|
R *big.Int `gencodec:"required"`
|
||||||
|
S *big.Int `gencodec:"required"`
|
||||||
|
V *big.Int `gencodec:"required"`
|
||||||
|
To common.Address `gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ttTransactionMarshaling struct {
|
||||||
|
Data hexutil.Bytes
|
||||||
|
GasLimit *math.HexOrDecimal256
|
||||||
|
GasPrice *math.HexOrDecimal256
|
||||||
|
Nonce math.HexOrDecimal64
|
||||||
|
Value *math.HexOrDecimal256
|
||||||
|
R *math.HexOrDecimal256
|
||||||
|
S *math.HexOrDecimal256
|
||||||
|
V *math.HexOrDecimal256
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tt *TransactionTest) Run(config *params.ChainConfig) error {
|
||||||
|
tx := new(types.Transaction)
|
||||||
|
if err := rlp.DecodeBytes(tt.json.RLP, tx); err != nil {
|
||||||
|
if tt.json.Transaction == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("RLP decoding failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check sender derivation.
|
||||||
|
signer := types.MakeSigner(config, new(big.Int).SetUint64(uint64(tt.json.BlockNumber)))
|
||||||
|
sender, err := types.Sender(signer, tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if sender != common.BytesToAddress(tt.json.Sender) {
|
||||||
|
return fmt.Errorf("Sender mismatch: got %x, want %x", sender, tt.json.Sender)
|
||||||
|
}
|
||||||
|
// Check decoded fields.
|
||||||
|
err = tt.json.Transaction.verify(signer, tx)
|
||||||
|
if tt.json.Sender == nil && err == nil {
|
||||||
|
return errors.New("field validations succeeded but should fail")
|
||||||
|
}
|
||||||
|
if tt.json.Sender != nil && err != nil {
|
||||||
|
return fmt.Errorf("field validations failed after RLP decoding: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tt *ttTransaction) verify(signer types.Signer, tx *types.Transaction) error {
|
||||||
|
if !bytes.Equal(tx.Data(), tt.Data) {
|
||||||
|
return fmt.Errorf("Tx input data mismatch: got %x want %x", tx.Data(), tt.Data)
|
||||||
|
}
|
||||||
|
if tx.Gas().Cmp(tt.GasLimit) != 0 {
|
||||||
|
return fmt.Errorf("GasLimit mismatch: got %v, want %v", tx.Gas(), tt.GasLimit)
|
||||||
|
}
|
||||||
|
if tx.GasPrice().Cmp(tt.GasPrice) != 0 {
|
||||||
|
return fmt.Errorf("GasPrice mismatch: got %v, want %v", tx.GasPrice(), tt.GasPrice)
|
||||||
|
}
|
||||||
|
if tx.Nonce() != tt.Nonce {
|
||||||
|
return fmt.Errorf("Nonce mismatch: got %v, want %v", tx.Nonce(), tt.Nonce)
|
||||||
|
}
|
||||||
|
v, r, s := tx.RawSignatureValues()
|
||||||
|
if r.Cmp(tt.R) != 0 {
|
||||||
|
return fmt.Errorf("R mismatch: got %v, want %v", r, tt.R)
|
||||||
|
}
|
||||||
|
if s.Cmp(tt.S) != 0 {
|
||||||
|
return fmt.Errorf("S mismatch: got %v, want %v", s, tt.S)
|
||||||
|
}
|
||||||
|
if v.Cmp(tt.V) != 0 {
|
||||||
|
return fmt.Errorf("V mismatch: got %v, want %v", v, tt.V)
|
||||||
|
}
|
||||||
|
if tx.To() == nil {
|
||||||
|
if tt.To != (common.Address{}) {
|
||||||
|
return fmt.Errorf("To mismatch when recipient is nil (contract creation): %x", tt.To)
|
||||||
|
}
|
||||||
|
} else if *tx.To() != tt.To {
|
||||||
|
return fmt.Errorf("To mismatch: got %x, want %x", *tx.To(), tt.To)
|
||||||
|
}
|
||||||
|
if tx.Value().Cmp(tt.Value) != 0 {
|
||||||
|
return fmt.Errorf("Value mismatch: got %x, want %x", tx.Value(), tt.Value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
// 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 tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VMTest checks EVM execution without block or transaction context.
|
||||||
|
// See https://github.com/ethereum/tests/wiki/VM-Tests for the test format specification.
|
||||||
|
type VMTest struct {
|
||||||
|
json vmJSON
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *VMTest) UnmarshalJSON(data []byte) error {
|
||||||
|
return json.Unmarshal(data, &t.json)
|
||||||
|
}
|
||||||
|
|
||||||
|
type vmJSON struct {
|
||||||
|
Env stEnv `json:"env"`
|
||||||
|
Exec vmExec `json:"exec"`
|
||||||
|
Logs common.UnprefixedHash `json:"logs"`
|
||||||
|
GasRemaining *math.HexOrDecimal64 `json:"gas"`
|
||||||
|
Out hexutil.Bytes `json:"out"`
|
||||||
|
Pre core.GenesisAlloc `json:"pre"`
|
||||||
|
Post core.GenesisAlloc `json:"post"`
|
||||||
|
PostStateRoot common.Hash `json:"postStateRoot"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate gencodec -type vmExec -field-override vmExecMarshaling -out gen_vmexec.go
|
||||||
|
|
||||||
|
type vmExec struct {
|
||||||
|
Address common.Address `json:"address" gencodec:"required"`
|
||||||
|
Caller common.Address `json:"caller" gencodec:"required"`
|
||||||
|
Origin common.Address `json:"origin" gencodec:"required"`
|
||||||
|
Code []byte `json:"code" gencodec:"required"`
|
||||||
|
Data []byte `json:"data" gencodec:"required"`
|
||||||
|
Value *big.Int `json:"value" gencodec:"required"`
|
||||||
|
GasLimit uint64 `json:"gas" gencodec:"required"`
|
||||||
|
GasPrice *big.Int `json:"gasPrice" gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type vmExecMarshaling struct {
|
||||||
|
Address common.UnprefixedAddress
|
||||||
|
Caller common.UnprefixedAddress
|
||||||
|
Origin common.UnprefixedAddress
|
||||||
|
Code hexutil.Bytes
|
||||||
|
Data hexutil.Bytes
|
||||||
|
Value *math.HexOrDecimal256
|
||||||
|
GasLimit math.HexOrDecimal64
|
||||||
|
GasPrice *math.HexOrDecimal256
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *VMTest) Run(vmconfig vm.Config) error {
|
||||||
|
db, _ := ethdb.NewMemDatabase()
|
||||||
|
statedb := makePreState(db, t.json.Pre)
|
||||||
|
ret, gasRemaining, err := t.exec(statedb, vmconfig)
|
||||||
|
|
||||||
|
if t.json.GasRemaining == nil {
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("gas unspecified (indicating an error), but VM returned no error")
|
||||||
|
}
|
||||||
|
if gasRemaining > 0 {
|
||||||
|
return fmt.Errorf("gas unspecified (indicating an error), but VM returned gas remaining > 0")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Test declares gas, expecting outputs to match.
|
||||||
|
if !bytes.Equal(ret, t.json.Out) {
|
||||||
|
return fmt.Errorf("return data mismatch: got %x, want %x", ret, t.json.Out)
|
||||||
|
}
|
||||||
|
if gasRemaining != uint64(*t.json.GasRemaining) {
|
||||||
|
return fmt.Errorf("remaining gas %v, want %v", gasRemaining, *t.json.GasRemaining)
|
||||||
|
}
|
||||||
|
for addr, account := range t.json.Post {
|
||||||
|
for k, wantV := range account.Storage {
|
||||||
|
if haveV := statedb.GetState(addr, k); haveV != wantV {
|
||||||
|
return fmt.Errorf("wrong storage value at %x:\n got %x\n want %x", k, haveV, wantV)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if root := statedb.IntermediateRoot(false); root != t.json.PostStateRoot {
|
||||||
|
// return fmt.Errorf("post state root mismatch, got %x, want %x", root, t.json.PostStateRoot)
|
||||||
|
// }
|
||||||
|
if logs := rlpHash(statedb.Logs()); logs != common.Hash(t.json.Logs) {
|
||||||
|
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, t.json.Logs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) {
|
||||||
|
evm := t.newEVM(statedb, vmconfig)
|
||||||
|
e := t.json.Exec
|
||||||
|
return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM {
|
||||||
|
initialCall := true
|
||||||
|
canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool {
|
||||||
|
if initialCall {
|
||||||
|
initialCall = false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return core.CanTransfer(db, address, amount)
|
||||||
|
}
|
||||||
|
transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {}
|
||||||
|
context := vm.Context{
|
||||||
|
CanTransfer: canTransfer,
|
||||||
|
Transfer: transfer,
|
||||||
|
GetHash: vmTestBlockHash,
|
||||||
|
Origin: t.json.Exec.Origin,
|
||||||
|
Coinbase: t.json.Env.Coinbase,
|
||||||
|
BlockNumber: new(big.Int).SetUint64(t.json.Env.Number),
|
||||||
|
Time: new(big.Int).SetUint64(t.json.Env.Timestamp),
|
||||||
|
GasLimit: t.json.Env.GasLimit,
|
||||||
|
Difficulty: t.json.Env.Difficulty,
|
||||||
|
GasPrice: t.json.Exec.GasPrice,
|
||||||
|
}
|
||||||
|
vmconfig.NoRecursion = true
|
||||||
|
return vm.NewEVM(context, statedb, params.MainnetChainConfig, vmconfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func vmTestBlockHash(n uint64) common.Hash {
|
||||||
|
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
|
||||||
|
}
|
Loading…
Reference in New Issue