diff --git a/.gitattributes b/.gitattributes index dfe0770424..0269fab9cb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ # Auto detect text files and perform LF normalization * text=auto +*.sol linguist-language=Solidity diff --git a/Dockerfile b/Dockerfile index 29cdc80f96..a5f450d19b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,5 +12,11 @@ FROM alpine:latest RUN apk add --no-cache ca-certificates 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 ENTRYPOINT ["geth"] diff --git a/Dockerfile.alltools b/Dockerfile.alltools index 1047738d25..2175edbcb7 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -12,4 +12,10 @@ FROM alpine:latest RUN apk add --no-cache ca-certificates 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 diff --git a/VERSION b/VERSION index a7ee35a3ea..bfa363e76e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.8.3 +1.8.4 diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go index 9ad99f90d2..0cd97cc66f 100644 --- a/accounts/abi/numbers.go +++ b/accounts/abi/numbers.go @@ -25,23 +25,23 @@ import ( ) var ( - big_t = reflect.TypeOf(&big.Int{}) - derefbig_t = reflect.TypeOf(big.Int{}) - uint8_t = reflect.TypeOf(uint8(0)) - uint16_t = reflect.TypeOf(uint16(0)) - uint32_t = reflect.TypeOf(uint32(0)) - uint64_t = reflect.TypeOf(uint64(0)) - int_t = reflect.TypeOf(int(0)) - int8_t = reflect.TypeOf(int8(0)) - int16_t = reflect.TypeOf(int16(0)) - int32_t = reflect.TypeOf(int32(0)) - int64_t = reflect.TypeOf(int64(0)) - address_t = reflect.TypeOf(common.Address{}) - int_ts = reflect.TypeOf([]int(nil)) - int8_ts = reflect.TypeOf([]int8(nil)) - int16_ts = reflect.TypeOf([]int16(nil)) - int32_ts = reflect.TypeOf([]int32(nil)) - int64_ts = reflect.TypeOf([]int64(nil)) + bigT = reflect.TypeOf(&big.Int{}) + derefbigT = reflect.TypeOf(big.Int{}) + uint8T = reflect.TypeOf(uint8(0)) + uint16T = reflect.TypeOf(uint16(0)) + uint32T = reflect.TypeOf(uint32(0)) + uint64T = reflect.TypeOf(uint64(0)) + intT = reflect.TypeOf(int(0)) + int8T = reflect.TypeOf(int8(0)) + int16T = reflect.TypeOf(int16(0)) + int32T = reflect.TypeOf(int32(0)) + int64T = reflect.TypeOf(int64(0)) + addressT = reflect.TypeOf(common.Address{}) + intTS = reflect.TypeOf([]int(nil)) + int8TS = reflect.TypeOf([]int8(nil)) + int16TS = reflect.TypeOf([]int16(nil)) + int32TS = reflect.TypeOf([]int32(nil)) + int64TS = reflect.TypeOf([]int64(nil)) ) // 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 func isSigned(v reflect.Value) bool { 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 false diff --git a/accounts/abi/reflect.go b/accounts/abi/reflect.go index 2e6bf7098f..5620a70845 100644 --- a/accounts/abi/reflect.go +++ b/accounts/abi/reflect.go @@ -24,7 +24,7 @@ import ( // indirect recursively dereferences the value until it either gets the value // or finds a big.Int 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 v @@ -36,26 +36,26 @@ func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) switch size { case 8: if unsigned { - return reflect.Uint8, uint8_t + return reflect.Uint8, uint8T } - return reflect.Int8, int8_t + return reflect.Int8, int8T case 16: if unsigned { - return reflect.Uint16, uint16_t + return reflect.Uint16, uint16T } - return reflect.Int16, int16_t + return reflect.Int16, int16T case 32: if unsigned { - return reflect.Uint32, uint32_t + return reflect.Uint32, uint32T } - return reflect.Int32, int32_t + return reflect.Int32, int32T case 64: 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 diff --git a/accounts/abi/type.go b/accounts/abi/type.go index a1f13ffa29..9de36daffb 100644 --- a/accounts/abi/type.go +++ b/accounts/abi/type.go @@ -135,7 +135,7 @@ func NewType(t string) (typ Type, err error) { typ.Type = reflect.TypeOf(bool(false)) case "address": typ.Kind = reflect.Array - typ.Type = address_t + typ.Type = addressT typ.Size = 20 typ.T = AddressTy case "string": diff --git a/accounts/abi/type_test.go b/accounts/abi/type_test.go index e55af12939..f6b36f18fd 100644 --- a/accounts/abi/type_test.go +++ b/accounts/abi/type_test.go @@ -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[][][]", 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][]"}}, - {"int8", Type{Kind: reflect.Int8, Type: int8_t, Size: 8, T: IntTy, stringKind: "int8"}}, - {"int16", Type{Kind: reflect.Int16, Type: int16_t, Size: 16, T: IntTy, stringKind: "int16"}}, - {"int32", Type{Kind: reflect.Int32, Type: int32_t, Size: 32, T: IntTy, stringKind: "int32"}}, - {"int64", Type{Kind: reflect.Int64, Type: int64_t, Size: 64, T: IntTy, stringKind: "int64"}}, - {"int256", Type{Kind: reflect.Ptr, Type: big_t, 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[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]"}}, - {"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[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]"}}, - {"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[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]"}}, - {"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[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]"}}, - {"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[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]"}}, - {"uint8", Type{Kind: reflect.Uint8, Type: uint8_t, Size: 8, T: UintTy, stringKind: "uint8"}}, - {"uint16", Type{Kind: reflect.Uint16, Type: uint16_t, Size: 16, T: UintTy, stringKind: "uint16"}}, - {"uint32", Type{Kind: reflect.Uint32, Type: uint32_t, Size: 32, T: UintTy, stringKind: "uint32"}}, - {"uint64", Type{Kind: reflect.Uint64, Type: uint64_t, Size: 64, T: UintTy, stringKind: "uint64"}}, - {"uint256", Type{Kind: reflect.Ptr, Type: big_t, 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[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]"}}, - {"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[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]"}}, - {"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[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]"}}, - {"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[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]"}}, - {"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[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]"}}, + {"int8", Type{Kind: reflect.Int8, Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}}, + {"int16", Type{Kind: reflect.Int16, Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}}, + {"int32", Type{Kind: reflect.Int32, Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}}, + {"int64", Type{Kind: reflect.Int64, Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}}, + {"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: 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: 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: 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: 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: 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: 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: 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: 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: 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: bigT, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}}, + {"uint8", Type{Kind: reflect.Uint8, Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}}, + {"uint16", Type{Kind: reflect.Uint16, Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}}, + {"uint32", Type{Kind: reflect.Uint32, Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}}, + {"uint64", Type{Kind: reflect.Uint64, Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}}, + {"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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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"}}, {"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]"}}, @@ -84,9 +84,9 @@ func TestTypeRegexp(t *testing.T) { {"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[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{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[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", 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: 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: addressT, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}}, // TODO when fixed types are implemented properly // {"fixed", Type{}}, // {"fixed128x128", Type{}}, @@ -252,6 +252,9 @@ func TestTypeCheck(t *testing.T) { {"bytes20", common.Address{}, ""}, {"address", [20]byte{}, ""}, {"address", common.Address{}, ""}, + {"bytes32[]]", "", "invalid arg type in abi"}, + {"invalidType", "", "unsupported arg type: invalidType"}, + {"invalidSlice[]", "", "unsupported arg type: invalidSlice"}, } { typ, err := NewType(test.typ) if err != nil && len(test.err) == 0 { diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index ee62567094..bdbab10b4f 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -56,6 +56,23 @@ var unpackTests = []unpackTest{ enc: "0000000000000000000000000000000000000000000000000000000000000001", 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"}]`, enc: "0000000000000000000000000000000000000000000000000000000000000001", diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 8a7399840c..c13e9fb335 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -76,6 +76,7 @@ func runCmd(ctx *cli.Context) error { logconfig := &vm.LogConfig{ DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), DisableStack: ctx.GlobalBool(DisableStackFlag.Name), + Debug: ctx.GlobalBool(DebugFlag.Name), } var ( @@ -234,9 +235,7 @@ Gas used: %d `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) } - if tracer != nil { - tracer.CaptureEnd(ret, initialGas-leftOverGas, execTime, err) - } else { + if tracer == nil { fmt.Printf("0x%x\n", ret) if err != nil { fmt.Printf(" error: %v\n", err) diff --git a/cmd/geth/bugcmd.go b/cmd/geth/bugcmd.go index ce9dbe6c0a..51187ac90e 100644 --- a/cmd/geth/bugcmd.go +++ b/cmd/geth/bugcmd.go @@ -49,15 +49,17 @@ func reportBug(ctx *cli.Context) error { // execute template and write contents to buff 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, "Go Version:", runtime.Version()) fmt.Fprintln(&buff, "OS:", runtime.GOOS) printOSDetails(&buff) + fmt.Fprintln(&buff, header) // open a new GH issue 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 } @@ -97,13 +99,15 @@ func printCmdOut(w io.Writer, prefix, path string, args ...string) { 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? - -#### What did you see instead? - -#### System details + +#### Actual behaviour + + +#### Steps to reproduce the behaviour + + +#### Backtrace ` diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index c9ab72b6df..d3086921b9 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -95,6 +95,34 @@ Requires a first argument of the file to write to. Optional second and third arguments control the first and last block to write. In this mode, the file will be appended if already existing.`, + } + importPreimagesCommand = cli.Command{ + Action: utils.MigrateFlags(importPreimages), + Name: "import-preimages", + Usage: "Import the preimage database from an RLP stream", + ArgsUsage: "", + Flags: []cli.Flag{ + utils.DataDirFlag, + utils.CacheFlag, + utils.LightModeFlag, + }, + Category: "BLOCKCHAIN COMMANDS", + Description: ` + The import-preimages command imports hash preimages from an RLP encoded stream.`, + } + exportPreimagesCommand = cli.Command{ + Action: utils.MigrateFlags(exportPreimages), + Name: "export-preimages", + Usage: "Export the preimage database into an RLP stream", + ArgsUsage: "", + Flags: []cli.Flag{ + utils.DataDirFlag, + utils.CacheFlag, + utils.LightModeFlag, + }, + Category: "BLOCKCHAIN COMMANDS", + Description: ` +The export-preimages command export hash preimages to an RLP encoded stream`, } copydbCommand = cli.Command{ Action: utils.MigrateFlags(copyDb), @@ -299,7 +327,39 @@ func exportChain(ctx *cli.Context) error { if err != nil { utils.Fatalf("Export error: %v\n", err) } - fmt.Printf("Export done in %v", time.Since(start)) + fmt.Printf("Export done in %v\n", time.Since(start)) + return nil +} + +// importPreimages imports preimage data from the specified file. +func importPreimages(ctx *cli.Context) error { + if len(ctx.Args()) < 1 { + utils.Fatalf("This command requires an argument.") + } + stack := makeFullNode(ctx) + diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase) + + start := time.Now() + if err := utils.ImportPreimages(diskdb, ctx.Args().First()); err != nil { + utils.Fatalf("Export error: %v\n", err) + } + fmt.Printf("Export done in %v\n", time.Since(start)) + return nil +} + +// exportPreimages dumps the preimage data to specified json file in streaming way. +func exportPreimages(ctx *cli.Context) error { + if len(ctx.Args()) < 1 { + utils.Fatalf("This command requires an argument.") + } + stack := makeFullNode(ctx) + diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase) + + start := time.Now() + if err := utils.ExportPreimages(diskdb, ctx.Args().First()); err != nil { + utils.Fatalf("Export error: %v\n", err) + } + fmt.Printf("Export done in %v\n", time.Since(start)) return nil } diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 50e4de2e78..e6bd4d5bef 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -32,7 +32,7 @@ import ( "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" - whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" + whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" "github.com/naoina/toml" ) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index c8e786be76..99cdcb9f3c 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethclient" @@ -46,8 +45,6 @@ const ( var ( // Git SHA1 commit hash of the release (set via linker flags) gitCommit = "" - // Ethereum address of the Geth release oracle. - relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf") // The app that holds all commands and flags. app = utils.NewApp(gitCommit, "the go-ethereum command line interface") // flags that configure the node @@ -156,6 +153,8 @@ func init() { initCommand, importCommand, exportCommand, + importPreimagesCommand, + exportPreimagesCommand, copydbCommand, removedbCommand, dumpCommand, diff --git a/cmd/puppeth/puppeth.go b/cmd/puppeth/puppeth.go index 26382dac13..f9b8fe4811 100644 --- a/cmd/puppeth/puppeth.go +++ b/cmd/puppeth/puppeth.go @@ -20,6 +20,7 @@ package main import ( "math/rand" "os" + "strings" "time" "github.com/ethereum/go-ethereum/log" @@ -34,7 +35,7 @@ func main() { app.Flags = []cli.Flag{ cli.StringFlag{ Name: "network", - Usage: "name of the network to administer", + Usage: "name of the network to administer (no spaces or hyphens, please)", }, cli.IntFlag{ Name: "loglevel", @@ -47,6 +48,10 @@ func main() { log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(os.Stdout, log.TerminalFormat(true)))) rand.Seed(time.Now().UnixNano()) + network := c.String("network") + if strings.Contains(network, " ") || strings.Contains(network, "-") { + log.Crit("No spaces or hyphens allowed in network name") + } // Start the wizard and relinquish control makeWizard(c.String("network")).run() return nil diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 186d18d8f5..c0af4c13e7 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -27,8 +27,11 @@ import ( "strings" "syscall" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" @@ -105,6 +108,8 @@ func ImportChain(chain *core.BlockChain, fn string) error { } log.Info("Importing blockchain", "file", fn) + + // Open the file handle and potentially unwrap the gzip stream fh, err := os.Open(fn) if err != nil { return err @@ -180,8 +185,12 @@ func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block return nil } +// ExportChain exports a blockchain into the specified file, truncating any data +// already present in the file. func ExportChain(blockchain *core.BlockChain, fn string) error { log.Info("Exporting blockchain", "file", fn) + + // Open the file handle and potentially wrap with a gzip stream fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) if err != nil { return err @@ -193,7 +202,7 @@ func ExportChain(blockchain *core.BlockChain, fn string) error { writer = gzip.NewWriter(writer) defer writer.(*gzip.Writer).Close() } - + // Iterate over the blocks and export them if err := blockchain.Export(writer); err != nil { return err } @@ -202,9 +211,12 @@ func ExportChain(blockchain *core.BlockChain, fn string) error { return nil } +// ExportAppendChain exports a blockchain into the specified file, appending to +// the file if data already exists in it. func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error { log.Info("Exporting blockchain", "file", fn) - // TODO verify mode perms + + // Open the file handle and potentially wrap with a gzip stream fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm) if err != nil { return err @@ -216,10 +228,86 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las writer = gzip.NewWriter(writer) defer writer.(*gzip.Writer).Close() } - + // Iterate over the blocks and export them if err := blockchain.ExportN(writer, first, last); err != nil { return err } log.Info("Exported blockchain to", "file", fn) return nil } + +// ImportPreimages imports a batch of exported hash preimages into the database. +func ImportPreimages(db *ethdb.LDBDatabase, fn string) error { + log.Info("Importing preimages", "file", fn) + + // Open the file handle and potentially unwrap the gzip stream + fh, err := os.Open(fn) + if err != nil { + return err + } + defer fh.Close() + + var reader io.Reader = fh + if strings.HasSuffix(fn, ".gz") { + if reader, err = gzip.NewReader(reader); err != nil { + return err + } + } + stream := rlp.NewStream(reader, 0) + + // Import the preimages in batches to prevent disk trashing + preimages := make(map[common.Hash][]byte) + + for { + // Read the next entry and ensure it's not junk + var blob []byte + + if err := stream.Decode(&blob); err != nil { + if err == io.EOF { + break + } + return err + } + // Accumulate the preimages and flush when enough ws gathered + preimages[crypto.Keccak256Hash(blob)] = common.CopyBytes(blob) + if len(preimages) > 1024 { + if err := core.WritePreimages(db, 0, preimages); err != nil { + return err + } + preimages = make(map[common.Hash][]byte) + } + } + // Flush the last batch preimage data + if len(preimages) > 0 { + return core.WritePreimages(db, 0, preimages) + } + return nil +} + +// ExportPreimages exports all known hash preimages into the specified file, +// truncating any data already present in the file. +func ExportPreimages(db *ethdb.LDBDatabase, fn string) error { + log.Info("Exporting preimages", "file", fn) + + // Open the file handle and potentially wrap with a gzip stream + fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) + if err != nil { + return err + } + defer fh.Close() + + var writer io.Writer = fh + if strings.HasSuffix(fn, ".gz") { + writer = gzip.NewWriter(writer) + defer writer.(*gzip.Writer).Close() + } + // Iterate over the preimages and export them + it := db.NewIteratorWithPrefix([]byte("secure-key-")) + for it.Next() { + if err := rlp.Encode(writer, it.Value()); err != nil { + return err + } + } + log.Info("Exported preimages", "file", fn) + return nil +} diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 51be23e3cb..132d51d611 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -55,7 +55,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/params" - whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" + whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" "gopkg.in/urfave/cli.v1" ) diff --git a/core/asm/compiler.go b/core/asm/compiler.go index 1b9025a549..18dc0877ff 100644 --- a/core/asm/compiler.go +++ b/core/asm/compiler.go @@ -114,7 +114,7 @@ func (c *Compiler) Compile() (string, []error) { } // next returns the next token and increments the -// posititon. +// position. func (c *Compiler) next() token { token := c.tokens[c.pos] c.pos++ diff --git a/core/database_util_test.go b/core/database_util_test.go index ab4e45a478..aa87fa6f86 100644 --- a/core/database_util_test.go +++ b/core/database_util_test.go @@ -317,7 +317,7 @@ func TestLookupStorage(t *testing.T) { 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) } - 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) } } diff --git a/core/evm.go b/core/evm.go index 55db53927b..596ea95fb7 100644 --- a/core/evm.go +++ b/core/evm.go @@ -60,13 +60,26 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author // GetHashFn returns a GetHashFunc which retrieves header hashes by number func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash { + var cache map[uint64]common.Hash + return func(n uint64) common.Hash { - for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { - if header.Number.Uint64() == n { - return header.Hash() + // If there's no hash cache yet, make one + if cache == nil { + cache = map[uint64]common.Hash{ + ref.Number.Uint64() - 1: ref.ParentHash, + } + } + // Try to fulfill the request from the cache + if hash, ok := cache[n]; ok { + return hash + } + // Not cached, iterate the blocks and cache the hashes + for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { + cache[header.Number.Uint64()-1] = header.ParentHash + if n == header.Number.Uint64()-1 { + return header.ParentHash } } - return common.Hash{} } } diff --git a/core/headerchain.go b/core/headerchain.go index 73cd5d2c41..2d1b0a2a18 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -23,6 +23,7 @@ import ( "math" "math/big" mrand "math/rand" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" @@ -32,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/hashicorp/golang-lru" - "sync/atomic" ) const ( diff --git a/core/state/database.go b/core/state/database.go index 36926ec69d..c1b630991c 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -26,7 +26,7 @@ import ( 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) const ( @@ -151,9 +151,6 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro return cached.(int), nil } code, err := db.ContractCode(addrHash, codeHash) - if err == nil { - db.codeSizeCache.Add(codeHash, len(code)) - } return len(code), err } diff --git a/core/state/statedb.go b/core/state/statedb.go index 776693e248..bd67e789d5 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -83,7 +83,7 @@ type StateDB struct { lock sync.Mutex } -// Create a new state from a given trie +// Create a new state from a given trie. func New(root common.Hash, db Database) (*StateDB, error) { tr, err := db.OpenTrie(root) if err != nil { @@ -110,7 +110,7 @@ func (self *StateDB) Error() error { return self.dbErr } -// Reset clears out all emphemeral state objects from the state db, but keeps +// Reset clears out all ephemeral state objects from the state db, but keeps // the underlying state trie to avoid reloading data for the next operations. func (self *StateDB) Reset(root common.Hash) error { tr, err := self.db.OpenTrie(root) @@ -235,10 +235,10 @@ func (self *StateDB) GetCodeHash(addr common.Address) common.Hash { return common.BytesToHash(stateObject.CodeHash()) } -func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { - stateObject := self.getStateObject(a) +func (self *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash { + stateObject := self.getStateObject(addr) if stateObject != nil { - return stateObject.GetState(self.db, b) + return stateObject.GetState(self.db, bhash) } return common.Hash{} } @@ -250,8 +250,8 @@ func (self *StateDB) Database() Database { // StorageTrie returns the storage trie of an account. // The return value is a copy and is nil for non-existent accounts. -func (self *StateDB) StorageTrie(a common.Address) Trie { - stateObject := self.getStateObject(a) +func (self *StateDB) StorageTrie(addr common.Address) Trie { + stateObject := self.getStateObject(addr) if stateObject == nil { return nil } @@ -271,7 +271,7 @@ func (self *StateDB) HasSuicided(addr common.Address) bool { * 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) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { @@ -279,7 +279,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) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { @@ -308,7 +308,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) if stateObject != nil { stateObject.SetState(self.db, key, value) @@ -337,7 +337,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. @@ -388,7 +388,7 @@ func (self *StateDB) setStateObject(object *stateObject) { 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 { stateObject := self.getStateObject(addr) if stateObject == nil || stateObject.deleted { diff --git a/core/types/block.go b/core/types/block.go index 92b868d9da..ae1b4299d3 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -19,7 +19,6 @@ package types import ( "encoding/binary" - "fmt" "io" "math/big" "sort" @@ -389,40 +388,6 @@ func (b *Block) Hash() common.Hash { 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 BlockBy func(b1, b2 *Block) bool diff --git a/core/types/log.go b/core/types/log.go index be5de38da7..b629b47ed5 100644 --- a/core/types/log.go +++ b/core/types/log.go @@ -17,7 +17,6 @@ package types import ( - "fmt" "io" "github.com/ethereum/go-ethereum/common" @@ -95,10 +94,6 @@ func (l *Log) DecodeRLP(s *rlp.Stream) error { 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 // a log including non-consensus fields. type LogForStorage Log diff --git a/core/types/receipt.go b/core/types/receipt.go index f945f6f6a2..613f03d50f 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -149,14 +149,6 @@ func (r *Receipt) Size() common.StorageSize { 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 // entire content of a receipt, as opposed to only the consensus fields originally. type ReceiptForStorage Receipt diff --git a/core/types/transaction.go b/core/types/transaction.go index 5660582baf..70d757c94e 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -19,7 +19,6 @@ package types import ( "container/heap" "errors" - "fmt" "io" "math/big" "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 } -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. type Transactions []*Transaction diff --git a/core/vm/doc.go b/core/vm/doc.go index 239be2cfec..5864d0cfa2 100644 --- a/core/vm/doc.go +++ b/core/vm/doc.go @@ -17,19 +17,8 @@ /* Package vm implements the Ethereum Virtual Machine. -The vm package implements two EVMs, a byte code VM and a JIT VM. The BC -(Byte Code) VM loops over a set of bytes and executes them according to the set -of rules defined in the Ethereum yellow paper. When the BC VM is invoked it -invokes the JIT VM in a separate goroutine and compiles the byte code in JIT -instructions. - -The JIT VM, when invoked, loops around a set of pre-defined instructions until -it either runs of gas, causes an internal error, returns or stops. - -The JIT optimiser attempts to pre-compile instructions in to chunks or segments -such as multiple PUSH operations and static JUMPs. It does this by analysing the -opcodes and attempts to match certain regions to known sets. Whenever the -optimiser finds said segments it creates a new instruction and replaces the -first occurrence in the sequence. +The vm package implements one EVM, a byte code VM. The BC (Byte Code) VM loops +over a set of bytes and executes them according to the set of rules defined +in the Ethereum yellow paper. */ package vm diff --git a/core/vm/evm.go b/core/vm/evm.go index 46e7baff4c..96676c314a 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -111,7 +111,7 @@ type EVM struct { callGasTemp uint64 } -// NewEVM retutrns a new EVM . The returned EVM is not thread safe and should +// NewEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { evm := &EVM{ @@ -221,7 +221,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, to = AccountRef(caller.Address()) ) // initialise a new contract and set the code that is to be used by the - // E The contract is a scoped evmironment for this execution context + // EVM. The contract is a scoped environment for this execution context // only. contract := NewContract(caller, to, value, gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) @@ -341,7 +341,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value) // initialise a new contract and set the code that is to be used by the - // E The contract is a scoped evmironment for this execution context + // EVM. The contract is a scoped environment for this execution context // only. contract := NewContract(caller, AccountRef(contractAddr), value, gas) contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 66e804fb7e..1e494a0eb8 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -39,20 +39,18 @@ var ( ) func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() - stack.push(math.U256(x.Add(x, y))) - - evm.interpreter.intPool.put(y) + x, y := stack.pop(), stack.peek() + math.U256(y.Add(x, y)) + evm.interpreter.intPool.put(x) return nil, nil } func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() - stack.push(math.U256(x.Sub(x, y))) - - evm.interpreter.intPool.put(y) + x, y := stack.pop(), stack.peek() + math.U256(y.Sub(x, y)) + evm.interpreter.intPool.put(x) return nil, nil } @@ -66,44 +64,39 @@ func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() + x, y := stack.pop(), stack.peek() if y.Sign() != 0 { - stack.push(math.U256(x.Div(x, y))) + math.U256(y.Div(x, y)) } else { - stack.push(new(big.Int)) + y.SetUint64(0) } - - evm.interpreter.intPool.put(y) - + evm.interpreter.intPool.put(x) return nil, nil } func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := math.S256(stack.pop()), math.S256(stack.pop()) - if y.Sign() == 0 { - stack.push(new(big.Int)) - return nil, nil + res := evm.interpreter.intPool.getZero() + + if y.Sign() == 0 || x.Sign() == 0 { + stack.push(res) } else { - n := new(big.Int) - if evm.interpreter.intPool.get().Mul(x, y).Sign() < 0 { - n.SetInt64(-1) + if x.Sign() != y.Sign() { + res.Div(x.Abs(x), y.Abs(y)) + res.Neg(res) } else { - n.SetInt64(1) + res.Div(x.Abs(x), y.Abs(y)) } - - res := x.Div(x.Abs(x), y.Abs(y)) - res.Mul(res, n) - stack.push(math.U256(res)) } - evm.interpreter.intPool.put(y) + evm.interpreter.intPool.put(x, y) return nil, nil } func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() if y.Sign() == 0 { - stack.push(new(big.Int)) + stack.push(x.SetUint64(0)) } else { stack.push(math.U256(x.Mod(x, y))) } @@ -113,23 +106,20 @@ func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := math.S256(stack.pop()), math.S256(stack.pop()) + res := evm.interpreter.intPool.getZero() if y.Sign() == 0 { - stack.push(new(big.Int)) + stack.push(res) } else { - n := new(big.Int) if x.Sign() < 0 { - n.SetInt64(-1) + res.Mod(x.Abs(x), y.Abs(y)) + res.Neg(res) } else { - n.SetInt64(1) + res.Mod(x.Abs(x), y.Abs(y)) } - - res := x.Mod(x.Abs(x), y.Abs(y)) - res.Mul(res, n) - stack.push(math.U256(res)) } - evm.interpreter.intPool.put(y) + evm.interpreter.intPool.put(x, y) return nil, nil } @@ -163,32 +153,30 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac } func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x := stack.pop() - stack.push(math.U256(x.Not(x))) + x := stack.peek() + math.U256(x.Not(x)) return nil, nil } func opLt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() + x, y := stack.pop(), stack.peek() if x.Cmp(y) < 0 { - stack.push(evm.interpreter.intPool.get().SetUint64(1)) + y.SetUint64(1) } else { - stack.push(new(big.Int)) + y.SetUint64(0) } - - evm.interpreter.intPool.put(x, y) + evm.interpreter.intPool.put(x) return nil, nil } func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() + x, y := stack.pop(), stack.peek() if x.Cmp(y) > 0 { - stack.push(evm.interpreter.intPool.get().SetUint64(1)) + y.SetUint64(1) } else { - stack.push(new(big.Int)) + y.SetUint64(0) } - - evm.interpreter.intPool.put(x, y) + evm.interpreter.intPool.put(x) return nil, nil } @@ -270,18 +258,18 @@ func opAnd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() - stack.push(x.Or(x, y)) + x, y := stack.pop(), stack.peek() + y.Or(x, y) - evm.interpreter.intPool.put(y) + evm.interpreter.intPool.put(x) return nil, nil } func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := stack.pop(), stack.pop() - stack.push(x.Xor(x, y)) + x, y := stack.pop(), stack.peek() + y.Xor(x, y) - evm.interpreter.intPool.put(y) + evm.interpreter.intPool.put(x) return nil, nil } @@ -300,13 +288,12 @@ func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y, z := stack.pop(), stack.pop(), stack.pop() if z.Cmp(bigZero) > 0 { - add := x.Add(x, y) - add.Mod(add, z) - stack.push(math.U256(add)) + x.Add(x, y) + x.Mod(x, z) + stack.push(math.U256(x)) } else { - stack.push(new(big.Int)) + stack.push(x.SetUint64(0)) } - evm.interpreter.intPool.put(y, z) return nil, nil } @@ -314,13 +301,12 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y, z := stack.pop(), stack.pop(), stack.pop() if z.Cmp(bigZero) > 0 { - mul := x.Mul(x, y) - mul.Mod(mul, z) - stack.push(math.U256(mul)) + x.Mul(x, y) + x.Mod(x, z) + stack.push(math.U256(x)) } else { - stack.push(new(big.Int)) + stack.push(x.SetUint64(0)) } - evm.interpreter.intPool.put(y, z) return nil, nil } @@ -393,8 +379,7 @@ func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta if evm.vmConfig.EnablePreimageRecording { evm.StateDB.AddPreimage(common.BytesToHash(hash), data) } - - stack.push(new(big.Int).SetBytes(hash)) + stack.push(evm.interpreter.intPool.get().SetBytes(hash)) evm.interpreter.intPool.put(offset, size) return nil, nil @@ -406,10 +391,8 @@ func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack * } func opBalance(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - addr := common.BigToAddress(stack.pop()) - balance := evm.StateDB.GetBalance(addr) - - stack.push(new(big.Int).Set(balance)) + slot := stack.peek() + slot.Set(evm.StateDB.GetBalance(common.BigToAddress(slot))) return nil, nil } @@ -429,7 +412,7 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack } func opCallDataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(new(big.Int).SetBytes(getDataBig(contract.Input, stack.pop(), big32))) + stack.push(evm.interpreter.intPool.get().SetBytes(getDataBig(contract.Input, stack.pop(), big32))) return nil, nil } @@ -460,10 +443,11 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, memOffset = stack.pop() dataOffset = stack.pop() length = stack.pop() - ) - defer evm.interpreter.intPool.put(memOffset, dataOffset, length) - end := new(big.Int).Add(dataOffset, length) + end = evm.interpreter.intPool.get().Add(dataOffset, length) + ) + defer evm.interpreter.intPool.put(memOffset, dataOffset, length, end) + if end.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < end.Uint64() { return nil, errReturnDataOutOfBounds } @@ -473,11 +457,8 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, } func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - a := stack.pop() - - addr := common.BigToAddress(a) - a.SetInt64(int64(evm.StateDB.GetCodeSize(addr))) - stack.push(a) + slot := stack.peek() + slot.SetUint64(uint64(evm.StateDB.GetCodeSize(common.BigToAddress(slot)))) return nil, nil } @@ -485,6 +466,7 @@ func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta func opCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { l := evm.interpreter.intPool.get().SetInt64(int64(len(contract.Code))) stack.push(l) + return nil, nil } @@ -527,9 +509,8 @@ func opBlockhash(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack if num.Cmp(n) > 0 && num.Cmp(evm.BlockNumber) < 0 { stack.push(evm.GetHash(num.Uint64()).Big()) } else { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } - evm.interpreter.intPool.put(num, n) return nil, nil } @@ -540,22 +521,22 @@ func opCoinbase(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack } func opTimestamp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(math.U256(new(big.Int).Set(evm.Time))) + stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.Time))) return nil, nil } func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(math.U256(new(big.Int).Set(evm.BlockNumber))) + stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.BlockNumber))) return nil, nil } func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(math.U256(new(big.Int).Set(evm.Difficulty))) + stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.Difficulty))) return nil, nil } func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(math.U256(new(big.Int).SetUint64(evm.GasLimit))) + stack.push(math.U256(evm.interpreter.intPool.get().SetUint64(evm.GasLimit))) return nil, nil } @@ -566,7 +547,7 @@ func opPop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { offset := stack.pop() - val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32)) + val := evm.interpreter.intPool.get().SetBytes(memory.Get(offset.Int64(), 32)) stack.push(val) evm.interpreter.intPool.put(offset) @@ -670,9 +651,9 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S // rule) and treat as an error, if the ruleset is frontier we must // ignore this error and pretend the operation was successful. if evm.ChainConfig().IsHomestead(evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } else { stack.push(addr.Big()) } @@ -701,9 +682,9 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta } ret, returnGas, err := evm.Call(contract, toAddr, args, gas, value) if err != nil { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } else { - stack.push(big.NewInt(1)) + stack.push(evm.interpreter.intPool.get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) @@ -730,9 +711,9 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack } ret, returnGas, err := evm.CallCode(contract, toAddr, args, gas, value) if err != nil { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } else { - stack.push(big.NewInt(1)) + stack.push(evm.interpreter.intPool.get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) @@ -755,9 +736,9 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st ret, returnGas, err := evm.DelegateCall(contract, toAddr, args, gas) if err != nil { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } else { - stack.push(big.NewInt(1)) + stack.push(evm.interpreter.intPool.get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) @@ -780,9 +761,9 @@ func opStaticCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac ret, returnGas, err := evm.StaticCall(contract, toAddr, args, gas) if err != nil { - stack.push(new(big.Int)) + stack.push(evm.interpreter.intPool.getZero()) } else { - stack.push(big.NewInt(1)) + stack.push(evm.interpreter.intPool.get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 134363bb74..0de558612c 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -32,7 +32,7 @@ type twoOperandTest struct { func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false}) + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) ) @@ -68,7 +68,7 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64 func TestByteOp(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false}) + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) stack = newstack() ) tests := []struct { @@ -198,7 +198,7 @@ func TestSLT(t *testing.T) { func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false}) + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) stack = newstack() ) // convert args diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 95490adfc4..7090e0261f 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -28,10 +28,6 @@ import ( type Config struct { // Debug enabled debugging Interpreter options Debug bool - // EnableJit enabled the JIT VM - EnableJit bool - // ForceJit forces the JIT VM - ForceJit bool // Tracer is the op code logger Tracer Tracer // NoRecursion disabled Interpreter call, callcode, @@ -46,8 +42,8 @@ type Config struct { } // Interpreter is used to run Ethereum based contracts and will utilise the -// passed evmironment to query external sources for state information. -// The Interpreter will run the byte code VM or JIT VM based on the passed +// passed environment to query external sources for state information. +// The Interpreter will run the byte code VM based on the passed // configuration. type Interpreter struct { evm *EVM @@ -188,7 +184,7 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er } } // consume the gas and return an error if not enough gas is available. - // cost is explicitly set so that the capture state defer method cas get the proper cost + // cost is explicitly set so that the capture state defer method can get the proper cost cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize) if err != nil || !contract.UseGas(cost) { return nil, ErrOutOfGas diff --git a/core/vm/intpool.go b/core/vm/intpool.go index 384f5df59b..5dbda18eee 100644 --- a/core/vm/intpool.go +++ b/core/vm/intpool.go @@ -32,24 +32,36 @@ func newIntPool() *intPool { return &intPool{pool: newstack()} } +// get retrieves a big int from the pool, allocating one if the pool is empty. +// Note, the returned int's value is arbitrary and will not be zeroed! func (p *intPool) get() *big.Int { if p.pool.len() > 0 { return p.pool.pop() } return new(big.Int) } + +// getZero retrieves a big int from the pool, setting it to zero or allocating +// a new one if the pool is empty. +func (p *intPool) getZero() *big.Int { + if p.pool.len() > 0 { + return p.pool.pop().SetUint64(0) + } + return new(big.Int) +} + +// put returns an allocated big int to the pool to be later reused by get calls. +// Note, the values as saved as is; neither put nor get zeroes the ints out! func (p *intPool) put(is ...*big.Int) { if len(p.pool.data) > poolLimit { return } - for _, i := range is { // verifyPool is a build flag. Pool verification makes sure the integrity // of the integer pool by comparing values to a default value. if verifyPool { i.Set(checkVal) } - p.pool.push(i) } } diff --git a/core/vm/logger.go b/core/vm/logger.go index 4c820d8b53..dde1903bf2 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -45,6 +45,7 @@ type LogConfig struct { DisableMemory bool // disable memory capture DisableStack bool // disable stack capture DisableStorage bool // disable storage capture + Debug bool // print output during capture end 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 { l.output = output l.err = err + if l.cfg.Debug { + fmt.Printf("0x%x\n", output) + if err != nil { + fmt.Printf(" error: %v\n", err) + } + } return nil } diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go index 915f7177e7..28830c445c 100644 --- a/core/vm/logger_test.go +++ b/core/vm/logger_test.go @@ -48,7 +48,7 @@ type dummyStateDB struct { func TestStoreCapture(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false}) + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) logger = NewStructLogger(nil) mem = NewMemory() stack = newstack() diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index edbf541766..1e9ed7ae2d 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -41,7 +41,6 @@ type Config struct { GasLimit uint64 GasPrice *big.Int Value *big.Int - DisableJit bool // "disable" so it's enabled by default Debug bool EVMConfig vm.Config @@ -92,8 +91,7 @@ func setDefaults(cfg *Config) { // It returns the EVM's return value, the new state and an error if it failed. // // Executes sets up a in memory, temporarily, environment for the execution of -// the given code. It enabled the JIT by default and make sure that it's restored -// to it's original state afterwards. +// the given code. It makes sure that it's restored to it's original state afterwards. func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { if cfg == nil { cfg = new(Config) diff --git a/core/vm/vm_jit.go b/core/vm/vm_jit.go deleted file mode 100644 index eb3acfb10d..0000000000 --- a/core/vm/vm_jit.go +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// +build evmjit - -package vm - -/* - -void* evmjit_create(); -int evmjit_run(void* _jit, void* _data, void* _env); -void evmjit_destroy(void* _jit); - -// Shared library evmjit (e.g. libevmjit.so) is expected to be installed in /usr/local/lib -// More: https://github.com/ethereum/evmjit -#cgo LDFLAGS: -levmjit -*/ -import "C" - -/* -import ( - "bytes" - "errors" - "fmt" - "math/big" - "unsafe" - - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" -) - -type JitVm struct { - env EVM - me ContextRef - callerAddr []byte - price *big.Int - data RuntimeData -} - -type i256 [32]byte - -type RuntimeData struct { - gas int64 - gasPrice int64 - callData *byte - callDataSize uint64 - address i256 - caller i256 - origin i256 - callValue i256 - coinBase i256 - difficulty i256 - gasLimit i256 - number uint64 - timestamp int64 - code *byte - codeSize uint64 - codeHash i256 -} - -func hash2llvm(h []byte) i256 { - var m i256 - copy(m[len(m)-len(h):], h) // right aligned copy - return m -} - -func llvm2hash(m *i256) []byte { - return C.GoBytes(unsafe.Pointer(m), C.int(len(m))) -} - -func llvm2hashRef(m *i256) []byte { - return (*[1 << 30]byte)(unsafe.Pointer(m))[:len(m):len(m)] -} - -func address2llvm(addr []byte) i256 { - n := hash2llvm(addr) - bswap(&n) - return n -} - -// bswap swap bytes of the 256-bit integer on LLVM side -// TODO: Do not change memory on LLVM side, that can conflict with memory access optimizations -func bswap(m *i256) *i256 { - for i, l := 0, len(m); i < l/2; i++ { - m[i], m[l-i-1] = m[l-i-1], m[i] - } - return m -} - -func trim(m []byte) []byte { - skip := 0 - for i := 0; i < len(m); i++ { - if m[i] == 0 { - skip++ - } else { - break - } - } - return m[skip:] -} - -func getDataPtr(m []byte) *byte { - var p *byte - if len(m) > 0 { - p = &m[0] - } - return p -} - -func big2llvm(n *big.Int) i256 { - m := hash2llvm(n.Bytes()) - bswap(&m) - return m -} - -func llvm2big(m *i256) *big.Int { - n := big.NewInt(0) - for i := 0; i < len(m); i++ { - b := big.NewInt(int64(m[i])) - b.Lsh(b, uint(i)*8) - n.Add(n, b) - } - return n -} - -// llvm2bytesRef creates a []byte slice that references byte buffer on LLVM side (as of that not controller by GC) -// User must ensure that referenced memory is available to Go until the data is copied or not needed any more -func llvm2bytesRef(data *byte, length uint64) []byte { - if length == 0 { - return nil - } - if data == nil { - panic("Unexpected nil data pointer") - } - return (*[1 << 30]byte)(unsafe.Pointer(data))[:length:length] -} - -func untested(condition bool, message string) { - if condition { - panic("Condition `" + message + "` tested. Remove assert.") - } -} - -func assert(condition bool, message string) { - if !condition { - panic("Assert `" + message + "` failed!") - } -} - -func NewJitVm(env EVM) *JitVm { - return &JitVm{env: env} -} - -func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { - // TODO: depth is increased but never checked by VM. VM should not know about it at all. - self.env.SetDepth(self.env.Depth() + 1) - - // TODO: Move it to Env.Call() or sth - if Precompiled[string(me.Address())] != nil { - // if it's address of precompiled contract - // fallback to standard VM - stdVm := New(self.env) - return stdVm.Run(me, caller, code, value, gas, price, callData) - } - - if self.me != nil { - panic("JitVm.Run() can be called only once per JitVm instance") - } - - self.me = me - self.callerAddr = caller.Address() - self.price = price - - self.data.gas = gas.Int64() - self.data.gasPrice = price.Int64() - self.data.callData = getDataPtr(callData) - self.data.callDataSize = uint64(len(callData)) - self.data.address = address2llvm(self.me.Address()) - self.data.caller = address2llvm(caller.Address()) - self.data.origin = address2llvm(self.env.Origin()) - self.data.callValue = big2llvm(value) - self.data.coinBase = address2llvm(self.env.Coinbase()) - self.data.difficulty = big2llvm(self.env.Difficulty()) - self.data.gasLimit = big2llvm(self.env.GasLimit()) - self.data.number = self.env.BlockNumber().Uint64() - self.data.timestamp = self.env.Time() - self.data.code = getDataPtr(code) - self.data.codeSize = uint64(len(code)) - self.data.codeHash = hash2llvm(crypto.Keccak256(code)) // TODO: Get already computed hash? - - jit := C.evmjit_create() - retCode := C.evmjit_run(jit, unsafe.Pointer(&self.data), unsafe.Pointer(self)) - - if retCode < 0 { - err = errors.New("OOG from JIT") - gas.SetInt64(0) // Set gas to 0, JIT does not bother - } else { - gas.SetInt64(self.data.gas) - if retCode == 1 { // RETURN - ret = C.GoBytes(unsafe.Pointer(self.data.callData), C.int(self.data.callDataSize)) - } else if retCode == 2 { // SUICIDE - // TODO: Suicide support logic should be moved to Env to be shared by VM implementations - state := self.Env().State() - receiverAddr := llvm2hashRef(bswap(&self.data.address)) - receiver := state.GetOrNewStateObject(receiverAddr) - balance := state.GetBalance(me.Address()) - receiver.AddBalance(balance) - state.Delete(me.Address()) - } - } - - C.evmjit_destroy(jit) - return -} - -func (self *JitVm) Printf(format string, v ...interface{}) VirtualMachine { - return self -} - -func (self *JitVm) Endl() VirtualMachine { - return self -} - -func (self *JitVm) Env() EVM { - return self.env -} - -//export env_sha3 -func env_sha3(dataPtr *byte, length uint64, resultPtr unsafe.Pointer) { - data := llvm2bytesRef(dataPtr, length) - hash := crypto.Keccak256(data) - result := (*i256)(resultPtr) - *result = hash2llvm(hash) -} - -//export env_sstore -func env_sstore(vmPtr unsafe.Pointer, indexPtr unsafe.Pointer, valuePtr unsafe.Pointer) { - vm := (*JitVm)(vmPtr) - index := llvm2hash(bswap((*i256)(indexPtr))) - value := llvm2hash(bswap((*i256)(valuePtr))) - value = trim(value) - if len(value) == 0 { - prevValue := vm.env.State().GetState(vm.me.Address(), index) - if len(prevValue) != 0 { - vm.Env().State().Refund(vm.callerAddr, GasSStoreRefund) - } - } - - vm.env.State().SetState(vm.me.Address(), index, value) -} - -//export env_sload -func env_sload(vmPtr unsafe.Pointer, indexPtr unsafe.Pointer, resultPtr unsafe.Pointer) { - vm := (*JitVm)(vmPtr) - index := llvm2hash(bswap((*i256)(indexPtr))) - value := vm.env.State().GetState(vm.me.Address(), index) - result := (*i256)(resultPtr) - *result = hash2llvm(value) - bswap(result) -} - -//export env_balance -func env_balance(_vm unsafe.Pointer, _addr unsafe.Pointer, _result unsafe.Pointer) { - vm := (*JitVm)(_vm) - addr := llvm2hash((*i256)(_addr)) - balance := vm.Env().State().GetBalance(addr) - result := (*i256)(_result) - *result = big2llvm(balance) -} - -//export env_blockhash -func env_blockhash(_vm unsafe.Pointer, _number unsafe.Pointer, _result unsafe.Pointer) { - vm := (*JitVm)(_vm) - number := llvm2big((*i256)(_number)) - result := (*i256)(_result) - - currNumber := vm.Env().BlockNumber() - limit := big.NewInt(0).Sub(currNumber, big.NewInt(256)) - if number.Cmp(limit) >= 0 && number.Cmp(currNumber) < 0 { - hash := vm.Env().GetHash(uint64(number.Int64())) - *result = hash2llvm(hash) - } else { - *result = i256{} - } -} - -//export env_call -func env_call(_vm unsafe.Pointer, _gas *int64, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr unsafe.Pointer, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool { - vm := (*JitVm)(_vm) - - //fmt.Printf("env_call (depth %d)\n", vm.Env().Depth()) - - defer func() { - if r := recover(); r != nil { - fmt.Printf("Recovered in env_call (depth %d, out %p %d): %s\n", vm.Env().Depth(), outDataPtr, outDataLen, r) - } - }() - - balance := vm.Env().State().GetBalance(vm.me.Address()) - value := llvm2big((*i256)(_value)) - - if balance.Cmp(value) >= 0 { - receiveAddr := llvm2hash((*i256)(_receiveAddr)) - inData := C.GoBytes(inDataPtr, C.int(inDataLen)) - outData := llvm2bytesRef(outDataPtr, outDataLen) - codeAddr := llvm2hash((*i256)(_codeAddr)) - gas := big.NewInt(*_gas) - var out []byte - var err error - if bytes.Equal(codeAddr, receiveAddr) { - out, err = vm.env.Call(vm.me, codeAddr, inData, gas, vm.price, value) - } else { - out, err = vm.env.CallCode(vm.me, codeAddr, inData, gas, vm.price, value) - } - *_gas = gas.Int64() - if err == nil { - copy(outData, out) - return true - } - } - - return false -} - -//export env_create -func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initDataPtr unsafe.Pointer, initDataLen uint64, _result unsafe.Pointer) { - vm := (*JitVm)(_vm) - - value := llvm2big((*i256)(_value)) - initData := C.GoBytes(initDataPtr, C.int(initDataLen)) // TODO: Unnecessary if low balance - result := (*i256)(_result) - *result = i256{} - - gas := big.NewInt(*_gas) - ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value) - if suberr == nil { - dataGas := big.NewInt(int64(len(ret))) // TODO: Not the best design. env.Create can do it, it has the reference to gas counter - dataGas.Mul(dataGas, params.CreateDataGas) - gas.Sub(gas, dataGas) - *result = hash2llvm(ref.Address()) - } - *_gas = gas.Int64() -} - -//export env_log -func env_log(_vm unsafe.Pointer, dataPtr unsafe.Pointer, dataLen uint64, _topic1 unsafe.Pointer, _topic2 unsafe.Pointer, _topic3 unsafe.Pointer, _topic4 unsafe.Pointer) { - vm := (*JitVm)(_vm) - - data := C.GoBytes(dataPtr, C.int(dataLen)) - - topics := make([][]byte, 0, 4) - if _topic1 != nil { - topics = append(topics, llvm2hash((*i256)(_topic1))) - } - if _topic2 != nil { - topics = append(topics, llvm2hash((*i256)(_topic2))) - } - if _topic3 != nil { - topics = append(topics, llvm2hash((*i256)(_topic3))) - } - if _topic4 != nil { - topics = append(topics, llvm2hash((*i256)(_topic4))) - } - - vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data, vm.env.BlockNumber().Uint64())) -} - -//export env_extcode -func env_extcode(_vm unsafe.Pointer, _addr unsafe.Pointer, o_size *uint64) *byte { - vm := (*JitVm)(_vm) - addr := llvm2hash((*i256)(_addr)) - code := vm.Env().State().GetCode(addr) - *o_size = uint64(len(code)) - return getDataPtr(code) -}*/ diff --git a/core/vm/vm_jit_fake.go b/core/vm/vm_jit_fake.go deleted file mode 100644 index 44b60abf6f..0000000000 --- a/core/vm/vm_jit_fake.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// +build !evmjit - -package vm diff --git a/crypto/ecies/ecies.go b/crypto/ecies/ecies.go index 2ed91c895d..1474181482 100644 --- a/crypto/ecies/ecies.go +++ b/crypto/ecies/ecies.go @@ -230,7 +230,7 @@ func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, // symDecrypt carries out CTR decryption using the block cipher specified in // the parameters -func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) { +func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { c, err := params.Cipher(key) if err != nil { return @@ -292,7 +292,7 @@ func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err e } // Decrypt decrypts an ECIES ciphertext. -func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) { +func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { if len(c) == 0 { return nil, ErrInvalidMessage } @@ -361,6 +361,6 @@ func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err return } - m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd]) + m, err = symDecrypt(params, Ke, c[mStart:mEnd]) return } diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go index 9cd5c79f7e..f33f204d5b 100644 --- a/crypto/ecies/ecies_test.go +++ b/crypto/ecies/ecies_test.go @@ -270,7 +270,7 @@ func TestEncryptDecrypt(t *testing.T) { t.FailNow() } - pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil) + pt, err := prv2.Decrypt(ct, nil, nil) if err != nil { fmt.Println(err.Error()) t.FailNow() @@ -281,7 +281,7 @@ func TestEncryptDecrypt(t *testing.T) { t.FailNow() } - _, err = prv1.Decrypt(rand.Reader, ct, nil, nil) + _, err = prv1.Decrypt(ct, nil, nil) if err == nil { fmt.Println("ecies: encryption should not have succeeded") t.FailNow() @@ -301,7 +301,7 @@ func TestDecryptShared2(t *testing.T) { } // Check that decrypting with correct shared data works. - pt, err := prv.Decrypt(rand.Reader, ct, nil, shared2) + pt, err := prv.Decrypt(ct, nil, shared2) if err != nil { t.Fatal(err) } @@ -310,10 +310,10 @@ func TestDecryptShared2(t *testing.T) { } // Decrypting without shared data or incorrect shared data fails. - if _, err = prv.Decrypt(rand.Reader, ct, nil, nil); err == nil { + if _, err = prv.Decrypt(ct, nil, nil); err == nil { t.Fatal("ecies: decrypting without shared data didn't fail") } - if _, err = prv.Decrypt(rand.Reader, ct, nil, []byte("garbage")); err == nil { + if _, err = prv.Decrypt(ct, nil, []byte("garbage")); err == nil { t.Fatal("ecies: decrypting with incorrect shared data didn't fail") } } @@ -381,7 +381,7 @@ func testParamSelection(t *testing.T, c testCase) { t.FailNow() } - pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil) + pt, err := prv2.Decrypt(ct, nil, nil) if err != nil { fmt.Printf("%s (%s)\n", err.Error(), c.Name) t.FailNow() @@ -393,7 +393,7 @@ func testParamSelection(t *testing.T, c testCase) { t.FailNow() } - _, err = prv1.Decrypt(rand.Reader, ct, nil, nil) + _, err = prv1.Decrypt(ct, nil, nil) if err == nil { fmt.Printf("ecies: encryption should not have succeeded (%s)\n", c.Name) @@ -422,7 +422,7 @@ func TestBasicKeyValidation(t *testing.T) { for _, b := range badBytes { ct[0] = b - _, err := prv.Decrypt(rand.Reader, ct, nil, nil) + _, err := prv.Decrypt(ct, nil, nil) if err != ErrInvalidPublicKey { fmt.Println("ecies: validated an invalid key") t.FailNow() @@ -441,14 +441,14 @@ func TestBox(t *testing.T) { t.Fatal(err) } - pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil) + pt, err := prv2.Decrypt(ct, nil, nil) if err != nil { t.Fatal(err) } if !bytes.Equal(pt, message) { t.Fatal("ecies: plaintext doesn't match message") } - if _, err = prv1.Decrypt(rand.Reader, ct, nil, nil); err == nil { + if _, err = prv1.Decrypt(ct, nil, nil); err == nil { t.Fatal("ecies: encryption should not have succeeded") } } diff --git a/crypto/secp256k1/curve.go b/crypto/secp256k1/curve.go index df80481857..f51be5e353 100644 --- a/crypto/secp256k1/curve.go +++ b/crypto/secp256k1/curve.go @@ -290,11 +290,11 @@ func init() { // See SEC 2 section 2.7.1 // curve parameters taken from: // http://www.secg.org/collateral/sec2_final.pdf - theCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) - theCurve.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) - theCurve.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16) - theCurve.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16) - theCurve.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) + theCurve.P = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F") + theCurve.N = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141") + theCurve.B = math.MustParseBig256("0x0000000000000000000000000000000000000000000000000000000000000007") + theCurve.Gx = math.MustParseBig256("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") + theCurve.Gy = math.MustParseBig256("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") theCurve.BitSize = 256 } diff --git a/eth/backend.go b/eth/backend.go index 94aad23101..ffd5d85421 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -63,7 +63,7 @@ type Ethereum struct { chainConfig *params.ChainConfig // 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 // Handlers @@ -351,7 +351,7 @@ func (s *Ethereum) StartMining(local bool) error { if local { // If local (CPU) mining is started, we can disable the transaction rejection // 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. atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) } diff --git a/eth/db_upgrade.go b/eth/db_upgrade.go index d41afa17c0..96c584ac64 100644 --- a/eth/db_upgrade.go +++ b/eth/db_upgrade.go @@ -62,7 +62,7 @@ func upgradeDeduplicateData(db ethdb.Database) func() error { failed error ) for failed == nil && it.Next() { - // Skip any entries that don't look like old transaction meta entires (0x01) + // Skip any entries that don't look like old transaction meta entries (0x01) key := it.Key() if len(key) != common.HashLength+1 || key[common.HashLength] != 0x01 { continue @@ -86,7 +86,7 @@ func upgradeDeduplicateData(db ethdb.Database) func() error { } } // 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(append([]byte("receipts-"), hash...)); failed == nil { // Delete the duplicate receipt data if failed = db.Delete(key); failed != nil { // Delete the old transaction metadata diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 62842adbc6..9e49498998 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -47,7 +47,7 @@ var ( MaxForkAncestry = 3 * params.EpochDuration // Maximum chain reorganisation 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 ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion 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 // 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. func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, int, error) { log.Debug("Filling up skeleton", "from", from) @@ -1377,7 +1377,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { pivot = height - uint64(fsMinFullBlocks) } // To cater for moving pivot points, track the pivot block and subsequently - // accumulated download results separatey. + // accumulated download results separately. var ( oldPivot *fetchResult // Locked in pivot block, might change eventually 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 // 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 { return time.Duration(atomic.LoadUint64(&d.rttEstimate)) * 9 / 10 } diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index cb671a7df4..e85e234c0e 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -159,7 +159,7 @@ func (dl *downloadTester) makeChainFork(n, f int, parent *types.Block, parentRec // Create the common suffix 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 = append(hashes1, hashes[1:]...) diff --git a/eth/downloader/fakepeer.go b/eth/downloader/fakepeer.go index b45acff7d0..5248e7fb0c 100644 --- a/eth/downloader/fakepeer.go +++ b/eth/downloader/fakepeer.go @@ -27,7 +27,7 @@ import ( // 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 -// sync commands from an xisting local database. +// sync commands from an existing local database. type FakePeer struct { id string db ethdb.Database @@ -48,7 +48,7 @@ func (p *FakePeer) Head() (common.Hash, *big.Int) { } // 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 { var ( 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 -// 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 { var ( headers []*types.Header diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go index a4aa861146..428a60f8a1 100644 --- a/eth/downloader/peer.go +++ b/eth/downloader/peer.go @@ -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 // peers if there are more peers available. 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() defer ps.lock.RUnlock() diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go index 359cce54b5..bbe0aed5dc 100644 --- a/eth/downloader/queue.go +++ b/eth/downloader/queue.go @@ -275,7 +275,7 @@ func (q *queue) ScheduleSkeleton(from uint64, skeleton []*types.Header) { if q.headerResults != nil { 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.headerTaskQueue = prque.New() q.headerPeerMiss = make(map[string]map[uint64]struct{}) // Reset availability to correct invalid chains diff --git a/eth/downloader/statesync.go b/eth/downloader/statesync.go index ee6c7b4914..4071d0ad98 100644 --- a/eth/downloader/statesync.go +++ b/eth/downloader/statesync.go @@ -31,7 +31,7 @@ import ( "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. type stateReq struct { 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: 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()] if req == nil { 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: // 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 - // 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 // request is never honored, alas we must not silently overwrite it, as that // 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) } -// 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. type stateTask struct { attempts map[string]struct{} @@ -333,7 +333,7 @@ func (s *stateSync) commit(force bool) error { 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. func (s *stateSync) assignTasks() { // Iterate over all idle peers and try to assign them state fetches diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index db554e1440..0c679cec3a 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -127,7 +127,7 @@ type Fetcher struct { // Block cache queue *prque.Prque // Queue containing the import operations (block number sorted) 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 getBlock blockRetrievalFn // Retrieves a block from the local chain diff --git a/eth/filters/api.go b/eth/filters/api.go index 406c9442e0..ec403709c5 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -98,7 +98,7 @@ func (api *PublicFilterAPI) timeoutLoop() { // NewPendingTransactionFilter creates a filter that fetches pending transaction hashes // 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. // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter diff --git a/eth/handler.go b/eth/handler.go index 3fae0cd00d..4069359c9e 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -96,8 +96,8 @@ type ProtocolManager struct { wg sync.WaitGroup } -// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable -// with the ethereum network. +// NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable +// 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) { // Create the protocol manager with the base fields manager := &ProtocolManager{ @@ -498,20 +498,20 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { return errResp(ErrDecode, "msg %v: %v", msg, err) } // 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)) for i, body := range request { - trasactions[i] = body.Transactions + transactions[i] = body.Transactions uncles[i] = body.Uncles } // 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 { - 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 { - err := pm.downloader.DeliverBodies(p.id, trasactions, uncles) + if len(transactions) > 0 || len(uncles) > 0 || !filter { + err := pm.downloader.DeliverBodies(p.id, transactions, uncles) if err != nil { log.Debug("Failed to deliver bodies", "err", err) } diff --git a/ethdb/database.go b/ethdb/database.go index 8c557e4820..30ed37dc7b 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -29,6 +29,7 @@ import ( "github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/iterator" "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/syndtr/goleveldb/leveldb/util" ) var OpenFileLimit = 64 @@ -121,6 +122,11 @@ func (db *LDBDatabase) NewIterator() iterator.Iterator { return db.db.NewIterator(nil, nil) } +// NewIteratorWithPrefix returns a iterator to iterate over subset of database content with a particular prefix. +func (db *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator { + return db.db.NewIterator(util.BytesPrefix(prefix), nil) +} + func (db *LDBDatabase) Close() { // Stop the metrics collection to avoid internal database races db.quitLock.Lock() diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 6525aa212c..e2bfbaf307 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -1388,7 +1389,7 @@ func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (strin if block == nil { 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. diff --git a/light/postprocess.go b/light/postprocess.go index 384a635f76..a1b1d9fb04 100644 --- a/light/postprocess.go +++ b/light/postprocess.go @@ -58,18 +58,18 @@ type trustedCheckpoint struct { var ( mainnetCheckpoint = trustedCheckpoint{ name: "mainnet", - sectionIdx: 157, - sectionHead: common.HexToHash("1963c080887ca7f406c2bb114293eea83e54f783f94df24b447f7e3b6317c747"), - chtRoot: common.HexToHash("42abc436567dfb678a38fa6a9f881aa4c8a4cc8eaa2def08359292c3d0bd48ec"), - bloomTrieRoot: common.HexToHash("281c9f8fb3cb8b37ae45e9907ef8f3b19cd22c54e297c2d6c09c1db1593dce42"), + sectionIdx: 161, + sectionHead: common.HexToHash("75b0c4baa7a62cece48abdcb03b6f31601961c9bece67dcd61df87aad4fc0d8d"), + chtRoot: common.HexToHash("bbbfaa67b29716348997ec21a39c03b8d1fb973f6a43740b865595ba26ee812f"), + bloomTrieRoot: common.HexToHash("d6db6e6248354d7453391ce97830072a28ea4216be0bd95a5db9f53b1a64677b"), } ropstenCheckpoint = trustedCheckpoint{ name: "ropsten", - sectionIdx: 83, - sectionHead: common.HexToHash("3ca623586bc0da35f1fc8d9b6b55950f3b1f69be9c6501846a2df672adb61236"), - chtRoot: common.HexToHash("8f08ec7783969768c6ef06e5fe3398223cbf4ae2907b676da7b6fe6c7f55b059"), - bloomTrieRoot: common.HexToHash("02d86d3c6a87f8f8a92c2a59bbba2132ff6f9f61b0915a5dc28a9d8279219fd0"), + sectionIdx: 87, + sectionHead: common.HexToHash("ebc0adcb30ed21cbe95bd77499cc1af0bada621fee3644cb80dbcf1444c123fe"), + chtRoot: common.HexToHash("d9830f4893c821ddf149b8cb9d3e3bfe3109d2eea8e3c4a4ede7c8b2ee8a7800"), + bloomTrieRoot: common.HexToHash("c76e12d713f65b84c5a36d06bc77d0c8419248ea0b36e0812a78b76aa6da0ddb"), } ) diff --git a/mobile/geth.go b/mobile/geth.go index 7e3b8f4915..488a4150fc 100644 --- a/mobile/geth.go +++ b/mobile/geth.go @@ -34,7 +34,7 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/params" - whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" + whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" ) // NodeConfig represents the collection of configuration values to fine tune the Geth diff --git a/mobile/types.go b/mobile/types.go index 4790afceff..24cd7ebf11 100644 --- a/mobile/types.go +++ b/mobile/types.go @@ -97,12 +97,6 @@ func (h *Header) EncodeJSON() (string, error) { 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) GetUncleHash() *Hash { return &Hash{h.header.UncleHash} } func (h *Header) GetCoinbase() *Address { return &Address{h.header.Coinbase} } @@ -174,12 +168,6 @@ func (b *Block) EncodeJSON() (string, error) { 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) GetUncleHash() *Hash { return &Hash{b.block.UncleHash()} } func (b *Block) GetCoinbase() *Address { return &Address{b.block.Coinbase()} } @@ -249,12 +237,6 @@ func (tx *Transaction) EncodeJSON() (string, error) { 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) GetGas() int64 { return int64(tx.tx.Gas()) } func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} } @@ -347,12 +329,6 @@ func (r *Receipt) EncodeJSON() (string, error) { 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) GetCumulativeGasUsed() int64 { return int64(r.receipt.CumulativeGasUsed) } func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} } diff --git a/p2p/rlpx.go b/p2p/rlpx.go index 1889edac99..a320e81e7c 100644 --- a/p2p/rlpx.go +++ b/p2p/rlpx.go @@ -491,7 +491,7 @@ func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r } // Attempt decoding pre-EIP-8 "plain" format. key := ecies.ImportECDSA(prv) - if dec, err := key.Decrypt(rand.Reader, buf, nil, nil); err == nil { + if dec, err := key.Decrypt(buf, nil, nil); err == nil { msg.decodePlain(dec) return buf, nil } @@ -505,7 +505,7 @@ func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r if _, err := io.ReadFull(r, buf[plainSize:]); err != nil { return buf, err } - dec, err := key.Decrypt(rand.Reader, buf[2:], nil, prefix) + dec, err := key.Decrypt(buf[2:], nil, prefix) if err != nil { return buf, err } diff --git a/params/version.go b/params/version.go index 921d075996..181f84631e 100644 --- a/params/version.go +++ b/params/version.go @@ -23,7 +23,7 @@ import ( const ( VersionMajor = 1 // Major version component of the current release VersionMinor = 8 // Minor version component of the current release - VersionPatch = 3 // Patch version component of the current release + VersionPatch = 4 // Patch version component of the current release VersionMeta = "unstable" // Version metadata to append to the version string ) diff --git a/rpc/http.go b/rpc/http.go index 9805d69b63..e8f51150f4 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -169,7 +169,8 @@ func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // All checks passed, create a codec that reads direct from the request body // untilEOF and writes the response to w and order the server to process a // single request. - codec := NewJSONCodec(&httpReadWriteNopCloser{r.Body, w}) + body := io.LimitReader(r.Body, maxRequestContentLength) + codec := NewJSONCodec(&httpReadWriteNopCloser{body, w}) defer codec.Close() w.Header().Set("content-type", contentType) diff --git a/whisper/shhclient/client.go b/whisper/shhclient/client.go index 61b4775d95..bbe694baaa 100644 --- a/whisper/shhclient/client.go +++ b/whisper/shhclient/client.go @@ -22,10 +22,10 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" + whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" ) -// Client defines typed wrappers for the Whisper v5 RPC API. +// Client defines typed wrappers for the Whisper v6 RPC API. type Client struct { c *rpc.Client } @@ -168,27 +168,27 @@ func (sc *Client) Post(ctx context.Context, message whisper.NewMessage) error { // SubscribeMessages subscribes to messages that match the given criteria. This method // is only supported on bi-directional connections such as websockets and IPC. // NewMessageFilter uses polling and is supported over HTTP. -func (ec *Client) SubscribeMessages(ctx context.Context, criteria whisper.Criteria, ch chan<- *whisper.Message) (ethereum.Subscription, error) { - return ec.c.ShhSubscribe(ctx, ch, "messages", criteria) +func (sc *Client) SubscribeMessages(ctx context.Context, criteria whisper.Criteria, ch chan<- *whisper.Message) (ethereum.Subscription, error) { + return sc.c.ShhSubscribe(ctx, ch, "messages", criteria) } // NewMessageFilter creates a filter within the node. This filter can be used to poll // for new messages (see FilterMessages) that satisfy the given criteria. A filter can // timeout when it was polled for in whisper.filterTimeout. -func (ec *Client) NewMessageFilter(ctx context.Context, criteria whisper.Criteria) (string, error) { +func (sc *Client) NewMessageFilter(ctx context.Context, criteria whisper.Criteria) (string, error) { var id string - return id, ec.c.CallContext(ctx, &id, "shh_newMessageFilter", criteria) + return id, sc.c.CallContext(ctx, &id, "shh_newMessageFilter", criteria) } // DeleteMessageFilter removes the filter associated with the given id. -func (ec *Client) DeleteMessageFilter(ctx context.Context, id string) error { +func (sc *Client) DeleteMessageFilter(ctx context.Context, id string) error { var ignored bool - return ec.c.CallContext(ctx, &ignored, "shh_deleteMessageFilter", id) + return sc.c.CallContext(ctx, &ignored, "shh_deleteMessageFilter", id) } // FilterMessages retrieves all messages that are received between the last call to // this function and match the criteria that where given when the filter was created. -func (ec *Client) FilterMessages(ctx context.Context, id string) ([]*whisper.Message, error) { +func (sc *Client) FilterMessages(ctx context.Context, id string) ([]*whisper.Message, error) { var messages []*whisper.Message - return messages, ec.c.CallContext(ctx, &messages, "shh_getFilterMessages", id) + return messages, sc.c.CallContext(ctx, &messages, "shh_getFilterMessages", id) } diff --git a/whisper/whisperv5/message.go b/whisper/whisperv5/message.go index c27535cd1a..34ce52e64f 100644 --- a/whisper/whisperv5/message.go +++ b/whisper/whisperv5/message.go @@ -277,7 +277,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, nonce []byte) error { // decryptAsymmetric decrypts an encrypted payload with a private key. func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error { - decrypted, err := ecies.ImportECDSA(key).Decrypt(crand.Reader, msg.Raw, nil, nil) + decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil) if err == nil { msg.Raw = decrypted } diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go index 96e2b17e7c..3f3a082afe 100644 --- a/whisper/whisperv6/api.go +++ b/whisper/whisperv6/api.go @@ -558,9 +558,10 @@ func (api *PublicWhisperAPI) NewMessageFilter(req Criteria) (string, error) { } if len(req.Topics) > 0 { - topics = make([][]byte, 0, len(req.Topics)) - for _, topic := range req.Topics { - topics = append(topics, topic[:]) + topics = make([][]byte, len(req.Topics)) + for i, topic := range req.Topics { + topics[i] = make([]byte, TopicLength) + copy(topics[i], topic[:]) } } diff --git a/whisper/whisperv6/api_test.go b/whisper/whisperv6/api_test.go new file mode 100644 index 0000000000..004a41c949 --- /dev/null +++ b/whisper/whisperv6/api_test.go @@ -0,0 +1,78 @@ +// Copyright 2018 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 . + +package whisperv6 + +import ( + "bytes" + "crypto/ecdsa" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + set "gopkg.in/fatih/set.v0" +) + +func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) { + w := &Whisper{ + privateKeys: make(map[string]*ecdsa.PrivateKey), + symKeys: make(map[string][]byte), + envelopes: make(map[common.Hash]*Envelope), + expirations: make(map[uint32]*set.SetNonTS), + peers: make(map[*Peer]struct{}), + messageQueue: make(chan *Envelope, messageQueueLimit), + p2pMsgQueue: make(chan *Envelope, messageQueueLimit), + quit: make(chan struct{}), + syncAllowance: DefaultSyncAllowance, + } + w.filters = NewFilters(w) + + keyID, err := w.GenerateSymKey() + if err != nil { + t.Fatalf("Error generating symmetric key: %v", err) + } + api := PublicWhisperAPI{ + w: w, + lastUsed: make(map[string]time.Time), + } + + t1 := [4]byte{0xde, 0xea, 0xbe, 0xef} + t2 := [4]byte{0xca, 0xfe, 0xde, 0xca} + + crit := Criteria{ + SymKeyID: keyID, + Topics: []TopicType{TopicType(t1), TopicType(t2)}, + } + + _, err = api.NewMessageFilter(crit) + if err != nil { + t.Fatalf("Error creating the filter: %v", err) + } + + found := false + candidates := w.filters.getWatchersByTopic(TopicType(t1)) + for _, f := range candidates { + if len(f.Topics) == 2 { + if bytes.Equal(f.Topics[0], t1[:]) && bytes.Equal(f.Topics[1], t2[:]) { + found = true + } + } + } + + if !found { + t.Fatalf("Could not find filter with both topics") + } +} diff --git a/whisper/whisperv6/message.go b/whisper/whisperv6/message.go index b8318cbe8f..2d4e862441 100644 --- a/whisper/whisperv6/message.go +++ b/whisper/whisperv6/message.go @@ -289,7 +289,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte) error { // decryptAsymmetric decrypts an encrypted payload with a private key. func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error { - decrypted, err := ecies.ImportECDSA(key).Decrypt(crand.Reader, msg.Raw, nil, nil) + decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil) if err == nil { msg.Raw = decrypted }