mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-07 22:54:17 -05:00
Merge branch 'master' of github.com:ethereum/go-ethereum
Former-commit-id: 64a62da53a5878450d6115fbc7fec6eeb70c7c2c [formerly 2a2a46b57a6a62b13689578cfcd33c8b8bf0529f] Former-commit-id: 58cdafb64755ab12a765d2156a8eab468989f3a4
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,2 +1,3 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
*.sol linguist-language=Solidity
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
`
|
||||
|
||||
@@ -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: "<datafile>",
|
||||
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: "<dumpfile>",
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
21
core/evm.go
21
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{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +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)
|
||||
}*/
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +build !evmjit
|
||||
|
||||
package vm
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 (<hash>0x01)
|
||||
// Skip any entries that don't look like old transaction meta entries (<hash>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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:]...)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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} }
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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[:])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
78
whisper/whisperv6/api_test.go
Normal file
78
whisper/whisperv6/api_test.go
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user