diff options
-rw-r--r-- | .travis.yml | 4 | ||||
-rw-r--r-- | Makefile | 46 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | accounts/abi/abi.go | 146 | ||||
-rw-r--r-- | accounts/abi/abi_test.go | 47 | ||||
-rw-r--r-- | accounts/abi/argument.go | 48 | ||||
-rw-r--r-- | accounts/abi/method.go | 76 | ||||
-rw-r--r-- | accounts/abi/numbers.go | 2 | ||||
-rw-r--r-- | accounts/abi/type.go | 12 | ||||
-rw-r--r-- | cmd/geth/library.c | 24 | ||||
-rw-r--r-- | cmd/geth/library.go | 46 | ||||
-rw-r--r-- | cmd/geth/main.go | 3 | ||||
-rw-r--r-- | core/blockchain.go | 34 | ||||
-rw-r--r-- | core/blockchain_test.go | 43 | ||||
-rw-r--r-- | core/chain_makers.go | 4 | ||||
-rw-r--r-- | core/events.go | 3 | ||||
-rw-r--r-- | crypto/secp256k1/README.md | 25 | ||||
-rw-r--r-- | crypto/secp256k1/secp256.go | 9 | ||||
-rw-r--r-- | p2p/server.go | 2 |
19 files changed, 417 insertions, 159 deletions
diff --git a/.travis.yml b/.travis.yml index 13211f736..c1d545c54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,10 +20,6 @@ env: global: - secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64=" sudo: false -addons: - apt: - packages: - - libgmp3-dev notifications: webhooks: urls: @@ -7,13 +7,9 @@ .PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64 .PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 .PHONY: geth-windows geth-windows-386 geth-windows-amd64 -.PHONY: geth-android -.PHONY: geth-ios geth-ios-arm-7 geth-ios-arm64 +.PHONY: geth-android geth-ios geth-ios-sim GOBIN = build/bin - -CROSSDEPS = https://gmplib.org/download/gmp/gmp-6.1.0.tar.bz2 -MODE ?= default GO ?= latest geth: @@ -30,12 +26,12 @@ geth-linux: geth-linux-386 geth-linux-amd64 geth-linux-arm @ls -l $(GOBIN)/geth-linux-* geth-linux-386: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/386 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/386 -v $(shell build/flags.sh) ./cmd/geth @echo "Linux 386 cross compilation done:" @ls -l $(GOBIN)/geth-linux-* | grep 386 geth-linux-amd64: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/amd64 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/amd64 -v $(shell build/flags.sh) ./cmd/geth @echo "Linux amd64 cross compilation done:" @ls -l $(GOBIN)/geth-linux-* | grep amd64 @@ -44,22 +40,22 @@ geth-linux-arm: geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-ar @ls -l $(GOBIN)/geth-linux-* | grep arm geth-linux-arm-5: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/arm-5 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-5 -v $(shell build/flags.sh) ./cmd/geth @echo "Linux ARMv5 cross compilation done:" @ls -l $(GOBIN)/geth-linux-* | grep arm-5 geth-linux-arm-6: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/arm-6 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-6 -v $(shell build/flags.sh) ./cmd/geth @echo "Linux ARMv6 cross compilation done:" @ls -l $(GOBIN)/geth-linux-* | grep arm-6 geth-linux-arm-7: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/arm-7 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-7 -v $(shell build/flags.sh) ./cmd/geth @echo "Linux ARMv7 cross compilation done:" @ls -l $(GOBIN)/geth-linux-* | grep arm-7 geth-linux-arm64: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=linux/arm64 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm64 -v $(shell build/flags.sh) ./cmd/geth @echo "Linux ARM64 cross compilation done:" @ls -l $(GOBIN)/geth-linux-* | grep arm64 @@ -68,12 +64,12 @@ geth-darwin: geth-darwin-386 geth-darwin-amd64 @ls -l $(GOBIN)/geth-darwin-* geth-darwin-386: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=darwin/386 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=darwin/386 -v $(shell build/flags.sh) ./cmd/geth @echo "Darwin 386 cross compilation done:" @ls -l $(GOBIN)/geth-darwin-* | grep 386 geth-darwin-amd64: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=darwin/amd64 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=darwin/amd64 -v $(shell build/flags.sh) ./cmd/geth @echo "Darwin amd64 cross compilation done:" @ls -l $(GOBIN)/geth-darwin-* | grep amd64 @@ -82,33 +78,29 @@ geth-windows: geth-windows-386 geth-windows-amd64 @ls -l $(GOBIN)/geth-windows-* geth-windows-386: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=windows/386 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=windows/386 -v $(shell build/flags.sh) ./cmd/geth @echo "Windows 386 cross compilation done:" @ls -l $(GOBIN)/geth-windows-* | grep 386 geth-windows-amd64: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=windows/amd64 -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=windows/amd64 -v $(shell build/flags.sh) ./cmd/geth @echo "Windows amd64 cross compilation done:" @ls -l $(GOBIN)/geth-windows-* | grep amd64 geth-android: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --targets=android/* -v $(shell build/flags.sh) ./cmd/geth + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=android/* -v $(shell build/flags.sh) ./cmd/geth @echo "Android cross compilation done:" @ls -l $(GOBIN)/geth-android-* -geth-ios: geth-ios-arm-7 geth-ios-arm64 - @echo "iOS cross compilation done:" +geth-ios: xgo + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=ios-7.0/* -v $(shell build/flags.sh) ./cmd/geth + @echo "iOS framework cross compilation done:" @ls -l $(GOBIN)/geth-ios-* -geth-ios-arm-7: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --depsargs=--disable-assembly --targets=ios/arm-7 -v $(shell build/flags.sh) ./cmd/geth - @echo "iOS ARMv7 cross compilation done:" - @ls -l $(GOBIN)/geth-ios-* | grep arm-7 - -geth-ios-arm64: xgo - build/env.sh $(GOBIN)/xgo --go=$(GO) --buildmode=$(MODE) --dest=$(GOBIN) --deps=$(CROSSDEPS) --depsargs=--disable-assembly --targets=ios-7.0/arm64 -v $(shell build/flags.sh) ./cmd/geth - @echo "iOS ARM64 cross compilation done:" - @ls -l $(GOBIN)/geth-ios-* | grep arm64 +geth-ios-sim: xgo + build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=ios-7.0/amd64 -v $(shell build/flags.sh) ./cmd/geth + @echo "iOS framework simulator-only cross compilation done:" + @ls -l $(GOBIN)/geth-ios-* evm: build/env.sh $(GOROOT)/bin/go install -v $(shell build/flags.sh) ./cmd/evm @@ -30,7 +30,7 @@ For prerequisites and detailed build instructions please read the [Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum) on the wiki. -Building geth requires two external dependencies, Go and GMP. +Building geth requires both a Go and a C compiler. You can install them using your favourite package manager. Once the dependencies are installed, run diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go index 3f05bfe2d..635dc43fe 100644 --- a/accounts/abi/abi.go +++ b/accounts/abi/abi.go @@ -20,75 +20,17 @@ import ( "encoding/json" "fmt" "io" - "strings" + "math" - "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" ) -// Callable method given a `Name` and whether the method is a constant. -// If the method is `Const` no transaction needs to be created for this -// particular Method call. It can easily be simulated using a local VM. -// For example a `Balance()` method only needs to retrieve something -// from the storage and therefor requires no Tx to be send to the -// network. A method such as `Transact` does require a Tx and thus will -// be flagged `true`. -// Input specifies the required input parameters for this gives method. -type Method struct { - Name string - Const bool - Inputs []Argument - Return Type // not yet implemented -} - -// Returns the methods string signature according to the ABI spec. -// -// Example -// -// function foo(uint32 a, int b) = "foo(uint32,int256)" -// -// Please note that "int" is substitute for its canonical representation "int256" -func (m Method) String() (out string) { - out += m.Name - types := make([]string, len(m.Inputs)) - i := 0 - for _, input := range m.Inputs { - types[i] = input.Type.String() - i++ - } - out += "(" + strings.Join(types, ",") + ")" - - return -} - -func (m Method) Id() []byte { - return crypto.Sha3([]byte(m.String()))[:4] -} - -// Argument holds the name of the argument and the corresponding type. -// Types are used when packing and testing arguments. -type Argument struct { - Name string - Type Type -} - -func (a *Argument) UnmarshalJSON(data []byte) error { - var extarg struct { - Name string - Type string - } - err := json.Unmarshal(data, &extarg) - if err != nil { - return fmt.Errorf("argument json err: %v", err) - } - - a.Type, err = NewType(extarg.Type) - if err != nil { - return err - } - a.Name = extarg.Name - - return nil -} +// Executer is an executer method for performing state executions. It takes one +// argument which is the input data and expects output data to be returned as +// multiple 32 byte word length concatenated slice +type Executer func(datain []byte) []byte // The ABI holds information about a contract's context and available // invokable methods. It will allow you to type check function calls and @@ -97,6 +39,18 @@ type ABI struct { Methods map[string]Method } +// JSON returns a parsed ABI interface and error if it failed. +func JSON(reader io.Reader) (ABI, error) { + dec := json.NewDecoder(reader) + + var abi ABI + if err := dec.Decode(&abi); err != nil { + return ABI{}, err + } + + return abi, nil +} + // tests, tests whether the given input would result in a successful // call. Checks argument list count and matches input to `input`. func (abi ABI) pack(name string, args ...interface{}) ([]byte, error) { @@ -145,6 +99,55 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { return packed, nil } +// toGoType parses the input and casts it to the proper type defined by the ABI +// argument in t. +func toGoType(t Argument, input []byte) interface{} { + switch t.Type.T { + case IntTy: + return common.BytesToBig(input) + case UintTy: + return common.BytesToBig(input) + case BoolTy: + return common.BytesToBig(input).Uint64() > 0 + case AddressTy: + return common.BytesToAddress(input) + case HashTy: + return common.BytesToHash(input) + } + return nil +} + +// Call executes a call and attemps to parse the return values and returns it as +// an interface. It uses the executer method to perform the actual call since +// the abi knows nothing of the lower level calling mechanism. +// +// Call supports all abi types and includes multiple return values. When only +// one item is returned a single interface{} will be returned, if a contract +// method returns multiple values an []interface{} slice is returned. +func (abi ABI) Call(executer Executer, name string, args ...interface{}) interface{} { + callData, err := abi.Pack(name, args...) + if err != nil { + glog.V(logger.Debug).Infoln("pack error:", err) + return nil + } + + output := executer(callData) + + method := abi.Methods[name] + ret := make([]interface{}, int(math.Max(float64(len(method.Outputs)), float64(len(output)/32)))) + for i := 0; i < len(ret); i += 32 { + index := i / 32 + ret[index] = toGoType(method.Outputs[index], output[i:i+32]) + } + + // return single interface + if len(ret) == 1 { + return ret[0] + } + + return ret +} + func (abi *ABI) UnmarshalJSON(data []byte) error { var methods []Method if err := json.Unmarshal(data, &methods); err != nil { @@ -158,14 +161,3 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { return nil } - -func JSON(reader io.Reader) (ABI, error) { - dec := json.NewDecoder(reader) - - var abi ABI - if err := dec.Decode(&abi); err != nil { - return ABI{}, err - } - - return abi, nil -} diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go index 96dd3ee62..d514fb8c7 100644 --- a/accounts/abi/abi_test.go +++ b/accounts/abi/abi_test.go @@ -92,12 +92,12 @@ func TestReader(t *testing.T) { exp := ABI{ Methods: map[string]Method{ "balance": Method{ - "balance", true, nil, Type{}, + "balance", true, nil, nil, }, "send": Method{ "send", false, []Argument{ Argument{"amount", Uint256}, - }, Type{}, + }, nil, }, }, } @@ -238,10 +238,10 @@ func TestTestAddress(t *testing.T) { func TestMethodSignature(t *testing.T) { String, _ := NewType("string") String32, _ := NewType("string32") - m := Method{"foo", false, []Argument{Argument{"bar", String32}, Argument{"baz", String}}, Type{}} + m := Method{"foo", false, []Argument{Argument{"bar", String32}, Argument{"baz", String}}, nil} exp := "foo(string32,string)" - if m.String() != exp { - t.Error("signature mismatch", exp, "!=", m.String()) + if m.Sig() != exp { + t.Error("signature mismatch", exp, "!=", m.Sig()) } idexp := crypto.Sha3([]byte(exp))[:4] @@ -250,10 +250,10 @@ func TestMethodSignature(t *testing.T) { } uintt, _ := NewType("uint") - m = Method{"foo", false, []Argument{Argument{"bar", uintt}}, Type{}} + m = Method{"foo", false, []Argument{Argument{"bar", uintt}}, nil} exp = "foo(uint256)" - if m.String() != exp { - t.Error("signature mismatch", exp, "!=", m.String()) + if m.Sig() != exp { + t.Error("signature mismatch", exp, "!=", m.Sig()) } } @@ -393,3 +393,34 @@ func TestBytes(t *testing.T) { t.Error("expected error") } } + +func TestReturn(t *testing.T) { + const definition = `[ + { "name" : "balance", "const" : true, "inputs" : [], "outputs" : [ { "name": "", "type": "hash" } ] }, + { "name" : "name", "const" : true, "inputs" : [], "outputs" : [ { "name": "", "type": "address" } ] } + +]` + + abi, err := JSON(strings.NewReader(definition)) + if err != nil { + t.Fatal(err) + } + + r := abi.Call(func([]byte) []byte { + t := make([]byte, 32) + t[0] = 1 + return t + }, "balance") + if _, ok := r.(common.Hash); !ok { + t.Errorf("expected type common.Hash, got %T", r) + } + + r = abi.Call(func([]byte) []byte { + t := make([]byte, 32) + t[0] = 1 + return t + }, "name") + if _, ok := r.(common.Address); !ok { + t.Errorf("expected type common.Address, got %T", r) + } +} diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go new file mode 100644 index 000000000..8907b2979 --- /dev/null +++ b/accounts/abi/argument.go @@ -0,0 +1,48 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package abi + +import ( + "encoding/json" + "fmt" +) + +// Argument holds the name of the argument and the corresponding type. +// Types are used when packing and testing arguments. +type Argument struct { + Name string + Type Type +} + +func (a *Argument) UnmarshalJSON(data []byte) error { + var extarg struct { + Name string + Type string + } + err := json.Unmarshal(data, &extarg) + if err != nil { + return fmt.Errorf("argument json err: %v", err) + } + + a.Type, err = NewType(extarg.Type) + if err != nil { + return err + } + a.Name = extarg.Name + + return nil +} diff --git a/accounts/abi/method.go b/accounts/abi/method.go new file mode 100644 index 000000000..63194e788 --- /dev/null +++ b/accounts/abi/method.go @@ -0,0 +1,76 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package abi + +import ( + "fmt" + "strings" + + "github.com/ethereum/go-ethereum/crypto" +) + +// Callable method given a `Name` and whether the method is a constant. +// If the method is `Const` no transaction needs to be created for this +// particular Method call. It can easily be simulated using a local VM. +// For example a `Balance()` method only needs to retrieve something +// from the storage and therefor requires no Tx to be send to the +// network. A method such as `Transact` does require a Tx and thus will +// be flagged `true`. +// Input specifies the required input parameters for this gives method. +type Method struct { + Name string + Const bool + Inputs []Argument + Outputs []Argument +} + +// Sig returns the methods string signature according to the ABI spec. +// +// Example +// +// function foo(uint32 a, int b) = "foo(uint32,int256)" +// +// Please note that "int" is substitute for its canonical representation "int256" +func (m Method) Sig() string { + types := make([]string, len(m.Inputs)) + i := 0 + for _, input := range m.Inputs { + types[i] = input.Type.String() + i++ + } + return fmt.Sprintf("%v(%v)", m.Name, strings.Join(types, ",")) +} + +func (m Method) String() string { + inputs := make([]string, len(m.Inputs)) + for i, input := range m.Inputs { + inputs[i] = fmt.Sprintf("%v %v", input.Name, input.Type) + } + outputs := make([]string, len(m.Outputs)) + for i, output := range m.Outputs { + if len(output.Name) > 0 { + outputs[i] = fmt.Sprintf("%v ", output.Name) + } + outputs[i] += output.Type.String() + } + + return fmt.Sprintf("function %v(%v) returns(%v)", m.Name, strings.Join(inputs, ", "), strings.Join(outputs, ", ")) +} + +func (m Method) Id() []byte { + return crypto.Sha3([]byte(m.Sig()))[:4] +} diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go index 2a7049425..c37cd5f68 100644 --- a/accounts/abi/numbers.go +++ b/accounts/abi/numbers.go @@ -37,6 +37,8 @@ var int8_t = reflect.TypeOf(int8(0)) var int16_t = reflect.TypeOf(int16(0)) var int32_t = reflect.TypeOf(int32(0)) var int64_t = reflect.TypeOf(int64(0)) +var hash_t = reflect.TypeOf(common.Hash{}) +var address_t = reflect.TypeOf(common.Address{}) var uint_ts = reflect.TypeOf([]uint(nil)) var uint8_ts = reflect.TypeOf([]uint8(nil)) diff --git a/accounts/abi/type.go b/accounts/abi/type.go index 16d7491e7..8f0238fc9 100644 --- a/accounts/abi/type.go +++ b/accounts/abi/type.go @@ -31,6 +31,7 @@ const ( BoolTy SliceTy AddressTy + HashTy RealTy ) @@ -121,7 +122,7 @@ func NewType(t string) (typ Type, err error) { typ.Kind = reflect.Invalid case "address": typ.Kind = reflect.Slice - typ.Type = byte_ts + typ.Type = address_t typ.Size = 20 typ.T = AddressTy case "string": @@ -130,6 +131,11 @@ func NewType(t string) (typ Type, err error) { if vsize > 0 { typ.Size = 32 } + case "hash": + typ.Kind = reflect.Slice + typ.Size = 32 + typ.Type = hash_t + typ.T = HashTy case "bytes": typ.Kind = reflect.Slice typ.Type = byte_ts @@ -206,9 +212,9 @@ func (t Type) pack(v interface{}) ([]byte, error) { } case reflect.Array: if v, ok := value.Interface().(common.Address); ok { - return t.pack(v[:]) + return common.LeftPadBytes(v[:], 32), nil } else if v, ok := value.Interface().(common.Hash); ok { - return t.pack(v[:]) + return v[:], nil } } diff --git a/cmd/geth/library.c b/cmd/geth/library.c new file mode 100644 index 000000000..f738621a8 --- /dev/null +++ b/cmd/geth/library.c @@ -0,0 +1,24 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// Simple wrapper to translate the API exposed methods and types to inthernal +// Go versions of the same types. + +#include "_cgo_export.h" + +int run(const char* args) { + return doRun((char*)args); +} diff --git a/cmd/geth/library.go b/cmd/geth/library.go new file mode 100644 index 000000000..b8ffaaed7 --- /dev/null +++ b/cmd/geth/library.go @@ -0,0 +1,46 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// Contains a simple library definition to allow creating a Geth instance from +// straight C code. + +package main + +// #ifdef __cplusplus +// extern "C" { +// #endif +// +// extern int run(const char*); +// +// #ifdef __cplusplus +// } +// #endif +import "C" +import ( + "fmt" + "os" + "strings" +) + +//export doRun +func doRun(args *C.char) C.int { + // This is equivalent to geth.main, just modified to handle the function arg passing + if err := app.Run(strings.Split("geth "+C.GoString(args), " ")); err != nil { + fmt.Fprintln(os.Stderr, err) + return -1 + } + return 0 +} diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 6ec30cebc..8798bbb27 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -340,6 +340,8 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.ExtraDataFlag, } app.Before = func(ctx *cli.Context) error { + runtime.GOMAXPROCS(runtime.NumCPU()) + utils.SetupLogger(ctx) utils.SetupNetwork(ctx) utils.SetupVM(ctx) @@ -353,7 +355,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso } func main() { - runtime.GOMAXPROCS(runtime.NumCPU()) defer logger.Flush() if err := app.Run(os.Args); err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/core/blockchain.go b/core/blockchain.go index 5a6795b3e..9d526e352 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -980,6 +980,18 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain glog.Fatal(errs[index]) return } + if err := WriteTransactions(self.chainDb, block); err != nil { + errs[index] = fmt.Errorf("failed to write individual transactions: %v", err) + atomic.AddInt32(&failed, 1) + glog.Fatal(errs[index]) + return + } + if err := WriteReceipts(self.chainDb, receipts); err != nil { + errs[index] = fmt.Errorf("failed to write individual receipts: %v", err) + atomic.AddInt32(&failed, 1) + glog.Fatal(errs[index]) + return + } atomic.AddInt32(&stats.processed, 1) } } @@ -1240,6 +1252,17 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { oldStart = oldBlock newStart = newBlock deletedTxs types.Transactions + deletedLogs vm.Logs + // collectLogs collects the logs that were generated during the + // processing of the block that corresponds with the given hash. + // These logs are later announced as deleted. + collectLogs = func(h common.Hash) { + // Coalesce logs + receipts := GetBlockReceipts(self.chainDb, h) + for _, receipt := range receipts { + deletedLogs = append(deletedLogs, receipt.Logs...) + } + } ) // first reduce whoever is higher bound @@ -1247,6 +1270,8 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { // reduce old chain for oldBlock = oldBlock; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = self.GetBlock(oldBlock.ParentHash()) { deletedTxs = append(deletedTxs, oldBlock.Transactions()...) + + collectLogs(oldBlock.Hash()) } } else { // reduce new chain and append new chain blocks for inserting later on @@ -1269,6 +1294,7 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { } newChain = append(newChain, newBlock) deletedTxs = append(deletedTxs, oldBlock.Transactions()...) + collectLogs(oldBlock.Hash()) oldBlock, newBlock = self.GetBlock(oldBlock.ParentHash()), self.GetBlock(newBlock.ParentHash()) if oldBlock == nil { @@ -1302,7 +1328,6 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil { return err } - addedTxs = append(addedTxs, block.Transactions()...) } @@ -1316,7 +1341,12 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { } // Must be posted in a goroutine because of the transaction pool trying // to acquire the chain manager lock - go self.eventMux.Post(RemovedTransactionEvent{diff}) + if len(diff) > 0 { + go self.eventMux.Post(RemovedTransactionEvent{diff}) + } + if len(deletedLogs) > 0 { + go self.eventMux.Post(RemovedLogEvent{deletedLogs}) + } return nil } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 6e1c5fdc7..b4ac1696a 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -963,3 +963,46 @@ func TestChainTxReorgs(t *testing.T) { } } } + +func TestLogReorgs(t *testing.T) { + params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be. + params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block. + + var ( + key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + addr1 = crypto.PubkeyToAddress(key1.PublicKey) + db, _ = ethdb.NewMemDatabase() + // this code generates a log + code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") + ) + genesis := WriteGenesisBlockForTesting(db, + GenesisAccount{addr1, big.NewInt(10000000000000)}, + ) + + evmux := &event.TypeMux{} + blockchain, _ := NewBlockChain(db, FakePow{}, evmux) + + subs := evmux.Subscribe(RemovedLogEvent{}) + chain, _ := GenerateChain(genesis, db, 2, func(i int, gen *BlockGen) { + if i == 1 { + tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code).SignECDSA(key1) + if err != nil { + t.Fatalf("failed to create tx: %v", err) + } + gen.AddTx(tx) + } + }) + if _, err := blockchain.InsertChain(chain); err != nil { + t.Fatalf("failed to insert chain: %v", err) + } + + chain, _ = GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {}) + if _, err := blockchain.InsertChain(chain); err != nil { + t.Fatalf("failed to insert forked chain: %v", err) + } + + ev := <-subs.Chan() + if len(ev.Data.(RemovedLogEvent).Logs) == 0 { + t.Error("expected logs") + } +} diff --git a/core/chain_makers.go b/core/chain_makers.go index 6d3152d97..4f6fa3989 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -90,6 +90,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) { if b.gasPool == nil { b.SetCoinbase(common.Address{}) } + b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs)) _, gas, err := ApplyMessage(NewEnv(b.statedb, nil, tx, b.header), tx, b.gasPool) if err != nil { panic(err) @@ -97,8 +98,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) { root := b.statedb.IntermediateRoot() b.header.GasUsed.Add(b.header.GasUsed, gas) receipt := types.NewReceipt(root.Bytes(), b.header.GasUsed) - logs := b.statedb.GetLogs(tx.Hash()) - receipt.Logs = logs + receipt.Logs = b.statedb.GetLogs(tx.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) b.txs = append(b.txs, tx) b.receipts = append(b.receipts, receipt) diff --git a/core/events.go b/core/events.go index 8cf230dda..1a760c71c 100644 --- a/core/events.go +++ b/core/events.go @@ -39,6 +39,9 @@ type NewMinedBlockEvent struct{ Block *types.Block } // RemovedTransactionEvent is posted when a reorg happens type RemovedTransactionEvent struct{ Txs types.Transactions } +// RemovedLogEvent is posted when a reorg happens +type RemovedLogEvent struct{ Logs vm.Logs } + // ChainSplit is posted when a new head is detected type ChainSplitEvent struct { Block *types.Block diff --git a/crypto/secp256k1/README.md b/crypto/secp256k1/README.md deleted file mode 100644 index 5a86147d4..000000000 --- a/crypto/secp256k1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -secp256k1-go -======= - -golang secp256k1 library - -Implements cryptographic operations for the secp256k1 ECDSA curve used by Bitcoin. - -Installing -=== - -GMP library headers are required to build. On Debian-based systems, the package is called `libgmp-dev`. - -``` -sudo apt-get install libgmp-dev -``` - -Now compiles with cgo! - -Test -=== - -To run tests do -``` -go tests -```
\ No newline at end of file diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go index 8dc248145..97b4bd8da 100644 --- a/crypto/secp256k1/secp256.go +++ b/crypto/secp256k1/secp256.go @@ -21,14 +21,7 @@ package secp256k1 /* #cgo CFLAGS: -I./libsecp256k1 #cgo CFLAGS: -I./libsecp256k1/src/ -#cgo darwin CFLAGS: -I/usr/local/include -#cgo freebsd CFLAGS: -I/usr/local/include -#cgo linux,arm CFLAGS: -I/usr/local/arm/include -#cgo LDFLAGS: -lgmp -#cgo darwin LDFLAGS: -L/usr/local/lib -#cgo freebsd LDFLAGS: -L/usr/local/lib -#cgo linux,arm LDFLAGS: -L/usr/local/arm/lib -#define USE_NUM_GMP +#define USE_NUM_NONE #define USE_FIELD_10X26 #define USE_FIELD_INV_BUILTIN #define USE_SCALAR_8X32 diff --git a/p2p/server.go b/p2p/server.go index ee670b10e..7991585f1 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -337,7 +337,7 @@ func (srv *Server) Start() (err error) { srv.ntab = ntab } - dynPeers := srv.MaxPeers / 2 + dynPeers := (srv.MaxPeers + 1) / 2 if !srv.Discovery { dynPeers = 0 } |