Merge branch 'master' into swarm-network-rewrite

This commit is contained in:
Balint Gabor 2018-04-10 21:41:12 +02:00
commit f6d48fe564
54 changed files with 518 additions and 604 deletions

1
.gitattributes vendored
View file

@ -1,2 +1,3 @@
# Auto detect text files and perform LF normalization # Auto detect text files and perform LF normalization
* text=auto * text=auto
*.sol linguist-language=Solidity

View file

@ -12,7 +12,7 @@ matrix:
- sudo chmod 666 /dev/fuse - sudo chmod 666 /dev/fuse
- sudo chown root:$USER /etc/fuse.conf - sudo chown root:$USER /etc/fuse.conf
- go run build/ci.go install - go run build/ci.go install
- go run build/ci.go test -coverage - go run build/ci.go test -coverage $TEST_PACKAGES
# These are the latest Go versions. # These are the latest Go versions.
- os: linux - os: linux
@ -24,7 +24,7 @@ matrix:
- sudo chmod 666 /dev/fuse - sudo chmod 666 /dev/fuse
- sudo chown root:$USER /etc/fuse.conf - sudo chown root:$USER /etc/fuse.conf
- go run build/ci.go install - go run build/ci.go install
- go run build/ci.go test -coverage - go run build/ci.go test -coverage $TEST_PACKAGES
- os: osx - os: osx
go: "1.10" go: "1.10"
@ -34,7 +34,7 @@ matrix:
- brew install caskroom/cask/brew-cask - brew install caskroom/cask/brew-cask
- brew cask install osxfuse - brew cask install osxfuse
- go run build/ci.go install - go run build/ci.go install
- go run build/ci.go test -coverage - go run build/ci.go test -coverage $TEST_PACKAGES
# This builder only tests code linters on latest version of Go # This builder only tests code linters on latest version of Go
- os: linux - os: linux
@ -47,14 +47,12 @@ matrix:
script: script:
- go run build/ci.go lint - go run build/ci.go lint
# This builder does the Ubuntu PPA and Linux Azure uploads # This builder does the Ubuntu PPA upload
- os: linux - os: linux
dist: trusty dist: trusty
sudo: required
go: "1.10" go: "1.10"
env: env:
- ubuntu-ppa - ubuntu-ppa
- azure-linux
git: git:
submodules: false # avoid cloning ethereum/tests submodules: false # avoid cloning ethereum/tests
addons: addons:
@ -63,11 +61,25 @@ matrix:
- devscripts - devscripts
- debhelper - debhelper
- dput - dput
- gcc-multilib
- fakeroot - fakeroot
script: script:
# Build for the primary platforms that Trusty can manage
- go run build/ci.go debsrc -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>" -upload ppa:ethereum/ethereum - go run build/ci.go debsrc -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>" -upload ppa:ethereum/ethereum
# This builder does the Linux Azure uploads
- os: linux
dist: trusty
sudo: required
go: "1.10"
env:
- azure-linux
git:
submodules: false # avoid cloning ethereum/tests
addons:
apt:
packages:
- gcc-multilib
script:
# Build for the primary platforms that Trusty can manage
- go run build/ci.go install - go run build/ci.go install
- go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go install -arch 386 - go run build/ci.go install -arch 386
@ -181,7 +193,6 @@ matrix:
# This builder does the Azure archive purges to avoid accumulating junk # This builder does the Azure archive purges to avoid accumulating junk
- os: linux - os: linux
dist: trusty dist: trusty
sudo: required
go: "1.10" go: "1.10"
env: env:
- azure-purge - azure-purge

View file

@ -12,5 +12,11 @@ FROM alpine:latest
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates
COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/ COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/
RUN addgroup -g 1000 geth && \
adduser -h /root -D -u 1000 -G geth geth && \
chown geth:geth /root
USER geth
EXPOSE 8545 8546 30303 30303/udp 30304/udp EXPOSE 8545 8546 30303 30303/udp 30304/udp
ENTRYPOINT ["geth"] ENTRYPOINT ["geth"]

View file

@ -12,4 +12,10 @@ FROM alpine:latest
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates
COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/ COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/
RUN addgroup -g 1000 geth && \
adduser -h /root -D -u 1000 -G geth geth && \
chown geth:geth /root
USER geth
EXPOSE 8545 8546 30303 30303/udp 30304/udp EXPOSE 8545 8546 30303 30303/udp 30304/udp

View file

@ -142,7 +142,7 @@ Do not forget `--rpcaddr 0.0.0.0`, if you want to access RPC from other containe
### Programatically interfacing Geth nodes ### Programatically interfacing Geth nodes
As a developer, sooner rather than later you'll want to start interacting with Geth and the Ethereum As a developer, sooner rather than later you'll want to start interacting with Geth and the Ethereum
network via your own programs and not manually through the console. To aid this, Geth has built in network via your own programs and not manually through the console. To aid this, Geth has built-in
support for a JSON-RPC based APIs ([standard APIs](https://github.com/ethereum/wiki/wiki/JSON-RPC) and support for a JSON-RPC based APIs ([standard APIs](https://github.com/ethereum/wiki/wiki/JSON-RPC) and
[Geth specific APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)). These can be [Geth specific APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)). These can be
exposed via HTTP, WebSockets and IPC (unix sockets on unix based platforms, and named pipes on Windows). exposed via HTTP, WebSockets and IPC (unix sockets on unix based platforms, and named pipes on Windows).

View file

@ -25,23 +25,23 @@ import (
) )
var ( var (
big_t = reflect.TypeOf(&big.Int{}) bigT = reflect.TypeOf(&big.Int{})
derefbig_t = reflect.TypeOf(big.Int{}) derefbigT = reflect.TypeOf(big.Int{})
uint8_t = reflect.TypeOf(uint8(0)) uint8T = reflect.TypeOf(uint8(0))
uint16_t = reflect.TypeOf(uint16(0)) uint16T = reflect.TypeOf(uint16(0))
uint32_t = reflect.TypeOf(uint32(0)) uint32T = reflect.TypeOf(uint32(0))
uint64_t = reflect.TypeOf(uint64(0)) uint64T = reflect.TypeOf(uint64(0))
int_t = reflect.TypeOf(int(0)) intT = reflect.TypeOf(int(0))
int8_t = reflect.TypeOf(int8(0)) int8T = reflect.TypeOf(int8(0))
int16_t = reflect.TypeOf(int16(0)) int16T = reflect.TypeOf(int16(0))
int32_t = reflect.TypeOf(int32(0)) int32T = reflect.TypeOf(int32(0))
int64_t = reflect.TypeOf(int64(0)) int64T = reflect.TypeOf(int64(0))
address_t = reflect.TypeOf(common.Address{}) addressT = reflect.TypeOf(common.Address{})
int_ts = reflect.TypeOf([]int(nil)) intTS = reflect.TypeOf([]int(nil))
int8_ts = reflect.TypeOf([]int8(nil)) int8TS = reflect.TypeOf([]int8(nil))
int16_ts = reflect.TypeOf([]int16(nil)) int16TS = reflect.TypeOf([]int16(nil))
int32_ts = reflect.TypeOf([]int32(nil)) int32TS = reflect.TypeOf([]int32(nil))
int64_ts = reflect.TypeOf([]int64(nil)) int64TS = reflect.TypeOf([]int64(nil))
) )
// U256 converts a big Int into a 256bit EVM number. // U256 converts a big Int into a 256bit EVM number.
@ -52,7 +52,7 @@ func U256(n *big.Int) []byte {
// checks whether the given reflect value is signed. This also works for slices with a number type // checks whether the given reflect value is signed. This also works for slices with a number type
func isSigned(v reflect.Value) bool { func isSigned(v reflect.Value) bool {
switch v.Type() { switch v.Type() {
case int_ts, int8_ts, int16_ts, int32_ts, int64_ts, int_t, int8_t, int16_t, int32_t, int64_t: case intTS, int8TS, int16TS, int32TS, int64TS, intT, int8T, int16T, int32T, int64T:
return true return true
} }
return false return false

View file

@ -24,7 +24,7 @@ import (
// indirect recursively dereferences the value until it either gets the value // indirect recursively dereferences the value until it either gets the value
// or finds a big.Int // or finds a big.Int
func indirect(v reflect.Value) reflect.Value { func indirect(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbig_t { if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbigT {
return indirect(v.Elem()) return indirect(v.Elem())
} }
return v return v
@ -36,26 +36,26 @@ func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type)
switch size { switch size {
case 8: case 8:
if unsigned { if unsigned {
return reflect.Uint8, uint8_t return reflect.Uint8, uint8T
} }
return reflect.Int8, int8_t return reflect.Int8, int8T
case 16: case 16:
if unsigned { if unsigned {
return reflect.Uint16, uint16_t return reflect.Uint16, uint16T
} }
return reflect.Int16, int16_t return reflect.Int16, int16T
case 32: case 32:
if unsigned { if unsigned {
return reflect.Uint32, uint32_t return reflect.Uint32, uint32T
} }
return reflect.Int32, int32_t return reflect.Int32, int32T
case 64: case 64:
if unsigned { if unsigned {
return reflect.Uint64, uint64_t return reflect.Uint64, uint64T
} }
return reflect.Int64, int64_t return reflect.Int64, int64T
} }
return reflect.Ptr, big_t return reflect.Ptr, bigT
} }
// mustArrayToBytesSlice creates a new byte slice with the exact same size as value // mustArrayToBytesSlice creates a new byte slice with the exact same size as value

View file

@ -135,7 +135,7 @@ func NewType(t string) (typ Type, err error) {
typ.Type = reflect.TypeOf(bool(false)) typ.Type = reflect.TypeOf(bool(false))
case "address": case "address":
typ.Kind = reflect.Array typ.Kind = reflect.Array
typ.Type = address_t typ.Type = addressT
typ.Size = 20 typ.Size = 20
typ.T = AddressTy typ.T = AddressTy
case "string": case "string":

View file

@ -46,36 +46,36 @@ func TestTypeRegexp(t *testing.T) {
{"bool[2][2][2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2][2]bool{}), Elem: &Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2]bool{}), Elem: &Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]bool{}), Elem: &Type{Kind: reflect.Bool, T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}, stringKind: "bool[2][2][2]"}}, {"bool[2][2][2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2][2]bool{}), Elem: &Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2]bool{}), Elem: &Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]bool{}), Elem: &Type{Kind: reflect.Bool, T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}, stringKind: "bool[2][2][2]"}},
{"bool[][][]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][][]bool{}), Elem: &Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][]bool{}), Elem: &Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]bool{}), Elem: &Type{Kind: reflect.Bool, T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}, stringKind: "bool[][][]"}}, {"bool[][][]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][][]bool{}), Elem: &Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][]bool{}), Elem: &Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]bool{}), Elem: &Type{Kind: reflect.Bool, T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}, stringKind: "bool[][][]"}},
{"bool[][2][]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][2][]bool{}), Elem: &Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]bool{}), Elem: &Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]bool{}), Elem: &Type{Kind: reflect.Bool, T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}, stringKind: "bool[][2][]"}}, {"bool[][2][]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][2][]bool{}), Elem: &Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]bool{}), Elem: &Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]bool{}), Elem: &Type{Kind: reflect.Bool, T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}, stringKind: "bool[][2][]"}},
{"int8", Type{Kind: reflect.Int8, Type: int8_t, Size: 8, T: IntTy, stringKind: "int8"}}, {"int8", Type{Kind: reflect.Int8, Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}},
{"int16", Type{Kind: reflect.Int16, Type: int16_t, Size: 16, T: IntTy, stringKind: "int16"}}, {"int16", Type{Kind: reflect.Int16, Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}},
{"int32", Type{Kind: reflect.Int32, Type: int32_t, Size: 32, T: IntTy, stringKind: "int32"}}, {"int32", Type{Kind: reflect.Int32, Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}},
{"int64", Type{Kind: reflect.Int64, Type: int64_t, Size: 64, T: IntTy, stringKind: "int64"}}, {"int64", Type{Kind: reflect.Int64, Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}},
{"int256", Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}}, {"int256", Type{Kind: reflect.Ptr, Type: bigT, Size: 256, T: IntTy, stringKind: "int256"}},
{"int8[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int8{}), Elem: &Type{Kind: reflect.Int8, Type: int8_t, Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[]"}}, {"int8[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int8{}), Elem: &Type{Kind: reflect.Int8, Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[]"}},
{"int8[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int8{}), Elem: &Type{Kind: reflect.Int8, Type: int8_t, Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[2]"}}, {"int8[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int8{}), Elem: &Type{Kind: reflect.Int8, Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[2]"}},
{"int16[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int16{}), Elem: &Type{Kind: reflect.Int16, Type: int16_t, Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[]"}}, {"int16[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int16{}), Elem: &Type{Kind: reflect.Int16, Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[]"}},
{"int16[2]", Type{Size: 2, Kind: reflect.Array, T: ArrayTy, Type: reflect.TypeOf([2]int16{}), Elem: &Type{Kind: reflect.Int16, Type: int16_t, Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[2]"}}, {"int16[2]", Type{Size: 2, Kind: reflect.Array, T: ArrayTy, Type: reflect.TypeOf([2]int16{}), Elem: &Type{Kind: reflect.Int16, Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[2]"}},
{"int32[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int32{}), Elem: &Type{Kind: reflect.Int32, Type: int32_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}}, {"int32[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int32{}), Elem: &Type{Kind: reflect.Int32, Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}},
{"int32[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int32{}), Elem: &Type{Kind: reflect.Int32, Type: int32_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}}, {"int32[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int32{}), Elem: &Type{Kind: reflect.Int32, Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}},
{"int64[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int64{}), Elem: &Type{Kind: reflect.Int64, Type: int64_t, Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[]"}}, {"int64[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]int64{}), Elem: &Type{Kind: reflect.Int64, Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[]"}},
{"int64[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int64{}), Elem: &Type{Kind: reflect.Int64, Type: int64_t, Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[2]"}}, {"int64[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int64{}), Elem: &Type{Kind: reflect.Int64, Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[2]"}},
{"int256[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]*big.Int{}), Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}}, {"int256[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]*big.Int{}), Elem: &Type{Kind: reflect.Ptr, Type: bigT, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}},
{"int256[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]*big.Int{}), Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}}, {"int256[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]*big.Int{}), Elem: &Type{Kind: reflect.Ptr, Type: bigT, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}},
{"uint8", Type{Kind: reflect.Uint8, Type: uint8_t, Size: 8, T: UintTy, stringKind: "uint8"}}, {"uint8", Type{Kind: reflect.Uint8, Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}},
{"uint16", Type{Kind: reflect.Uint16, Type: uint16_t, Size: 16, T: UintTy, stringKind: "uint16"}}, {"uint16", Type{Kind: reflect.Uint16, Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}},
{"uint32", Type{Kind: reflect.Uint32, Type: uint32_t, Size: 32, T: UintTy, stringKind: "uint32"}}, {"uint32", Type{Kind: reflect.Uint32, Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}},
{"uint64", Type{Kind: reflect.Uint64, Type: uint64_t, Size: 64, T: UintTy, stringKind: "uint64"}}, {"uint64", Type{Kind: reflect.Uint64, Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}},
{"uint256", Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: UintTy, stringKind: "uint256"}}, {"uint256", Type{Kind: reflect.Ptr, Type: bigT, Size: 256, T: UintTy, stringKind: "uint256"}},
{"uint8[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]uint8{}), Elem: &Type{Kind: reflect.Uint8, Type: uint8_t, Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[]"}}, {"uint8[]", Type{Kind: reflect.Slice, T: SliceTy, Type: reflect.TypeOf([]uint8{}), Elem: &Type{Kind: reflect.Uint8, Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[]"}},
{"uint8[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint8{}), Elem: &Type{Kind: reflect.Uint8, Type: uint8_t, Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[2]"}}, {"uint8[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint8{}), Elem: &Type{Kind: reflect.Uint8, Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[2]"}},
{"uint16[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]uint16{}), Elem: &Type{Kind: reflect.Uint16, Type: uint16_t, Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[]"}}, {"uint16[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]uint16{}), Elem: &Type{Kind: reflect.Uint16, Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[]"}},
{"uint16[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint16{}), Elem: &Type{Kind: reflect.Uint16, Type: uint16_t, Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[2]"}}, {"uint16[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint16{}), Elem: &Type{Kind: reflect.Uint16, Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[2]"}},
{"uint32[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]uint32{}), Elem: &Type{Kind: reflect.Uint32, Type: uint32_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}}, {"uint32[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]uint32{}), Elem: &Type{Kind: reflect.Uint32, Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}},
{"uint32[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint32{}), Elem: &Type{Kind: reflect.Uint32, Type: uint32_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}}, {"uint32[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint32{}), Elem: &Type{Kind: reflect.Uint32, Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}},
{"uint64[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]uint64{}), Elem: &Type{Kind: reflect.Uint64, Type: uint64_t, Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[]"}}, {"uint64[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]uint64{}), Elem: &Type{Kind: reflect.Uint64, Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[]"}},
{"uint64[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint64{}), Elem: &Type{Kind: reflect.Uint64, Type: uint64_t, Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[2]"}}, {"uint64[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint64{}), Elem: &Type{Kind: reflect.Uint64, Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[2]"}},
{"uint256[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]*big.Int{}), Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}}, {"uint256[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]*big.Int{}), Elem: &Type{Kind: reflect.Ptr, Type: bigT, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}},
{"uint256[2]", Type{Kind: reflect.Array, T: ArrayTy, Type: reflect.TypeOf([2]*big.Int{}), Size: 2, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}}, {"uint256[2]", Type{Kind: reflect.Array, T: ArrayTy, Type: reflect.TypeOf([2]*big.Int{}), Size: 2, Elem: &Type{Kind: reflect.Ptr, Type: bigT, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}},
{"bytes32", Type{Kind: reflect.Array, T: FixedBytesTy, Size: 32, Type: reflect.TypeOf([32]byte{}), stringKind: "bytes32"}}, {"bytes32", Type{Kind: reflect.Array, T: FixedBytesTy, Size: 32, Type: reflect.TypeOf([32]byte{}), stringKind: "bytes32"}},
{"bytes[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][]byte{}), Elem: &Type{Kind: reflect.Slice, Type: reflect.TypeOf([]byte{}), T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}}, {"bytes[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([][]byte{}), Elem: &Type{Kind: reflect.Slice, Type: reflect.TypeOf([]byte{}), T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}},
{"bytes[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]byte{}), Elem: &Type{T: BytesTy, Type: reflect.TypeOf([]byte{}), Kind: reflect.Slice, stringKind: "bytes"}, stringKind: "bytes[2]"}}, {"bytes[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]byte{}), Elem: &Type{T: BytesTy, Type: reflect.TypeOf([]byte{}), Kind: reflect.Slice, stringKind: "bytes"}, stringKind: "bytes[2]"}},
@ -84,9 +84,9 @@ func TestTypeRegexp(t *testing.T) {
{"string", Type{Kind: reflect.String, T: StringTy, Type: reflect.TypeOf(""), stringKind: "string"}}, {"string", Type{Kind: reflect.String, T: StringTy, Type: reflect.TypeOf(""), stringKind: "string"}},
{"string[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]string{}), Elem: &Type{Kind: reflect.String, Type: reflect.TypeOf(""), T: StringTy, stringKind: "string"}, stringKind: "string[]"}}, {"string[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]string{}), Elem: &Type{Kind: reflect.String, Type: reflect.TypeOf(""), T: StringTy, stringKind: "string"}, stringKind: "string[]"}},
{"string[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]string{}), Elem: &Type{Kind: reflect.String, T: StringTy, Type: reflect.TypeOf(""), stringKind: "string"}, stringKind: "string[2]"}}, {"string[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]string{}), Elem: &Type{Kind: reflect.String, T: StringTy, Type: reflect.TypeOf(""), stringKind: "string"}, stringKind: "string[2]"}},
{"address", Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}}, {"address", Type{Kind: reflect.Array, Type: addressT, Size: 20, T: AddressTy, stringKind: "address"}},
{"address[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]common.Address{}), Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}}, {"address[]", Type{T: SliceTy, Kind: reflect.Slice, Type: reflect.TypeOf([]common.Address{}), Elem: &Type{Kind: reflect.Array, Type: addressT, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}},
{"address[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]common.Address{}), Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}}, {"address[2]", Type{Kind: reflect.Array, T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]common.Address{}), Elem: &Type{Kind: reflect.Array, Type: addressT, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}},
// TODO when fixed types are implemented properly // TODO when fixed types are implemented properly
// {"fixed", Type{}}, // {"fixed", Type{}},
// {"fixed128x128", Type{}}, // {"fixed128x128", Type{}},
@ -252,6 +252,9 @@ func TestTypeCheck(t *testing.T) {
{"bytes20", common.Address{}, ""}, {"bytes20", common.Address{}, ""},
{"address", [20]byte{}, ""}, {"address", [20]byte{}, ""},
{"address", common.Address{}, ""}, {"address", common.Address{}, ""},
{"bytes32[]]", "", "invalid arg type in abi"},
{"invalidType", "", "unsupported arg type: invalidType"},
{"invalidSlice[]", "", "unsupported arg type: invalidSlice"},
} { } {
typ, err := NewType(test.typ) typ, err := NewType(test.typ)
if err != nil && len(test.err) == 0 { if err != nil && len(test.err) == 0 {

View file

@ -56,6 +56,23 @@ var unpackTests = []unpackTest{
enc: "0000000000000000000000000000000000000000000000000000000000000001", enc: "0000000000000000000000000000000000000000000000000000000000000001",
want: true, want: true,
}, },
{
def: `[{ "type": "bool" }]`,
enc: "0000000000000000000000000000000000000000000000000000000000000000",
want: false,
},
{
def: `[{ "type": "bool" }]`,
enc: "0000000000000000000000000000000000000000000000000001000000000001",
want: false,
err: "abi: improperly encoded boolean value",
},
{
def: `[{ "type": "bool" }]`,
enc: "0000000000000000000000000000000000000000000000000000000000000003",
want: false,
err: "abi: improperly encoded boolean value",
},
{ {
def: `[{"type": "uint32"}]`, def: `[{"type": "uint32"}]`,
enc: "0000000000000000000000000000000000000000000000000000000000000001", enc: "0000000000000000000000000000000000000000000000000000000000000001",

View file

@ -75,7 +75,7 @@ type Hasher struct {
blocksize int // segment size (size of hash) also for hash.Hash blocksize int // segment size (size of hash) also for hash.Hash
count int // segment count count int // segment count
size int // for hash.Hash same as hashsize size int // for hash.Hash same as hashsize
cur int // cursor position for righmost currently open chunk cur int // cursor position for rightmost currently open chunk
segment []byte // the rightmost open segment (not complete) segment []byte // the rightmost open segment (not complete)
depth int // index of last level depth int // index of last level
result chan []byte // result channel result chan []byte // result channel
@ -149,7 +149,7 @@ func NewTreePool(hasher BaseHasher, segmentCount, capacity int) *TreePool {
} }
} }
// Drain drains the pool uptil it has no more than n resources // Drain drains the pool until it has no more than n resources
func (self *TreePool) Drain(n int) { func (self *TreePool) Drain(n int) {
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
@ -412,11 +412,10 @@ func (self *Hasher) Reset() {
// ResetWithLength needs to be called before writing to the hasher // ResetWithLength needs to be called before writing to the hasher
// the argument is supposed to be the byte slice binary representation of // the argument is supposed to be the byte slice binary representation of
// the legth of the data subsumed under the hash // the length of the data subsumed under the hash
func (self *Hasher) ResetWithLength(l []byte) { func (self *Hasher) ResetWithLength(l []byte) {
self.Reset() self.Reset()
self.blockLength = l self.blockLength = l
} }
// Release gives back the Tree to the pool whereby it unlocks // Release gives back the Tree to the pool whereby it unlocks
@ -531,7 +530,7 @@ func (self *Hasher) finalise(n *Node, i int) (d int) {
for { for {
// when the final segment's path is going via left segments // when the final segment's path is going via left segments
// the incoming data is pushed to the parent upon pulling the left // the incoming data is pushed to the parent upon pulling the left
// we do not need toogle the state since this condition is // we do not need toggle the state since this condition is
// detectable // detectable
n.unbalanced = isLeft n.unbalanced = isLeft
n.right = nil n.right = nil

View file

@ -766,7 +766,7 @@ func doAndroidArchive(cmdline []string) {
if meta.Develop { if meta.Develop {
repo = *deploy + "/content/repositories/snapshots" repo = *deploy + "/content/repositories/snapshots"
} }
build.MustRunCommand("mvn", "gpg:sign-and-deploy-file", build.MustRunCommand("mvn", "gpg:sign-and-deploy-file", "-e", "-X",
"-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh", "-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh",
"-DpomFile="+meta.Package+".pom", "-Dfile="+meta.Package+".aar") "-DpomFile="+meta.Package+".pom", "-Dfile="+meta.Package+".aar")
} }

View file

@ -76,6 +76,7 @@ func runCmd(ctx *cli.Context) error {
logconfig := &vm.LogConfig{ logconfig := &vm.LogConfig{
DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name),
DisableStack: ctx.GlobalBool(DisableStackFlag.Name), DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
Debug: ctx.GlobalBool(DebugFlag.Name),
} }
var ( var (
@ -83,8 +84,8 @@ func runCmd(ctx *cli.Context) error {
debugLogger *vm.StructLogger debugLogger *vm.StructLogger
statedb *state.StateDB statedb *state.StateDB
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
sender = common.StringToAddress("sender") sender = common.BytesToAddress([]byte("sender"))
receiver = common.StringToAddress("receiver") receiver = common.BytesToAddress([]byte("receiver"))
) )
if ctx.GlobalBool(MachineFlag.Name) { if ctx.GlobalBool(MachineFlag.Name) {
tracer = NewJSONLogger(logconfig, os.Stdout) tracer = NewJSONLogger(logconfig, os.Stdout)
@ -234,9 +235,7 @@ Gas used: %d
`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas)
} }
if tracer != nil { if tracer == nil {
tracer.CaptureEnd(ret, initialGas-leftOverGas, execTime, err)
} else {
fmt.Printf("0x%x\n", ret) fmt.Printf("0x%x\n", ret)
if err != nil { if err != nil {
fmt.Printf(" error: %v\n", err) fmt.Printf(" error: %v\n", err)

View file

@ -49,15 +49,17 @@ func reportBug(ctx *cli.Context) error {
// execute template and write contents to buff // execute template and write contents to buff
var buff bytes.Buffer var buff bytes.Buffer
fmt.Fprintln(&buff, header) fmt.Fprintln(&buff, "#### System information")
fmt.Fprintln(&buff)
fmt.Fprintln(&buff, "Version:", params.Version) fmt.Fprintln(&buff, "Version:", params.Version)
fmt.Fprintln(&buff, "Go Version:", runtime.Version()) fmt.Fprintln(&buff, "Go Version:", runtime.Version())
fmt.Fprintln(&buff, "OS:", runtime.GOOS) fmt.Fprintln(&buff, "OS:", runtime.GOOS)
printOSDetails(&buff) printOSDetails(&buff)
fmt.Fprintln(&buff, header)
// open a new GH issue // open a new GH issue
if !browser.Open(issueUrl + "?body=" + url.QueryEscape(buff.String())) { if !browser.Open(issueUrl + "?body=" + url.QueryEscape(buff.String())) {
fmt.Printf("Please file a new issue at %s using this template:\n%s", issueUrl, buff.String()) fmt.Printf("Please file a new issue at %s using this template:\n\n%s", issueUrl, buff.String())
} }
return nil return nil
} }
@ -97,13 +99,15 @@ func printCmdOut(w io.Writer, prefix, path string, args ...string) {
fmt.Fprintf(w, "%s%s\n", prefix, bytes.TrimSpace(out)) fmt.Fprintf(w, "%s%s\n", prefix, bytes.TrimSpace(out))
} }
const header = `Please answer these questions before submitting your issue. Thanks! const header = `
#### Expected behaviour
#### What did you do?
#### What did you expect to see? #### Actual behaviour
#### What did you see instead?
#### System details #### Steps to reproduce the behaviour
#### Backtrace
` `

View file

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
@ -46,8 +45,6 @@ const (
var ( var (
// Git SHA1 commit hash of the release (set via linker flags) // Git SHA1 commit hash of the release (set via linker flags)
gitCommit = "" gitCommit = ""
// Ethereum address of the Geth release oracle.
relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf")
// The app that holds all commands and flags. // The app that holds all commands and flags.
app = utils.NewApp(gitCommit, "the go-ethereum command line interface") app = utils.NewApp(gitCommit, "the go-ethereum command line interface")
// flags that configure the node // flags that configure the node

View file

@ -40,11 +40,11 @@ ADD genesis.json /genesis.json
ADD signer.pass /signer.pass ADD signer.pass /signer.pass
{{end}} {{end}}
RUN \ RUN \
echo 'geth --cache 512 init /genesis.json' > geth.sh && \{{if .Unlock}} echo 'geth --cache 512 init /genesis.json' > /root/geth.sh && \{{if .Unlock}}
echo 'mkdir -p /root/.ethereum/keystore/ && cp /signer.json /root/.ethereum/keystore/' >> geth.sh && \{{end}} echo 'mkdir -p /root/.ethereum/keystore/ && cp /signer.json /root/.ethereum/keystore/' >> /root/geth.sh && \{{end}}
echo $'geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--etherbase {{.Etherbase}} --mine --minerthreads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --targetgaslimit {{.GasTarget}} --gasprice {{.GasPrice}}' >> geth.sh echo $'geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--etherbase {{.Etherbase}} --mine --minerthreads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --targetgaslimit {{.GasTarget}} --gasprice {{.GasPrice}}' >> /root/geth.sh
ENTRYPOINT ["/bin/sh", "geth.sh"] ENTRYPOINT ["/bin/sh", "/root/geth.sh"]
` `
// nodeComposefile is the docker-compose.yml file required to deploy and maintain // nodeComposefile is the docker-compose.yml file required to deploy and maintain

View file

@ -45,9 +45,8 @@ func BytesToHash(b []byte) Hash {
h.SetBytes(b) h.SetBytes(b)
return h return h
} }
func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
// Get the string representation of the underlying hash // Get the string representation of the underlying hash
func (h Hash) Str() string { return string(h[:]) } func (h Hash) Str() string { return string(h[:]) }
@ -143,9 +142,8 @@ func BytesToAddress(b []byte) Address {
a.SetBytes(b) a.SetBytes(b)
return a return a
} }
func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) }
func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) }
// IsHexAddress verifies whether a string can represent a valid hex-encoded // IsHexAddress verifies whether a string can represent a valid hex-encoded
// Ethereum address or not. // Ethereum address or not.

View file

@ -1,101 +0,0 @@
// Copyright 2014 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 rle implements the run-length encoding used for Ethereum data.
package rle
import (
"bytes"
"errors"
"github.com/ethereum/go-ethereum/crypto"
)
const (
token byte = 0xfe
emptyShaToken = 0xfd
emptyListShaToken = 0xfe
tokenToken = 0xff
)
var empty = crypto.Keccak256([]byte(""))
var emptyList = crypto.Keccak256([]byte{0x80})
func Decompress(dat []byte) ([]byte, error) {
buf := new(bytes.Buffer)
for i := 0; i < len(dat); i++ {
if dat[i] == token {
if i+1 < len(dat) {
switch dat[i+1] {
case emptyShaToken:
buf.Write(empty)
case emptyListShaToken:
buf.Write(emptyList)
case tokenToken:
buf.WriteByte(token)
default:
buf.Write(make([]byte, int(dat[i+1]-2)))
}
i++
} else {
return nil, errors.New("error reading bytes. token encountered without proceeding bytes")
}
} else {
buf.WriteByte(dat[i])
}
}
return buf.Bytes(), nil
}
func compressChunk(dat []byte) (ret []byte, n int) {
switch {
case dat[0] == token:
return []byte{token, tokenToken}, 1
case len(dat) > 1 && dat[0] == 0x0 && dat[1] == 0x0:
j := 0
for j <= 254 && j < len(dat) {
if dat[j] != 0 {
break
}
j++
}
return []byte{token, byte(j + 2)}, j
case len(dat) >= 32:
if dat[0] == empty[0] && bytes.Equal(dat[:32], empty) {
return []byte{token, emptyShaToken}, 32
} else if dat[0] == emptyList[0] && bytes.Equal(dat[:32], emptyList) {
return []byte{token, emptyListShaToken}, 32
}
fallthrough
default:
return dat[:1], 1
}
}
func Compress(dat []byte) []byte {
buf := new(bytes.Buffer)
i := 0
for i < len(dat) {
b, n := compressChunk(dat[i:])
buf.Write(b)
i += n
}
return buf.Bytes()
}

View file

@ -1,50 +0,0 @@
// Copyright 2014 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 rle
import (
"testing"
checker "gopkg.in/check.v1"
)
func Test(t *testing.T) { checker.TestingT(t) }
type CompressionRleSuite struct{}
var _ = checker.Suite(&CompressionRleSuite{})
func (s *CompressionRleSuite) TestDecompressSimple(c *checker.C) {
exp := []byte{0xc5, 0xd2, 0x46, 0x1, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x3, 0xc0, 0xe5, 0x0, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x4, 0x5d, 0x85, 0xa4, 0x70}
res, err := Decompress([]byte{token, 0xfd})
c.Assert(err, checker.IsNil)
c.Assert(res, checker.DeepEquals, exp)
exp = []byte{0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x1, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21}
res, err = Decompress([]byte{token, 0xfe})
c.Assert(err, checker.IsNil)
c.Assert(res, checker.DeepEquals, exp)
res, err = Decompress([]byte{token, 0xff})
c.Assert(err, checker.IsNil)
c.Assert(res, checker.DeepEquals, []byte{token})
res, err = Decompress([]byte{token, 12})
c.Assert(err, checker.IsNil)
c.Assert(res, checker.DeepEquals, make([]byte, 10))
}

View file

@ -1338,3 +1338,114 @@ func TestLargeReorgTrieGC(t *testing.T) {
} }
} }
} }
// Benchmarks large blocks with value transfers to non-existing accounts
func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) {
var (
signer = types.HomesteadSigner{}
testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
bankFunds = big.NewInt(100000000000000000)
gspec = Genesis{
Config: params.TestChainConfig,
Alloc: GenesisAlloc{
testBankAddress: {Balance: bankFunds},
common.HexToAddress("0xc0de"): {
Code: []byte{0x60, 0x01, 0x50},
Balance: big.NewInt(0),
}, // push 1, pop
},
GasLimit: 100e6, // 100 M
}
)
// Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker()
db, _ := ethdb.NewMemDatabase()
genesis := gspec.MustCommit(db)
blockGenerator := func(i int, block *BlockGen) {
block.SetCoinbase(common.Address{1})
for txi := 0; txi < numTxs; txi++ {
uniq := uint64(i*numTxs + txi)
recipient := recipientFn(uniq)
//recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq))
tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey)
if err != nil {
b.Error(err)
}
block.AddTx(tx)
}
}
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator)
b.StopTimer()
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Import the shared chain and the original canonical one
diskdb, _ := ethdb.NewMemDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
if err != nil {
b.Fatalf("failed to create tester chain: %v", err)
}
b.StartTimer()
if _, err := chain.InsertChain(shared); err != nil {
b.Fatalf("failed to insert shared chain: %v", err)
}
b.StopTimer()
if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks {
b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got)
}
}
}
func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) {
var (
numTxs = 1000
numBlocks = 1
)
recipientFn := func(nonce uint64) common.Address {
return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce))
}
dataFn := func(nonce uint64) []byte {
return nil
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
}
func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) {
var (
numTxs = 1000
numBlocks = 1
)
b.StopTimer()
b.ResetTimer()
recipientFn := func(nonce uint64) common.Address {
return common.BigToAddress(big.NewInt(0).SetUint64(1337))
}
dataFn := func(nonce uint64) []byte {
return nil
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
}
func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
var (
numTxs = 1000
numBlocks = 1
)
b.StopTimer()
b.ResetTimer()
recipientFn := func(nonce uint64) common.Address {
return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de))
}
dataFn := func(nonce uint64) []byte {
return nil
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
}

View file

@ -317,7 +317,7 @@ func TestLookupStorage(t *testing.T) {
if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) {
t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i)
} }
if tx.String() != txn.String() { if tx.Hash() != txn.Hash() {
t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx)
} }
} }

View file

@ -26,7 +26,7 @@ import (
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
// Trie cache generation limit after which to evic trie nodes from memory. // Trie cache generation limit after which to evict trie nodes from memory.
var MaxTrieCacheGen = uint16(120) var MaxTrieCacheGen = uint16(120)
const ( const (
@ -151,9 +151,6 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro
return cached.(int), nil return cached.(int), nil
} }
code, err := db.ContractCode(addrHash, codeHash) code, err := db.ContractCode(addrHash, codeHash)
if err == nil {
db.codeSizeCache.Add(codeHash, len(code))
}
return len(code), err return len(code), err
} }

View file

@ -53,7 +53,7 @@ func (self *StateDB) RawDump() Dump {
panic(err) panic(err)
} }
obj := newObject(nil, common.BytesToAddress(addr), data, nil) obj := newObject(nil, common.BytesToAddress(addr), data)
account := DumpAccount{ account := DumpAccount{
Balance: data.Balance.String(), Balance: data.Balance.String(),
Nonce: data.Nonce, Nonce: data.Nonce,

View file

@ -22,11 +22,67 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
// journalEntry is a modification entry in the state change journal that can be
// reverted on demand.
type journalEntry interface { type journalEntry interface {
undo(*StateDB) // revert undoes the changes introduced by this journal entry.
revert(*StateDB)
// dirtied returns the Ethereum address modified by this journal entry.
dirtied() *common.Address
} }
type journal []journalEntry // journal contains the list of state modifications applied since the last state
// commit. These are tracked to be able to be reverted in case of an execution
// exception or revertal request.
type journal struct {
entries []journalEntry // Current changes tracked by the journal
dirties map[common.Address]int // Dirty accounts and the number of changes
}
// newJournal create a new initialized journal.
func newJournal() *journal {
return &journal{
dirties: make(map[common.Address]int),
}
}
// append inserts a new modification entry to the end of the change journal.
func (j *journal) append(entry journalEntry) {
j.entries = append(j.entries, entry)
if addr := entry.dirtied(); addr != nil {
j.dirties[*addr]++
}
}
// revert undoes a batch of journalled modifications along with any reverted
// dirty handling too.
func (j *journal) revert(statedb *StateDB, snapshot int) {
for i := len(j.entries) - 1; i >= snapshot; i-- {
// Undo the changes made by the operation
j.entries[i].revert(statedb)
// Drop any dirty tracking induced by the change
if addr := j.entries[i].dirtied(); addr != nil {
if j.dirties[*addr]--; j.dirties[*addr] == 0 {
delete(j.dirties, *addr)
}
}
}
j.entries = j.entries[:snapshot]
}
// dirty explicitly sets an address to dirty, even if the change entries would
// otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD
// precompile consensus exception.
func (j *journal) dirty(addr common.Address) {
j.dirties[addr]++
}
// length returns the current number of entries in the journal.
func (j *journal) length() int {
return len(j.entries)
}
type ( type (
// Changes to the account trie. // Changes to the account trie.
@ -77,16 +133,24 @@ type (
} }
) )
func (ch createObjectChange) undo(s *StateDB) { func (ch createObjectChange) revert(s *StateDB) {
delete(s.stateObjects, *ch.account) delete(s.stateObjects, *ch.account)
delete(s.stateObjectsDirty, *ch.account) delete(s.stateObjectsDirty, *ch.account)
} }
func (ch resetObjectChange) undo(s *StateDB) { func (ch createObjectChange) dirtied() *common.Address {
return ch.account
}
func (ch resetObjectChange) revert(s *StateDB) {
s.setStateObject(ch.prev) s.setStateObject(ch.prev)
} }
func (ch suicideChange) undo(s *StateDB) { func (ch resetObjectChange) dirtied() *common.Address {
return nil
}
func (ch suicideChange) revert(s *StateDB) {
obj := s.getStateObject(*ch.account) obj := s.getStateObject(*ch.account)
if obj != nil { if obj != nil {
obj.suicided = ch.prev obj.suicided = ch.prev
@ -94,38 +158,60 @@ func (ch suicideChange) undo(s *StateDB) {
} }
} }
var ripemd = common.HexToAddress("0000000000000000000000000000000000000003") func (ch suicideChange) dirtied() *common.Address {
return ch.account
func (ch touchChange) undo(s *StateDB) {
if !ch.prev && *ch.account != ripemd {
s.getStateObject(*ch.account).touched = ch.prev
if !ch.prevDirty {
delete(s.stateObjectsDirty, *ch.account)
}
}
} }
func (ch balanceChange) undo(s *StateDB) { var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
func (ch touchChange) revert(s *StateDB) {
}
func (ch touchChange) dirtied() *common.Address {
return ch.account
}
func (ch balanceChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setBalance(ch.prev) s.getStateObject(*ch.account).setBalance(ch.prev)
} }
func (ch nonceChange) undo(s *StateDB) { func (ch balanceChange) dirtied() *common.Address {
return ch.account
}
func (ch nonceChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setNonce(ch.prev) s.getStateObject(*ch.account).setNonce(ch.prev)
} }
func (ch codeChange) undo(s *StateDB) { func (ch nonceChange) dirtied() *common.Address {
return ch.account
}
func (ch codeChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
} }
func (ch storageChange) undo(s *StateDB) { func (ch codeChange) dirtied() *common.Address {
return ch.account
}
func (ch storageChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue) s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
} }
func (ch refundChange) undo(s *StateDB) { func (ch storageChange) dirtied() *common.Address {
return ch.account
}
func (ch refundChange) revert(s *StateDB) {
s.refund = ch.prev s.refund = ch.prev
} }
func (ch addLogChange) undo(s *StateDB) { func (ch refundChange) dirtied() *common.Address {
return nil
}
func (ch addLogChange) revert(s *StateDB) {
logs := s.logs[ch.txhash] logs := s.logs[ch.txhash]
if len(logs) == 1 { if len(logs) == 1 {
delete(s.logs, ch.txhash) delete(s.logs, ch.txhash)
@ -135,6 +221,14 @@ func (ch addLogChange) undo(s *StateDB) {
s.logSize-- s.logSize--
} }
func (ch addPreimageChange) undo(s *StateDB) { func (ch addLogChange) dirtied() *common.Address {
return nil
}
func (ch addPreimageChange) revert(s *StateDB) {
delete(s.preimages, ch.hash) delete(s.preimages, ch.hash)
} }
func (ch addPreimageChange) dirtied() *common.Address {
return nil
}

View file

@ -85,9 +85,7 @@ type stateObject struct {
// during the "update" phase of the state transition. // during the "update" phase of the state transition.
dirtyCode bool // true if the code was updated dirtyCode bool // true if the code was updated
suicided bool suicided bool
touched bool
deleted bool deleted bool
onDirty func(addr common.Address) // Callback method to mark a state object newly dirty
} }
// empty returns whether the account is considered empty. // empty returns whether the account is considered empty.
@ -105,7 +103,7 @@ type Account struct {
} }
// newObject creates a state object. // newObject creates a state object.
func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject { func newObject(db *StateDB, address common.Address, data Account) *stateObject {
if data.Balance == nil { if data.Balance == nil {
data.Balance = new(big.Int) data.Balance = new(big.Int)
} }
@ -119,7 +117,6 @@ func newObject(db *StateDB, address common.Address, data Account, onDirty func(a
data: data, data: data,
cachedStorage: make(Storage), cachedStorage: make(Storage),
dirtyStorage: make(Storage), dirtyStorage: make(Storage),
onDirty: onDirty,
} }
} }
@ -137,23 +134,17 @@ func (self *stateObject) setError(err error) {
func (self *stateObject) markSuicided() { func (self *stateObject) markSuicided() {
self.suicided = true self.suicided = true
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
}
} }
func (c *stateObject) touch() { func (c *stateObject) touch() {
c.db.journal = append(c.db.journal, touchChange{ c.db.journal.append(touchChange{
account: &c.address, account: &c.address,
prev: c.touched,
prevDirty: c.onDirty == nil,
}) })
if c.onDirty != nil { if c.address == ripemd {
c.onDirty(c.Address()) // Explicitly put it in the dirty-cache, which is otherwise generated from
c.onDirty = nil // flattened journals.
c.db.journal.dirty(c.address)
} }
c.touched = true
} }
func (c *stateObject) getTrie(db Database) Trie { func (c *stateObject) getTrie(db Database) Trie {
@ -195,7 +186,7 @@ func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
// SetState updates a value in account storage. // SetState updates a value in account storage.
func (self *stateObject) SetState(db Database, key, value common.Hash) { func (self *stateObject) SetState(db Database, key, value common.Hash) {
self.db.journal = append(self.db.journal, storageChange{ self.db.journal.append(storageChange{
account: &self.address, account: &self.address,
key: key, key: key,
prevalue: self.GetState(db, key), prevalue: self.GetState(db, key),
@ -207,10 +198,6 @@ func (self *stateObject) setState(key, value common.Hash) {
self.cachedStorage[key] = value self.cachedStorage[key] = value
self.dirtyStorage[key] = value self.dirtyStorage[key] = value
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
}
} }
// updateTrie writes cached storage modifications into the object's storage trie. // updateTrie writes cached storage modifications into the object's storage trie.
@ -274,7 +261,7 @@ func (c *stateObject) SubBalance(amount *big.Int) {
} }
func (self *stateObject) SetBalance(amount *big.Int) { func (self *stateObject) SetBalance(amount *big.Int) {
self.db.journal = append(self.db.journal, balanceChange{ self.db.journal.append(balanceChange{
account: &self.address, account: &self.address,
prev: new(big.Int).Set(self.data.Balance), prev: new(big.Int).Set(self.data.Balance),
}) })
@ -283,17 +270,13 @@ func (self *stateObject) SetBalance(amount *big.Int) {
func (self *stateObject) setBalance(amount *big.Int) { func (self *stateObject) setBalance(amount *big.Int) {
self.data.Balance = amount self.data.Balance = amount
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
}
} }
// Return the gas back to the origin. Used by the Virtual machine or Closures // Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *stateObject) ReturnGas(gas *big.Int) {} func (c *stateObject) ReturnGas(gas *big.Int) {}
func (self *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *stateObject { func (self *stateObject) deepCopy(db *StateDB) *stateObject {
stateObject := newObject(db, self.address, self.data, onDirty) stateObject := newObject(db, self.address, self.data)
if self.trie != nil { if self.trie != nil {
stateObject.trie = db.db.CopyTrie(self.trie) stateObject.trie = db.db.CopyTrie(self.trie)
} }
@ -333,7 +316,7 @@ func (self *stateObject) Code(db Database) []byte {
func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { func (self *stateObject) SetCode(codeHash common.Hash, code []byte) {
prevcode := self.Code(self.db.db) prevcode := self.Code(self.db.db)
self.db.journal = append(self.db.journal, codeChange{ self.db.journal.append(codeChange{
account: &self.address, account: &self.address,
prevhash: self.CodeHash(), prevhash: self.CodeHash(),
prevcode: prevcode, prevcode: prevcode,
@ -345,14 +328,10 @@ func (self *stateObject) setCode(codeHash common.Hash, code []byte) {
self.code = code self.code = code
self.data.CodeHash = codeHash[:] self.data.CodeHash = codeHash[:]
self.dirtyCode = true self.dirtyCode = true
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
}
} }
func (self *stateObject) SetNonce(nonce uint64) { func (self *stateObject) SetNonce(nonce uint64) {
self.db.journal = append(self.db.journal, nonceChange{ self.db.journal.append(nonceChange{
account: &self.address, account: &self.address,
prev: self.data.Nonce, prev: self.data.Nonce,
}) })
@ -361,10 +340,6 @@ func (self *stateObject) SetNonce(nonce uint64) {
func (self *stateObject) setNonce(nonce uint64) { func (self *stateObject) setNonce(nonce uint64) {
self.data.Nonce = nonce self.data.Nonce = nonce
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
}
} }
func (self *stateObject) CodeHash() []byte { func (self *stateObject) CodeHash() []byte {

View file

@ -76,7 +76,7 @@ type StateDB struct {
// Journal of state modifications. This is the backbone of // Journal of state modifications. This is the backbone of
// Snapshot and RevertToSnapshot. // Snapshot and RevertToSnapshot.
journal journal journal *journal
validRevisions []revision validRevisions []revision
nextRevisionId int nextRevisionId int
@ -96,6 +96,7 @@ func New(root common.Hash, db Database) (*StateDB, error) {
stateObjectsDirty: make(map[common.Address]struct{}), stateObjectsDirty: make(map[common.Address]struct{}),
logs: make(map[common.Hash][]*types.Log), logs: make(map[common.Hash][]*types.Log),
preimages: make(map[common.Hash][]byte), preimages: make(map[common.Hash][]byte),
journal: newJournal(),
}, nil }, nil
} }
@ -131,7 +132,7 @@ func (self *StateDB) Reset(root common.Hash) error {
} }
func (self *StateDB) AddLog(log *types.Log) { func (self *StateDB) AddLog(log *types.Log) {
self.journal = append(self.journal, addLogChange{txhash: self.thash}) self.journal.append(addLogChange{txhash: self.thash})
log.TxHash = self.thash log.TxHash = self.thash
log.BlockHash = self.bhash log.BlockHash = self.bhash
@ -156,7 +157,7 @@ func (self *StateDB) Logs() []*types.Log {
// AddPreimage records a SHA3 preimage seen by the VM. // AddPreimage records a SHA3 preimage seen by the VM.
func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) { func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
if _, ok := self.preimages[hash]; !ok { if _, ok := self.preimages[hash]; !ok {
self.journal = append(self.journal, addPreimageChange{hash: hash}) self.journal.append(addPreimageChange{hash: hash})
pi := make([]byte, len(preimage)) pi := make([]byte, len(preimage))
copy(pi, preimage) copy(pi, preimage)
self.preimages[hash] = pi self.preimages[hash] = pi
@ -169,7 +170,7 @@ func (self *StateDB) Preimages() map[common.Hash][]byte {
} }
func (self *StateDB) AddRefund(gas uint64) { func (self *StateDB) AddRefund(gas uint64) {
self.journal = append(self.journal, refundChange{prev: self.refund}) self.journal.append(refundChange{prev: self.refund})
self.refund += gas self.refund += gas
} }
@ -235,10 +236,10 @@ func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
return common.BytesToHash(stateObject.CodeHash()) return common.BytesToHash(stateObject.CodeHash())
} }
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { func (self *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash {
stateObject := self.getStateObject(a) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
return stateObject.GetState(self.db, b) return stateObject.GetState(self.db, bhash)
} }
return common.Hash{} return common.Hash{}
} }
@ -250,12 +251,12 @@ func (self *StateDB) Database() Database {
// StorageTrie returns the storage trie of an account. // StorageTrie returns the storage trie of an account.
// The return value is a copy and is nil for non-existent accounts. // The return value is a copy and is nil for non-existent accounts.
func (self *StateDB) StorageTrie(a common.Address) Trie { func (self *StateDB) StorageTrie(addr common.Address) Trie {
stateObject := self.getStateObject(a) stateObject := self.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return nil return nil
} }
cpy := stateObject.deepCopy(self, nil) cpy := stateObject.deepCopy(self)
return cpy.updateTrie(self.db) return cpy.updateTrie(self.db)
} }
@ -271,7 +272,7 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
* SETTERS * SETTERS
*/ */
// AddBalance adds amount to the account associated with addr // AddBalance adds amount to the account associated with addr.
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
@ -279,7 +280,7 @@ func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
} }
} }
// SubBalance subtracts amount from the account associated with addr // SubBalance subtracts amount from the account associated with addr.
func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
@ -308,7 +309,7 @@ func (self *StateDB) SetCode(addr common.Address, code []byte) {
} }
} }
func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) { func (self *StateDB) SetState(addr common.Address, key, value common.Hash) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetState(self.db, key, value) stateObject.SetState(self.db, key, value)
@ -325,7 +326,7 @@ func (self *StateDB) Suicide(addr common.Address) bool {
if stateObject == nil { if stateObject == nil {
return false return false
} }
self.journal = append(self.journal, suicideChange{ self.journal.append(suicideChange{
account: &addr, account: &addr,
prev: stateObject.suicided, prev: stateObject.suicided,
prevbalance: new(big.Int).Set(stateObject.Balance()), prevbalance: new(big.Int).Set(stateObject.Balance()),
@ -337,7 +338,7 @@ func (self *StateDB) Suicide(addr common.Address) bool {
} }
// //
// Setting, updating & deleting state object methods // Setting, updating & deleting state object methods.
// //
// updateStateObject writes the given object to the trie. // updateStateObject writes the given object to the trie.
@ -379,7 +380,7 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje
return nil return nil
} }
// Insert into the live set. // Insert into the live set.
obj := newObject(self, addr, data, self.MarkStateObjectDirty) obj := newObject(self, addr, data)
self.setStateObject(obj) self.setStateObject(obj)
return obj return obj
} }
@ -388,7 +389,7 @@ func (self *StateDB) setStateObject(object *stateObject) {
self.stateObjects[object.Address()] = object self.stateObjects[object.Address()] = object
} }
// Retrieve a state object or create a new state object if nil // Retrieve a state object or create a new state object if nil.
func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
stateObject := self.getStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject == nil || stateObject.deleted { if stateObject == nil || stateObject.deleted {
@ -397,22 +398,16 @@ func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
return stateObject return stateObject
} }
// MarkStateObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *StateDB) MarkStateObjectDirty(addr common.Address) {
self.stateObjectsDirty[addr] = struct{}{}
}
// createObject creates a new state object. If there is an existing account with // createObject creates a new state object. If there is an existing account with
// the given address, it is overwritten and returned as the second return value. // the given address, it is overwritten and returned as the second return value.
func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = self.getStateObject(addr) prev = self.getStateObject(addr)
newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty) newobj = newObject(self, addr, Account{})
newobj.setNonce(0) // sets the object to dirty newobj.setNonce(0) // sets the object to dirty
if prev == nil { if prev == nil {
self.journal = append(self.journal, createObjectChange{account: &addr}) self.journal.append(createObjectChange{account: &addr})
} else { } else {
self.journal = append(self.journal, resetObjectChange{prev: prev}) self.journal.append(resetObjectChange{prev: prev})
} }
self.setStateObject(newobj) self.setStateObject(newobj)
return newobj, prev return newobj, prev
@ -466,16 +461,17 @@ func (self *StateDB) Copy() *StateDB {
state := &StateDB{ state := &StateDB{
db: self.db, db: self.db,
trie: self.db.CopyTrie(self.trie), trie: self.db.CopyTrie(self.trie),
stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)), stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)),
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)), stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)),
refund: self.refund, refund: self.refund,
logs: make(map[common.Hash][]*types.Log, len(self.logs)), logs: make(map[common.Hash][]*types.Log, len(self.logs)),
logSize: self.logSize, logSize: self.logSize,
preimages: make(map[common.Hash][]byte), preimages: make(map[common.Hash][]byte),
journal: newJournal(),
} }
// Copy the dirty states, logs, and preimages // Copy the dirty states, logs, and preimages
for addr := range self.stateObjectsDirty { for addr := range self.journal.dirties {
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty) state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state)
state.stateObjectsDirty[addr] = struct{}{} state.stateObjectsDirty[addr] = struct{}{}
} }
for hash, logs := range self.logs { for hash, logs := range self.logs {
@ -492,7 +488,7 @@ func (self *StateDB) Copy() *StateDB {
func (self *StateDB) Snapshot() int { func (self *StateDB) Snapshot() int {
id := self.nextRevisionId id := self.nextRevisionId
self.nextRevisionId++ self.nextRevisionId++
self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)}) self.validRevisions = append(self.validRevisions, revision{id, self.journal.length()})
return id return id
} }
@ -507,13 +503,8 @@ func (self *StateDB) RevertToSnapshot(revid int) {
} }
snapshot := self.validRevisions[idx].journalIndex snapshot := self.validRevisions[idx].journalIndex
// Replay the journal to undo changes. // Replay the journal to undo changes and remove invalidated snapshots
for i := len(self.journal) - 1; i >= snapshot; i-- { self.journal.revert(self, snapshot)
self.journal[i].undo(self)
}
self.journal = self.journal[:snapshot]
// Remove invalidated snapshots from the stack.
self.validRevisions = self.validRevisions[:idx] self.validRevisions = self.validRevisions[:idx]
} }
@ -525,14 +516,25 @@ func (self *StateDB) GetRefund() uint64 {
// Finalise finalises the state by removing the self destructed objects // Finalise finalises the state by removing the self destructed objects
// and clears the journal as well as the refunds. // and clears the journal as well as the refunds.
func (s *StateDB) Finalise(deleteEmptyObjects bool) { func (s *StateDB) Finalise(deleteEmptyObjects bool) {
for addr := range s.stateObjectsDirty { for addr := range s.journal.dirties {
stateObject := s.stateObjects[addr] stateObject, exist := s.stateObjects[addr]
if !exist {
// ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2
// That tx goes out of gas, and although the notion of 'touched' does not exist there, the
// touch-event will still be recorded in the journal. Since ripeMD is a special snowflake,
// it will persist in the journal even though the journal is reverted. In this special circumstance,
// it may exist in `s.journal.dirties` but not in `s.stateObjects`.
// Thus, we can safely ignore it here
continue
}
if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) {
s.deleteStateObject(stateObject) s.deleteStateObject(stateObject)
} else { } else {
stateObject.updateRoot(s.db) stateObject.updateRoot(s.db)
s.updateStateObject(stateObject) s.updateStateObject(stateObject)
} }
s.stateObjectsDirty[addr] = struct{}{}
} }
// Invalidate journal because reverting across transactions is not allowed. // Invalidate journal because reverting across transactions is not allowed.
s.clearJournalAndRefund() s.clearJournalAndRefund()
@ -576,7 +578,7 @@ func (s *StateDB) DeleteSuicides() {
} }
func (s *StateDB) clearJournalAndRefund() { func (s *StateDB) clearJournalAndRefund() {
s.journal = nil s.journal = newJournal()
s.validRevisions = s.validRevisions[:0] s.validRevisions = s.validRevisions[:0]
s.refund = 0 s.refund = 0
} }
@ -585,6 +587,9 @@ func (s *StateDB) clearJournalAndRefund() {
func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) { func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) {
defer s.clearJournalAndRefund() defer s.clearJournalAndRefund()
for addr := range s.journal.dirties {
s.stateObjectsDirty[addr] = struct{}{}
}
// Commit objects to the trie. // Commit objects to the trie.
for addr, stateObject := range s.stateObjects { for addr, stateObject := range s.stateObjects {
_, isDirty := s.stateObjectsDirty[addr] _, isDirty := s.stateObjectsDirty[addr]

View file

@ -413,11 +413,12 @@ func (s *StateSuite) TestTouchDelete(c *check.C) {
snapshot := s.state.Snapshot() snapshot := s.state.Snapshot()
s.state.AddBalance(common.Address{}, new(big.Int)) s.state.AddBalance(common.Address{}, new(big.Int))
if len(s.state.stateObjectsDirty) != 1 {
if len(s.state.journal.dirties) != 1 {
c.Fatal("expected one dirty state object") c.Fatal("expected one dirty state object")
} }
s.state.RevertToSnapshot(snapshot) s.state.RevertToSnapshot(snapshot)
if len(s.state.stateObjectsDirty) != 0 { if len(s.state.journal.dirties) != 0 {
c.Fatal("expected no dirty state object") c.Fatal("expected no dirty state object")
} }
} }

View file

@ -132,28 +132,12 @@ func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool,
return NewStateTransition(evm, msg, gp).TransitionDb() return NewStateTransition(evm, msg, gp).TransitionDb()
} }
func (st *StateTransition) from() vm.AccountRef { // to returns the recipient of the message.
f := st.msg.From() func (st *StateTransition) to() common.Address {
if !st.state.Exist(f) { if st.msg == nil || st.msg.To() == nil /* contract creation */ {
st.state.CreateAccount(f) return common.Address{}
} }
return vm.AccountRef(f) return *st.msg.To()
}
func (st *StateTransition) to() vm.AccountRef {
if st.msg == nil {
return vm.AccountRef{}
}
to := st.msg.To()
if to == nil {
return vm.AccountRef{} // contract creation
}
reference := vm.AccountRef(*to)
if !st.state.Exist(*to) {
st.state.CreateAccount(*to)
}
return reference
} }
func (st *StateTransition) useGas(amount uint64) error { func (st *StateTransition) useGas(amount uint64) error {
@ -166,12 +150,8 @@ func (st *StateTransition) useGas(amount uint64) error {
} }
func (st *StateTransition) buyGas() error { func (st *StateTransition) buyGas() error {
var (
state = st.state
sender = st.from()
)
mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice) mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
if state.GetBalance(sender.Address()).Cmp(mgval) < 0 { if st.state.GetBalance(st.msg.From()).Cmp(mgval) < 0 {
return errInsufficientBalanceForGas return errInsufficientBalanceForGas
} }
if err := st.gp.SubGas(st.msg.Gas()); err != nil { if err := st.gp.SubGas(st.msg.Gas()); err != nil {
@ -180,20 +160,17 @@ func (st *StateTransition) buyGas() error {
st.gas += st.msg.Gas() st.gas += st.msg.Gas()
st.initialGas = st.msg.Gas() st.initialGas = st.msg.Gas()
state.SubBalance(sender.Address(), mgval) st.state.SubBalance(st.msg.From(), mgval)
return nil return nil
} }
func (st *StateTransition) preCheck() error { func (st *StateTransition) preCheck() error {
msg := st.msg // Make sure this transaction's nonce is correct.
sender := st.from() if st.msg.CheckNonce() {
nonce := st.state.GetNonce(st.msg.From())
// Make sure this transaction's nonce is correct if nonce < st.msg.Nonce() {
if msg.CheckNonce() {
nonce := st.state.GetNonce(sender.Address())
if nonce < msg.Nonce() {
return ErrNonceTooHigh return ErrNonceTooHigh
} else if nonce > msg.Nonce() { } else if nonce > st.msg.Nonce() {
return ErrNonceTooLow return ErrNonceTooLow
} }
} }
@ -208,8 +185,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
return return
} }
msg := st.msg msg := st.msg
sender := st.from() // err checked in preCheck sender := vm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber) homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
contractCreation := msg.To() == nil contractCreation := msg.To() == nil
@ -233,8 +209,8 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value) ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
} else { } else {
// Increment the nonce for the next transaction // Increment the nonce for the next transaction
st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1) st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
ret, st.gas, vmerr = evm.Call(sender, st.to().Address(), st.data, st.gas, st.value) ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
} }
if vmerr != nil { if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr) log.Debug("VM returned with error", "err", vmerr)
@ -260,10 +236,8 @@ func (st *StateTransition) refundGas() {
st.gas += refund st.gas += refund
// Return ETH for remaining gas, exchanged at the original rate. // Return ETH for remaining gas, exchanged at the original rate.
sender := st.from()
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
st.state.AddBalance(sender.Address(), remaining) st.state.AddBalance(st.msg.From(), remaining)
// Also return remaining gas to the block gas counter so it is // Also return remaining gas to the block gas counter so it is
// available for the next transaction. // available for the next transaction.

View file

@ -19,7 +19,6 @@ package types
import ( import (
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
"math/big" "math/big"
"sort" "sort"
@ -389,40 +388,6 @@ func (b *Block) Hash() common.Hash {
return v return v
} }
func (b *Block) String() string {
str := fmt.Sprintf(`Block(#%v): Size: %v {
MinerHash: %x
%v
Transactions:
%v
Uncles:
%v
}
`, b.Number(), b.Size(), b.header.HashNoNonce(), b.header, b.transactions, b.uncles)
return str
}
func (h *Header) String() string {
return fmt.Sprintf(`Header(%x):
[
ParentHash: %x
UncleHash: %x
Coinbase: %x
Root: %x
TxSha %x
ReceiptSha: %x
Bloom: %x
Difficulty: %v
Number: %v
GasLimit: %v
GasUsed: %v
Time: %v
Extra: %s
MixDigest: %x
Nonce: %x
]`, h.Hash(), h.ParentHash, h.UncleHash, h.Coinbase, h.Root, h.TxHash, h.ReceiptHash, h.Bloom, h.Difficulty, h.Number, h.GasLimit, h.GasUsed, h.Time, h.Extra, h.MixDigest, h.Nonce)
}
type Blocks []*Block type Blocks []*Block
type BlockBy func(b1, b2 *Block) bool type BlockBy func(b1, b2 *Block) bool

View file

@ -17,7 +17,6 @@
package types package types
import ( import (
"fmt"
"io" "io"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -95,10 +94,6 @@ func (l *Log) DecodeRLP(s *rlp.Stream) error {
return err return err
} }
func (l *Log) String() string {
return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, l.Address, l.Topics, l.Data, l.TxHash, l.TxIndex, l.BlockHash, l.Index)
}
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of // LogForStorage is a wrapper around a Log that flattens and parses the entire content of
// a log including non-consensus fields. // a log including non-consensus fields.
type LogForStorage Log type LogForStorage Log

View file

@ -149,14 +149,6 @@ func (r *Receipt) Size() common.StorageSize {
return size return size
} }
// String implements the Stringer interface.
func (r *Receipt) String() string {
if len(r.PostState) == 0 {
return fmt.Sprintf("receipt{status=%d cgas=%v bloom=%x logs=%v}", r.Status, r.CumulativeGasUsed, r.Bloom, r.Logs)
}
return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs)
}
// ReceiptForStorage is a wrapper around a Receipt that flattens and parses the // ReceiptForStorage is a wrapper around a Receipt that flattens and parses the
// entire content of a receipt, as opposed to only the consensus fields originally. // entire content of a receipt, as opposed to only the consensus fields originally.
type ReceiptForStorage Receipt type ReceiptForStorage Receipt

View file

@ -19,7 +19,6 @@ package types
import ( import (
"container/heap" "container/heap"
"errors" "errors"
"fmt"
"io" "io"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
@ -262,58 +261,6 @@ func (tx *Transaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) {
return tx.data.V, tx.data.R, tx.data.S return tx.data.V, tx.data.R, tx.data.S
} }
func (tx *Transaction) String() string {
var from, to string
if tx.data.V != nil {
// make a best guess about the signer and use that to derive
// the sender.
signer := deriveSigner(tx.data.V)
if f, err := Sender(signer, tx); err != nil { // derive but don't cache
from = "[invalid sender: invalid sig]"
} else {
from = fmt.Sprintf("%x", f[:])
}
} else {
from = "[invalid sender: nil V field]"
}
if tx.data.Recipient == nil {
to = "[contract creation]"
} else {
to = fmt.Sprintf("%x", tx.data.Recipient[:])
}
enc, _ := rlp.EncodeToBytes(&tx.data)
return fmt.Sprintf(`
TX(%x)
Contract: %v
From: %s
To: %s
Nonce: %v
GasPrice: %#x
GasLimit %#x
Value: %#x
Data: 0x%x
V: %#x
R: %#x
S: %#x
Hex: %x
`,
tx.Hash(),
tx.data.Recipient == nil,
from,
to,
tx.data.AccountNonce,
tx.data.Price,
tx.data.GasLimit,
tx.data.Amount,
tx.data.Payload,
tx.data.V,
tx.data.R,
tx.data.S,
enc,
)
}
// Transactions is a Transaction slice type for basic sorting. // Transactions is a Transaction slice type for basic sorting.
type Transactions []*Transaction type Transactions []*Transaction

View file

@ -45,6 +45,7 @@ type LogConfig struct {
DisableMemory bool // disable memory capture DisableMemory bool // disable memory capture
DisableStack bool // disable stack capture DisableStack bool // disable stack capture
DisableStorage bool // disable storage capture DisableStorage bool // disable storage capture
Debug bool // print output during capture end
Limit int // maximum length of output, but zero means unlimited Limit int // maximum length of output, but zero means unlimited
} }
@ -184,6 +185,12 @@ func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost ui
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error {
l.output = output l.output = output
l.err = err l.err = err
if l.cfg.Debug {
fmt.Printf("0x%x\n", output)
if err != nil {
fmt.Printf(" error: %v\n", err)
}
}
return nil return nil
} }

View file

@ -103,7 +103,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db)) cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db))
} }
var ( var (
address = common.StringToAddress("contract") address = common.BytesToAddress([]byte("contract"))
vmenv = NewEnv(cfg) vmenv = NewEnv(cfg)
sender = vm.AccountRef(cfg.Origin) sender = vm.AccountRef(cfg.Origin)
) )
@ -113,7 +113,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
// Call the code with the given configuration. // Call the code with the given configuration.
ret, _, err := vmenv.Call( ret, _, err := vmenv.Call(
sender, sender,
common.StringToAddress("contract"), common.BytesToAddress([]byte("contract")),
input, input,
cfg.GasLimit, cfg.GasLimit,
cfg.Value, cfg.Value,

View file

@ -290,11 +290,11 @@ func init() {
// See SEC 2 section 2.7.1 // See SEC 2 section 2.7.1
// curve parameters taken from: // curve parameters taken from:
// http://www.secg.org/collateral/sec2_final.pdf // http://www.secg.org/collateral/sec2_final.pdf
theCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) theCurve.P = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")
theCurve.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) theCurve.N = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")
theCurve.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16) theCurve.B = math.MustParseBig256("0x0000000000000000000000000000000000000000000000000000000000000007")
theCurve.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16) theCurve.Gx = math.MustParseBig256("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
theCurve.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) theCurve.Gy = math.MustParseBig256("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
theCurve.BitSize = 256 theCurve.BitSize = 256
} }

View file

@ -63,7 +63,7 @@ type Ethereum struct {
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
// Channel for shutting down the service // Channel for shutting down the service
shutdownChan chan bool // Channel for shutting down the ethereum shutdownChan chan bool // Channel for shutting down the Ethereum
stopDbUpgrade func() error // stop chain db sequential key upgrade stopDbUpgrade func() error // stop chain db sequential key upgrade
// Handlers // Handlers
@ -351,7 +351,7 @@ func (s *Ethereum) StartMining(local bool) error {
if local { if local {
// If local (CPU) mining is started, we can disable the transaction rejection // If local (CPU) mining is started, we can disable the transaction rejection
// mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous // mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous
// so noone will ever hit this path, whereas marking sync done on CPU mining // so none will ever hit this path, whereas marking sync done on CPU mining
// will ensure that private networks work in single miner mode too. // will ensure that private networks work in single miner mode too.
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
} }

View file

@ -62,7 +62,7 @@ func upgradeDeduplicateData(db ethdb.Database) func() error {
failed error failed error
) )
for failed == nil && it.Next() { for failed == nil && it.Next() {
// Skip any entries that don't look like old transaction meta entires (<hash>0x01) // Skip any entries that don't look like old transaction meta entries (<hash>0x01)
key := it.Key() key := it.Key()
if len(key) != common.HashLength+1 || key[common.HashLength] != 0x01 { if len(key) != common.HashLength+1 || key[common.HashLength] != 0x01 {
continue continue
@ -86,7 +86,7 @@ func upgradeDeduplicateData(db ethdb.Database) func() error {
} }
} }
// Convert the old metadata to a new lookup entry, delete duplicate data // Convert the old metadata to a new lookup entry, delete duplicate data
if failed = db.Put(append([]byte("l"), hash...), it.Value()); failed == nil { // Write the new looku entry if failed = db.Put(append([]byte("l"), hash...), it.Value()); failed == nil { // Write the new lookup entry
if failed = db.Delete(hash); failed == nil { // Delete the duplicate transaction data if failed = db.Delete(hash); failed == nil { // Delete the duplicate transaction data
if failed = db.Delete(append([]byte("receipts-"), hash...)); failed == nil { // Delete the duplicate receipt data if failed = db.Delete(append([]byte("receipts-"), hash...)); failed == nil { // Delete the duplicate receipt data
if failed = db.Delete(key); failed != nil { // Delete the old transaction metadata if failed = db.Delete(key); failed != nil { // Delete the old transaction metadata

View file

@ -47,7 +47,7 @@ var (
MaxForkAncestry = 3 * params.EpochDuration // Maximum chain reorganisation MaxForkAncestry = 3 * params.EpochDuration // Maximum chain reorganisation
rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests
rttMaxEstimate = 20 * time.Second // Maximum rount-trip time to target for download requests rttMaxEstimate = 20 * time.Second // Maximum round-trip time to target for download requests
rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value
ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion
ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts
@ -884,7 +884,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64)
// immediately to the header processor to keep the rest of the pipeline full even // immediately to the header processor to keep the rest of the pipeline full even
// in the case of header stalls. // in the case of header stalls.
// //
// The method returs the entire filled skeleton and also the number of headers // The method returns the entire filled skeleton and also the number of headers
// already forwarded for processing. // already forwarded for processing.
func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, int, error) { func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, int, error) {
log.Debug("Filling up skeleton", "from", from) log.Debug("Filling up skeleton", "from", from)
@ -1377,7 +1377,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
pivot = height - uint64(fsMinFullBlocks) pivot = height - uint64(fsMinFullBlocks)
} }
// To cater for moving pivot points, track the pivot block and subsequently // To cater for moving pivot points, track the pivot block and subsequently
// accumulated download results separatey. // accumulated download results separately.
var ( var (
oldPivot *fetchResult // Locked in pivot block, might change eventually oldPivot *fetchResult // Locked in pivot block, might change eventually
oldTail []*fetchResult // Downloaded content after the pivot oldTail []*fetchResult // Downloaded content after the pivot
@ -1615,7 +1615,7 @@ func (d *Downloader) qosReduceConfidence() {
// //
// Note, the returned RTT is .9 of the actually estimated RTT. The reason is that // Note, the returned RTT is .9 of the actually estimated RTT. The reason is that
// the downloader tries to adapt queries to the RTT, so multiple RTT values can // the downloader tries to adapt queries to the RTT, so multiple RTT values can
// be adapted to, but smaller ones are preffered (stabler download stream). // be adapted to, but smaller ones are preferred (stabler download stream).
func (d *Downloader) requestRTT() time.Duration { func (d *Downloader) requestRTT() time.Duration {
return time.Duration(atomic.LoadUint64(&d.rttEstimate)) * 9 / 10 return time.Duration(atomic.LoadUint64(&d.rttEstimate)) * 9 / 10
} }

View file

@ -159,7 +159,7 @@ func (dl *downloadTester) makeChainFork(n, f int, parent *types.Block, parentRec
// Create the common suffix // Create the common suffix
hashes, headers, blocks, receipts := dl.makeChain(n-f, 0, parent, parentReceipts, false) hashes, headers, blocks, receipts := dl.makeChain(n-f, 0, parent, parentReceipts, false)
// Create the forks, making the second heavyer if non balanced forks were requested // Create the forks, making the second heavier if non balanced forks were requested
hashes1, headers1, blocks1, receipts1 := dl.makeChain(f, 1, blocks[hashes[0]], receipts[hashes[0]], false) hashes1, headers1, blocks1, receipts1 := dl.makeChain(f, 1, blocks[hashes[0]], receipts[hashes[0]], false)
hashes1 = append(hashes1, hashes[1:]...) hashes1 = append(hashes1, hashes[1:]...)

View file

@ -27,7 +27,7 @@ import (
// FakePeer is a mock downloader peer that operates on a local database instance // FakePeer is a mock downloader peer that operates on a local database instance
// instead of being an actual live node. It's useful for testing and to implement // instead of being an actual live node. It's useful for testing and to implement
// sync commands from an xisting local database. // sync commands from an existing local database.
type FakePeer struct { type FakePeer struct {
id string id string
db ethdb.Database db ethdb.Database
@ -48,7 +48,7 @@ func (p *FakePeer) Head() (common.Hash, *big.Int) {
} }
// RequestHeadersByHash implements downloader.Peer, returning a batch of headers // RequestHeadersByHash implements downloader.Peer, returning a batch of headers
// defined by the origin hash and the associaed query parameters. // defined by the origin hash and the associated query parameters.
func (p *FakePeer) RequestHeadersByHash(hash common.Hash, amount int, skip int, reverse bool) error { func (p *FakePeer) RequestHeadersByHash(hash common.Hash, amount int, skip int, reverse bool) error {
var ( var (
headers []*types.Header headers []*types.Header
@ -92,7 +92,7 @@ func (p *FakePeer) RequestHeadersByHash(hash common.Hash, amount int, skip int,
} }
// RequestHeadersByNumber implements downloader.Peer, returning a batch of headers // RequestHeadersByNumber implements downloader.Peer, returning a batch of headers
// defined by the origin number and the associaed query parameters. // defined by the origin number and the associated query parameters.
func (p *FakePeer) RequestHeadersByNumber(number uint64, amount int, skip int, reverse bool) error { func (p *FakePeer) RequestHeadersByNumber(number uint64, amount int, skip int, reverse bool) error {
var ( var (
headers []*types.Header headers []*types.Header

View file

@ -551,7 +551,7 @@ func (ps *peerSet) idlePeers(minProtocol, maxProtocol int, idleCheck func(*peerC
// medianRTT returns the median RTT of the peerset, considering only the tuning // medianRTT returns the median RTT of the peerset, considering only the tuning
// peers if there are more peers available. // peers if there are more peers available.
func (ps *peerSet) medianRTT() time.Duration { func (ps *peerSet) medianRTT() time.Duration {
// Gather all the currnetly measured round trip times // Gather all the currently measured round trip times
ps.lock.RLock() ps.lock.RLock()
defer ps.lock.RUnlock() defer ps.lock.RUnlock()

View file

@ -275,7 +275,7 @@ func (q *queue) ScheduleSkeleton(from uint64, skeleton []*types.Header) {
if q.headerResults != nil { if q.headerResults != nil {
panic("skeleton assembly already in progress") panic("skeleton assembly already in progress")
} }
// Shedule all the header retrieval tasks for the skeleton assembly // Schedule all the header retrieval tasks for the skeleton assembly
q.headerTaskPool = make(map[uint64]*types.Header) q.headerTaskPool = make(map[uint64]*types.Header)
q.headerTaskQueue = prque.New() q.headerTaskQueue = prque.New()
q.headerPeerMiss = make(map[string]map[uint64]struct{}) // Reset availability to correct invalid chains q.headerPeerMiss = make(map[string]map[uint64]struct{}) // Reset availability to correct invalid chains

View file

@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
// stateReq represents a batch of state fetch requests groupped together into // stateReq represents a batch of state fetch requests grouped together into
// a single data retrieval network packet. // a single data retrieval network packet.
type stateReq struct { type stateReq struct {
items []common.Hash // Hashes of the state items to download items []common.Hash // Hashes of the state items to download
@ -139,7 +139,7 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
// Handle incoming state packs: // Handle incoming state packs:
case pack := <-d.stateCh: case pack := <-d.stateCh:
// Discard any data not requested (or previsouly timed out) // Discard any data not requested (or previously timed out)
req := active[pack.PeerId()] req := active[pack.PeerId()]
if req == nil { if req == nil {
log.Debug("Unrequested node data", "peer", pack.PeerId(), "len", pack.Items()) log.Debug("Unrequested node data", "peer", pack.PeerId(), "len", pack.Items())
@ -182,7 +182,7 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
case req := <-d.trackStateReq: case req := <-d.trackStateReq:
// If an active request already exists for this peer, we have a problem. In // If an active request already exists for this peer, we have a problem. In
// theory the trie node schedule must never assign two requests to the same // theory the trie node schedule must never assign two requests to the same
// peer. In practive however, a peer might receive a request, disconnect and // peer. In practice however, a peer might receive a request, disconnect and
// immediately reconnect before the previous times out. In this case the first // immediately reconnect before the previous times out. In this case the first
// request is never honored, alas we must not silently overwrite it, as that // request is never honored, alas we must not silently overwrite it, as that
// causes valid requests to go missing and sync to get stuck. // causes valid requests to go missing and sync to get stuck.
@ -228,7 +228,7 @@ type stateSync struct {
err error // Any error hit during sync (set before completion) err error // Any error hit during sync (set before completion)
} }
// stateTask represents a single trie node download taks, containing a set of // stateTask represents a single trie node download task, containing a set of
// peers already attempted retrieval from to detect stalled syncs and abort. // peers already attempted retrieval from to detect stalled syncs and abort.
type stateTask struct { type stateTask struct {
attempts map[string]struct{} attempts map[string]struct{}
@ -274,15 +274,21 @@ func (s *stateSync) Cancel() error {
// receive data from peers, rather those are buffered up in the downloader and // receive data from peers, rather those are buffered up in the downloader and
// pushed here async. The reason is to decouple processing from data receipt // pushed here async. The reason is to decouple processing from data receipt
// and timeouts. // and timeouts.
func (s *stateSync) loop() error { func (s *stateSync) loop() (err error) {
// Listen for new peer events to assign tasks to them // Listen for new peer events to assign tasks to them
newPeer := make(chan *peerConnection, 1024) newPeer := make(chan *peerConnection, 1024)
peerSub := s.d.peers.SubscribeNewPeers(newPeer) peerSub := s.d.peers.SubscribeNewPeers(newPeer)
defer peerSub.Unsubscribe() defer peerSub.Unsubscribe()
defer func() {
cerr := s.commit(true)
if err == nil {
err = cerr
}
}()
// Keep assigning new tasks until the sync completes or aborts // Keep assigning new tasks until the sync completes or aborts
for s.sched.Pending() > 0 { for s.sched.Pending() > 0 {
if err := s.commit(false); err != nil { if err = s.commit(false); err != nil {
return err return err
} }
s.assignTasks() s.assignTasks()
@ -307,14 +313,14 @@ func (s *stateSync) loop() error {
s.d.dropPeer(req.peer.id) s.d.dropPeer(req.peer.id)
} }
// Process all the received blobs and check for stale delivery // Process all the received blobs and check for stale delivery
if err := s.process(req); err != nil { if err = s.process(req); err != nil {
log.Warn("Node data write error", "err", err) log.Warn("Node data write error", "err", err)
return err return err
} }
req.peer.SetNodeDataIdle(len(req.response)) req.peer.SetNodeDataIdle(len(req.response))
} }
} }
return s.commit(true) return nil
} }
func (s *stateSync) commit(force bool) error { func (s *stateSync) commit(force bool) error {
@ -323,7 +329,9 @@ func (s *stateSync) commit(force bool) error {
} }
start := time.Now() start := time.Now()
b := s.d.stateDB.NewBatch() b := s.d.stateDB.NewBatch()
s.sched.Commit(b) if written, err := s.sched.Commit(b); written == 0 || err != nil {
return err
}
if err := b.Write(); err != nil { if err := b.Write(); err != nil {
return fmt.Errorf("DB write error: %v", err) return fmt.Errorf("DB write error: %v", err)
} }
@ -333,7 +341,7 @@ func (s *stateSync) commit(force bool) error {
return nil return nil
} }
// assignTasks attempts to assing new tasks to all idle peers, either from the // assignTasks attempts to assign new tasks to all idle peers, either from the
// batch currently being retried, or fetching new data from the trie sync itself. // batch currently being retried, or fetching new data from the trie sync itself.
func (s *stateSync) assignTasks() { func (s *stateSync) assignTasks() {
// Iterate over all idle peers and try to assign them state fetches // Iterate over all idle peers and try to assign them state fetches

View file

@ -127,7 +127,7 @@ type Fetcher struct {
// Block cache // Block cache
queue *prque.Prque // Queue containing the import operations (block number sorted) queue *prque.Prque // Queue containing the import operations (block number sorted)
queues map[string]int // Per peer block counts to prevent memory exhaustion queues map[string]int // Per peer block counts to prevent memory exhaustion
queued map[common.Hash]*inject // Set of already queued blocks (to dedup imports) queued map[common.Hash]*inject // Set of already queued blocks (to dedupe imports)
// Callbacks // Callbacks
getBlock blockRetrievalFn // Retrieves a block from the local chain getBlock blockRetrievalFn // Retrieves a block from the local chain

View file

@ -98,7 +98,7 @@ func (api *PublicFilterAPI) timeoutLoop() {
// NewPendingTransactionFilter creates a filter that fetches pending transaction hashes // NewPendingTransactionFilter creates a filter that fetches pending transaction hashes
// as transactions enter the pending state. // as transactions enter the pending state.
// //
// It is part of the filter package because this filter can be used throug the // It is part of the filter package because this filter can be used through the
// `eth_getFilterChanges` polling method that is also used for log filters. // `eth_getFilterChanges` polling method that is also used for log filters.
// //
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter

View file

@ -29,8 +29,8 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) {
var ( var (
fromBlock rpc.BlockNumber = 0x123435 fromBlock rpc.BlockNumber = 0x123435
toBlock rpc.BlockNumber = 0xabcdef toBlock rpc.BlockNumber = 0xabcdef
address0 = common.StringToAddress("70c87d191324e6712a591f304b4eedef6ad9bb9d") address0 = common.HexToAddress("70c87d191324e6712a591f304b4eedef6ad9bb9d")
address1 = common.StringToAddress("9b2055d370f73ec7d8a03e965129118dc8f5bf83") address1 = common.HexToAddress("9b2055d370f73ec7d8a03e965129118dc8f5bf83")
topic0 = common.HexToHash("3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1ca") topic0 = common.HexToHash("3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1ca")
topic1 = common.HexToHash("9084a792d2f8b16a62b882fd56f7860c07bf5fa91dd8a2ae7e809e5180fef0b3") topic1 = common.HexToHash("9084a792d2f8b16a62b882fd56f7860c07bf5fa91dd8a2ae7e809e5180fef0b3")
topic2 = common.HexToHash("6ccae1c4af4152f460ff510e573399795dfab5dcf1fa60d1f33ac8fdc1e480ce") topic2 = common.HexToHash("6ccae1c4af4152f460ff510e573399795dfab5dcf1fa60d1f33ac8fdc1e480ce")

View file

@ -96,8 +96,8 @@ type ProtocolManager struct {
wg sync.WaitGroup wg sync.WaitGroup
} }
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the ethereum network. // with the Ethereum network.
func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
// Create the protocol manager with the base fields // Create the protocol manager with the base fields
manager := &ProtocolManager{ manager := &ProtocolManager{
@ -498,20 +498,20 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return errResp(ErrDecode, "msg %v: %v", msg, err) return errResp(ErrDecode, "msg %v: %v", msg, err)
} }
// Deliver them all to the downloader for queuing // Deliver them all to the downloader for queuing
trasactions := make([][]*types.Transaction, len(request)) transactions := make([][]*types.Transaction, len(request))
uncles := make([][]*types.Header, len(request)) uncles := make([][]*types.Header, len(request))
for i, body := range request { for i, body := range request {
trasactions[i] = body.Transactions transactions[i] = body.Transactions
uncles[i] = body.Uncles uncles[i] = body.Uncles
} }
// Filter out any explicitly requested bodies, deliver the rest to the downloader // Filter out any explicitly requested bodies, deliver the rest to the downloader
filter := len(trasactions) > 0 || len(uncles) > 0 filter := len(transactions) > 0 || len(uncles) > 0
if filter { if filter {
trasactions, uncles = pm.fetcher.FilterBodies(p.id, trasactions, uncles, time.Now()) transactions, uncles = pm.fetcher.FilterBodies(p.id, transactions, uncles, time.Now())
} }
if len(trasactions) > 0 || len(uncles) > 0 || !filter { if len(transactions) > 0 || len(uncles) > 0 || !filter {
err := pm.downloader.DeliverBodies(p.id, trasactions, uncles) err := pm.downloader.DeliverBodies(p.id, transactions, uncles)
if err != nil { if err != nil {
log.Debug("Failed to deliver bodies", "err", err) log.Debug("Failed to deliver bodies", "err", err)
} }

View file

@ -296,7 +296,7 @@ func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, err
// SubscribeNewHead subscribes to notifications about the current blockchain head // SubscribeNewHead subscribes to notifications about the current blockchain head
// on the given channel. // on the given channel.
func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
return ec.c.EthSubscribe(ctx, ch, "newHeads", map[string]struct{}{}) return ec.c.EthSubscribe(ctx, ch, "newHeads")
} }
// State Access // State Access

View file

@ -91,9 +91,6 @@ func (db *LDBDatabase) Path() string {
// Put puts the given key / value to the queue // Put puts the given key / value to the queue
func (db *LDBDatabase) Put(key []byte, value []byte) error { func (db *LDBDatabase) Put(key []byte, value []byte) error {
// Generate the data to write to disk, update the meter and write
//value = rle.Compress(value)
return db.db.Put(key, value, nil) return db.db.Put(key, value, nil)
} }
@ -103,18 +100,15 @@ func (db *LDBDatabase) Has(key []byte) (bool, error) {
// Get returns the given key if it's present. // Get returns the given key if it's present.
func (db *LDBDatabase) Get(key []byte) ([]byte, error) { func (db *LDBDatabase) Get(key []byte) ([]byte, error) {
// Retrieve the key and increment the miss counter if not found
dat, err := db.db.Get(key, nil) dat, err := db.db.Get(key, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return dat, nil return dat, nil
//return rle.Decompress(dat)
} }
// Delete deletes the key from the queue and database // Delete deletes the key from the queue and database
func (db *LDBDatabase) Delete(key []byte) error { func (db *LDBDatabase) Delete(key []byte) error {
// Execute the actual operation
return db.db.Delete(key, nil) return db.db.Delete(key, nil)
} }

View file

@ -25,6 +25,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -1388,7 +1389,7 @@ func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (strin
if block == nil { if block == nil {
return "", fmt.Errorf("block #%d not found", number) return "", fmt.Errorf("block #%d not found", number)
} }
return block.String(), nil return spew.Sdump(block), nil
} }
// SeedHash retrieves the seed hash of a block. // SeedHash retrieves the seed hash of a block.

View file

@ -97,12 +97,6 @@ func (h *Header) EncodeJSON() (string, error) {
return string(data), err return string(data), err
} }
// String implements the fmt.Stringer interface to print some semi-meaningful
// data dump of the header for debugging purposes.
func (h *Header) String() string {
return h.header.String()
}
func (h *Header) GetParentHash() *Hash { return &Hash{h.header.ParentHash} } func (h *Header) GetParentHash() *Hash { return &Hash{h.header.ParentHash} }
func (h *Header) GetUncleHash() *Hash { return &Hash{h.header.UncleHash} } func (h *Header) GetUncleHash() *Hash { return &Hash{h.header.UncleHash} }
func (h *Header) GetCoinbase() *Address { return &Address{h.header.Coinbase} } func (h *Header) GetCoinbase() *Address { return &Address{h.header.Coinbase} }
@ -174,12 +168,6 @@ func (b *Block) EncodeJSON() (string, error) {
return string(data), err return string(data), err
} }
// String implements the fmt.Stringer interface to print some semi-meaningful
// data dump of the block for debugging purposes.
func (b *Block) String() string {
return b.block.String()
}
func (b *Block) GetParentHash() *Hash { return &Hash{b.block.ParentHash()} } func (b *Block) GetParentHash() *Hash { return &Hash{b.block.ParentHash()} }
func (b *Block) GetUncleHash() *Hash { return &Hash{b.block.UncleHash()} } func (b *Block) GetUncleHash() *Hash { return &Hash{b.block.UncleHash()} }
func (b *Block) GetCoinbase() *Address { return &Address{b.block.Coinbase()} } func (b *Block) GetCoinbase() *Address { return &Address{b.block.Coinbase()} }
@ -249,12 +237,6 @@ func (tx *Transaction) EncodeJSON() (string, error) {
return string(data), err return string(data), err
} }
// String implements the fmt.Stringer interface to print some semi-meaningful
// data dump of the transaction for debugging purposes.
func (tx *Transaction) String() string {
return tx.tx.String()
}
func (tx *Transaction) GetData() []byte { return tx.tx.Data() } func (tx *Transaction) GetData() []byte { return tx.tx.Data() }
func (tx *Transaction) GetGas() int64 { return int64(tx.tx.Gas()) } func (tx *Transaction) GetGas() int64 { return int64(tx.tx.Gas()) }
func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} } func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} }
@ -347,12 +329,6 @@ func (r *Receipt) EncodeJSON() (string, error) {
return string(data), err return string(data), err
} }
// String implements the fmt.Stringer interface to print some semi-meaningful
// data dump of the transaction receipt for debugging purposes.
func (r *Receipt) String() string {
return r.receipt.String()
}
func (r *Receipt) GetPostState() []byte { return r.receipt.PostState } func (r *Receipt) GetPostState() []byte { return r.receipt.PostState }
func (r *Receipt) GetCumulativeGasUsed() int64 { return int64(r.receipt.CumulativeGasUsed) } func (r *Receipt) GetCumulativeGasUsed() int64 { return int64(r.receipt.CumulativeGasUsed) }
func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} } func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} }

View file

@ -22,7 +22,6 @@ package storage
import ( import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/compression/rle"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/iterator" "github.com/syndtr/goleveldb/leveldb/iterator"
"github.com/syndtr/goleveldb/leveldb/opt" "github.com/syndtr/goleveldb/leveldb/opt"
@ -31,8 +30,7 @@ import (
const openFileLimit = 128 const openFileLimit = 128
type LDBDatabase struct { type LDBDatabase struct {
db *leveldb.DB db *leveldb.DB
comp bool
} }
func NewLDBDatabase(file string) (*LDBDatabase, error) { func NewLDBDatabase(file string) (*LDBDatabase, error) {
@ -42,16 +40,12 @@ func NewLDBDatabase(file string) (*LDBDatabase, error) {
return nil, err return nil, err
} }
database := &LDBDatabase{db: db, comp: false} database := &LDBDatabase{db: db}
return database, nil return database, nil
} }
func (self *LDBDatabase) Put(key []byte, value []byte) { func (self *LDBDatabase) Put(key []byte, value []byte) {
if self.comp {
value = rle.Compress(value)
}
err := self.db.Put(key, value, nil) err := self.db.Put(key, value, nil)
if err != nil { if err != nil {
fmt.Println("Error put", err) fmt.Println("Error put", err)
@ -63,11 +57,6 @@ func (self *LDBDatabase) Get(key []byte) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if self.comp {
return rle.Decompress(dat)
}
return dat, nil return dat, nil
} }

View file

@ -36,14 +36,7 @@ func TestState(t *testing.T) {
st.skipLoad(`^stTransactionTest/zeroSigTransa[^/]*\.json`) // EIP-86 is not supported yet st.skipLoad(`^stTransactionTest/zeroSigTransa[^/]*\.json`) // EIP-86 is not supported yet
// Expected failures: // Expected failures:
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/EIP158`, "bug in test") st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/EIP158`, "bug in test")
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/EIP158`, "bug in test")
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test") st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/Byzantium`, "bug in test")
st.fails(`^stRandom2/randomStatetest64[45]\.json/(EIP150|Frontier|Homestead)/.*`, "known bug #15119")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/EIP158/2`, "known bug ")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/EIP158/3`, "known bug ")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/Byzantium/2`, "known bug ")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/Byzantium/3`, "known bug ")
st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) { st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) {
for _, subtest := range test.Subtests() { for _, subtest := range test.Subtests() {

View file

@ -212,7 +212,7 @@ func (s *TrieSync) Process(results []SyncResult) (bool, int, error) {
} }
// Commit flushes the data stored in the internal membatch out to persistent // Commit flushes the data stored in the internal membatch out to persistent
// storage, returning th enumber of items written and any occurred error. // storage, returning the number of items written and any occurred error.
func (s *TrieSync) Commit(dbw ethdb.Putter) (int, error) { func (s *TrieSync) Commit(dbw ethdb.Putter) (int, error) {
// Dump the membatch into a database dbw // Dump the membatch into a database dbw
for i, key := range s.membatch.order { for i, key := range s.membatch.order {