diff options
37 files changed, 400 insertions, 234 deletions
diff --git a/accounts/errors.go b/accounts/errors.go index 9ecc1eafd..64da8821c 100644 --- a/accounts/errors.go +++ b/accounts/errors.go @@ -38,7 +38,7 @@ var ErrNotSupported = errors.New("not supported") var ErrInvalidPassphrase = errors.New("invalid passphrase") // ErrWalletAlreadyOpen is returned if a wallet is attempted to be opened the -// secodn time. +// second time. var ErrWalletAlreadyOpen = errors.New("wallet already open") // ErrWalletClosed is returned if a wallet is attempted to be opened the diff --git a/cmd/evm/json_logger.go b/cmd/evm/json_logger.go new file mode 100644 index 000000000..a84d5daeb --- /dev/null +++ b/cmd/evm/json_logger.go @@ -0,0 +1,60 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package main + +import ( + "encoding/json" + "io" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/vm" +) + +type JSONLogger struct { + encoder *json.Encoder +} + +func NewJSONLogger(writer io.Writer) *JSONLogger { + return &JSONLogger{json.NewEncoder(writer)} +} + +// CaptureState outputs state information on the logger. +func (l *JSONLogger) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { + return l.encoder.Encode(vm.StructLog{ + Pc: pc, + Op: op, + Gas: gas + cost, + GasCost: cost, + Memory: memory.Data(), + Stack: stack.Data(), + Storage: nil, + Depth: depth, + Err: err, + }) +} + +// CaptureEnd is triggered at end of execution. +func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error { + type endLog struct { + Output string `json:"output"` + GasUsed math.HexOrDecimal64 `json:"gasUsed"` + Time time.Duration `json:"time"` + } + return l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), t}) +} diff --git a/cmd/evm/main.go b/cmd/evm/main.go index e85d31d03..48a1b92cb 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -90,6 +90,18 @@ var ( Name: "nogasmetering", Usage: "disable gas metering", } + GenesisFlag = cli.StringFlag{ + Name: "prestate", + Usage: "JSON file with prestate (genesis) config", + } + MachineFlag = cli.BoolFlag{ + Name: "json", + Usage: "output trace logs in machine readable format (json)", + } + SenderFlag = cli.StringFlag{ + Name: "sender", + Usage: "The transaction origin", + } ) func init() { @@ -108,6 +120,9 @@ func init() { MemProfileFlag, CPUProfileFlag, StatDumpFlag, + GenesisFlag, + MachineFlag, + SenderFlag, } app.Commands = []cli.Command{ compileCommand, diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 22538d7b1..b1fb8998f 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -18,6 +18,7 @@ package main import ( "bytes" + "encoding/json" "fmt" "io/ioutil" "os" @@ -29,11 +30,13 @@ import ( "github.com/ethereum/go-ethereum/cmd/evm/internal/compiler" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm/runtime" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" cli "gopkg.in/urfave/cli.v1" ) @@ -45,17 +48,59 @@ var runCommand = cli.Command{ Description: `The run command runs arbitrary EVM code.`, } +// readGenesis will read the given JSON format genesis file and return +// the initialized Genesis structure +func readGenesis(genesisPath string) *core.Genesis { + // Make sure we have a valid genesis JSON + //genesisPath := ctx.Args().First() + if len(genesisPath) == 0 { + utils.Fatalf("Must supply path to genesis JSON file") + } + file, err := os.Open(genesisPath) + if err != nil { + utils.Fatalf("Failed to read genesis file: %v", err) + } + defer file.Close() + + genesis := new(core.Genesis) + if err := json.NewDecoder(file).Decode(genesis); err != nil { + utils.Fatalf("invalid genesis file: %v", err) + } + return genesis +} + func runCmd(ctx *cli.Context) error { glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) log.Root().SetHandler(glogger) var ( - db, _ = ethdb.NewMemDatabase() - statedb, _ = state.New(common.Hash{}, db) - sender = common.StringToAddress("sender") - logger = vm.NewStructLogger(nil) + tracer vm.Tracer + debugLogger *vm.StructLogger + statedb *state.StateDB + chainConfig *params.ChainConfig + sender = common.StringToAddress("sender") ) + if ctx.GlobalBool(MachineFlag.Name) { + tracer = NewJSONLogger(os.Stdout) + } else if ctx.GlobalBool(DebugFlag.Name) { + debugLogger = vm.NewStructLogger(nil) + tracer = debugLogger + } else { + debugLogger = vm.NewStructLogger(nil) + } + if ctx.GlobalString(GenesisFlag.Name) != "" { + gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) + _, statedb = gen.ToBlock() + chainConfig = gen.Config + } else { + var db, _ = ethdb.NewMemDatabase() + statedb, _ = state.New(common.Hash{}, db) + } + if ctx.GlobalString(SenderFlag.Name) != "" { + sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) + } + statedb.CreateAccount(sender) var ( @@ -95,16 +140,16 @@ func runCmd(ctx *cli.Context) error { } code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n"))) } - + initialGas := ctx.GlobalUint64(GasFlag.Name) runtimeConfig := runtime.Config{ Origin: sender, State: statedb, - GasLimit: ctx.GlobalUint64(GasFlag.Name), + GasLimit: initialGas, GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), Value: utils.GlobalBig(ctx, ValueFlag.Name), EVMConfig: vm.Config{ - Tracer: logger, - Debug: ctx.GlobalBool(DebugFlag.Name), + Tracer: tracer, + Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name), }, } @@ -122,15 +167,19 @@ func runCmd(ctx *cli.Context) error { defer pprof.StopCPUProfile() } + if chainConfig != nil { + runtimeConfig.ChainConfig = chainConfig + } tstart := time.Now() + var leftOverGas uint64 if ctx.GlobalBool(CreateFlag.Name) { input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) - ret, _, err = runtime.Create(input, &runtimeConfig) + ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) } else { receiver := common.StringToAddress("receiver") statedb.SetCode(receiver, code) - ret, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) + ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) } execTime := time.Since(tstart) @@ -153,8 +202,10 @@ func runCmd(ctx *cli.Context) error { } if ctx.GlobalBool(DebugFlag.Name) { - fmt.Fprintln(os.Stderr, "#### TRACE ####") - vm.WriteTrace(os.Stderr, logger.StructLogs()) + if debugLogger != nil { + fmt.Fprintln(os.Stderr, "#### TRACE ####") + vm.WriteTrace(os.Stderr, debugLogger.StructLogs()) + } fmt.Fprintln(os.Stderr, "#### LOGS ####") vm.WriteLogs(os.Stderr, statedb.Logs()) } @@ -167,14 +218,18 @@ heap objects: %d allocations: %d total allocations: %d GC calls: %d +Gas used: %d -`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC) +`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) + } + if tracer != nil { + tracer.CaptureEnd(ret, initialGas-leftOverGas, execTime) + } else { + fmt.Printf("0x%x\n", ret) } - fmt.Printf("0x%x", ret) if err != nil { - fmt.Printf(" error: %v", err) + fmt.Printf(" error: %v\n", err) } - fmt.Println() return nil } diff --git a/cmd/swarm/upload.go b/cmd/swarm/upload.go index 42673ae21..9f4c525bb 100644 --- a/cmd/swarm/upload.go +++ b/cmd/swarm/upload.go @@ -18,6 +18,7 @@ package main import ( + "errors" "fmt" "io" "io/ioutil" @@ -87,24 +88,32 @@ func upload(ctx *cli.Context) { if err != nil { utils.Fatalf("Error opening file: %s", err) } - var hash string + + // define a function which either uploads a directory or single file + // based on the type of the file being uploaded + var doUpload func() (hash string, err error) if stat.IsDir() { - if !recursive { - utils.Fatalf("Argument is a directory and recursive upload is disabled") + doUpload = func() (string, error) { + if !recursive { + return "", errors.New("Argument is a directory and recursive upload is disabled") + } + return client.UploadDirectory(file, defaultPath, "") } - hash, err = client.UploadDirectory(file, defaultPath, "") } else { - if mimeType == "" { - mimeType = detectMimeType(file) - } - f, err := swarm.Open(file) - if err != nil { - utils.Fatalf("Error opening file: %s", err) + doUpload = func() (string, error) { + f, err := swarm.Open(file) + if err != nil { + return "", fmt.Errorf("error opening file: %s", err) + } + defer f.Close() + if mimeType == "" { + mimeType = detectMimeType(file) + } + f.ContentType = mimeType + return client.Upload(f, "") } - defer f.Close() - f.ContentType = mimeType - hash, err = client.Upload(f, "") } + hash, err := doUpload() if err != nil { utils.Fatalf("Upload failed: %s", err) } diff --git a/compression/rle/read_write_test.go b/compression/rle/read_write_test.go index 20a23a196..b36f7907b 100644 --- a/compression/rle/read_write_test.go +++ b/compression/rle/read_write_test.go @@ -33,102 +33,18 @@ func (s *CompressionRleSuite) TestDecompressSimple(c *checker.C) { res, err := Decompress([]byte{token, 0xfd}) c.Assert(err, checker.IsNil) c.Assert(res, checker.DeepEquals, exp) - // if bytes.Compare(res, exp) != 0 { - // t.Error("empty sha3", res) - // } exp = []byte{0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x1, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21} res, err = Decompress([]byte{token, 0xfe}) c.Assert(err, checker.IsNil) c.Assert(res, checker.DeepEquals, exp) - // if bytes.Compare(res, exp) != 0 { - // t.Error("0x80 sha3", res) - // } res, err = Decompress([]byte{token, 0xff}) c.Assert(err, checker.IsNil) c.Assert(res, checker.DeepEquals, []byte{token}) - // if bytes.Compare(res, []byte{token}) != 0 { - // t.Error("token", res) - // } res, err = Decompress([]byte{token, 12}) c.Assert(err, checker.IsNil) c.Assert(res, checker.DeepEquals, make([]byte, 10)) - // if bytes.Compare(res, make([]byte, 10)) != 0 { - // t.Error("10 * zero", res) - // } -} - -// func TestDecompressMulti(t *testing.T) { -// res, err := Decompress([]byte{token, 0xfd, token, 0xfe, token, 12}) -// if err != nil { -// t.Error(err) -// } - -// var exp []byte -// exp = append(exp, crypto.Keccak256([]byte(""))...) -// exp = append(exp, crypto.Keccak256([]byte{0x80})...) -// exp = append(exp, make([]byte, 10)...) - -// if bytes.Compare(res, res) != 0 { -// t.Error("Expected", exp, "result", res) -// } -// } - -// func TestCompressSimple(t *testing.T) { -// res := Compress([]byte{0, 0, 0, 0, 0}) -// if bytes.Compare(res, []byte{token, 7}) != 0 { -// t.Error("5 * zero", res) -// } - -// res = Compress(crypto.Keccak256([]byte(""))) -// if bytes.Compare(res, []byte{token, emptyShaToken}) != 0 { -// t.Error("empty sha", res) -// } - -// res = Compress(crypto.Keccak256([]byte{0x80})) -// if bytes.Compare(res, []byte{token, emptyListShaToken}) != 0 { -// t.Error("empty list sha", res) -// } -// res = Compress([]byte{token}) -// if bytes.Compare(res, []byte{token, tokenToken}) != 0 { -// t.Error("token", res) -// } -// } - -// func TestCompressMulti(t *testing.T) { -// in := []byte{0, 0, 0, 0, 0} -// in = append(in, crypto.Keccak256([]byte(""))...) -// in = append(in, crypto.Keccak256([]byte{0x80})...) -// in = append(in, token) -// res := Compress(in) - -// exp := []byte{token, 7, token, emptyShaToken, token, emptyListShaToken, token, tokenToken} -// if bytes.Compare(res, exp) != 0 { -// t.Error("expected", exp, "got", res) -// } -// } - -// func TestCompressDecompress(t *testing.T) { -// var in []byte - -// for i := 0; i < 20; i++ { -// in = append(in, []byte{0, 0, 0, 0, 0}...) -// in = append(in, crypto.Keccak256([]byte(""))...) -// in = append(in, crypto.Keccak256([]byte{0x80})...) -// in = append(in, []byte{123, 2, 19, 89, 245, 254, 255, token, 98, 233}...) -// in = append(in, token) -// } - -// c := Compress(in) -// d, err := Decompress(c) -// if err != nil { -// t.Error(err) -// } - -// if bytes.Compare(d, in) != 0 { -// t.Error("multi failed\n", d, "\n", in) -// } -// } +} diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 87a983377..5a50b2eb4 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -76,7 +76,7 @@ var ( errUnknownBlock = errors.New("unknown block") // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition - // block has a beneficiary set to non zeroes. + // block has a beneficiary set to non-zeroes. errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") // errInvalidVote is returned if a nonce value is something else that the two @@ -84,7 +84,7 @@ var ( errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block - // has a vote nonce set to non zeroes. + // has a vote nonce set to non-zeroes. errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") // errMissingVanity is returned if a block's extra-data section is shorter than @@ -104,7 +104,7 @@ var ( // ones). drrInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") - // errInvalidMixDigest is returned if a block's mix digest is non zero. + // errInvalidMixDigest is returned if a block's mix digest is non-zero. errInvalidMixDigest = errors.New("non-zero mix digest") // errInvalidUncleHash is returned if a block contains an non-empty uncle list. @@ -122,7 +122,7 @@ var ( // be modified via out-of-range or non-contiguous headers. errInvalidVotingChain = errors.New("invalid voting chain") - // errUnauthorized is returned if a header is signed by a non authorized entity. + // errUnauthorized is returned if a header is signed by a non-authorized entity. errUnauthorized = errors.New("unauthorized") ) @@ -499,7 +499,7 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) error { - // If the block isn't a checkpoint, cast a random vote (good enough fror now) + // If the block isn't a checkpoint, cast a random vote (good enough for now) header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} @@ -601,7 +601,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, stop <-ch if _, authorized := snap.Signers[signer]; !authorized { return nil, errUnauthorized } - // If we're amongs the recent signers, wait for the next block + // If we're amongst the recent signers, wait for the next block for seen, recent := range snap.Recents { if recent == signer { // Signer is among recents, only wait if the current block doens't shift it out diff --git a/consensus/clique/snapshot.go b/consensus/clique/snapshot.go index fb86bc5e6..8eaf3b62e 100644 --- a/consensus/clique/snapshot.go +++ b/consensus/clique/snapshot.go @@ -39,7 +39,7 @@ type Vote struct { // Tally is a simple vote tally to keep the current score of votes. Votes that // go against the proposal aren't counted since it's equivalent to not voting. type Tally struct { - Authorize bool `json:"authorize"` // Whether the vote it about authorizing or kicking someone + Authorize bool `json:"authorize"` // Whether the vote is about authorizing or kicking someone Votes int `json:"votes"` // Number of votes until now wanting to pass the proposal } @@ -56,7 +56,7 @@ type Snapshot struct { Tally map[common.Address]Tally `json:"tally"` // Current vote tally to avoid recalculating } -// newSnapshot create a new snapshot with the specified startup parameters. This +// newSnapshot creates a new snapshot with the specified startup parameters. This // method does not initialize the set of recent signers, so only ever use if for // the genesis block. func newSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot { diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index 49a1d7d5b..f18934b89 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -243,7 +243,7 @@ func TestVoting(t *testing.T) { }, results: []string{"A", "B"}, }, { - // Cascading changes are not allowed, only the the account being voted on may change + // Cascading changes are not allowed, only the account being voted on may change signers: []string{"A", "B", "C", "D"}, votes: []testerVote{ {signer: "A", voted: "C", auth: false}, @@ -293,7 +293,7 @@ func TestVoting(t *testing.T) { results: []string{"A", "B", "C"}, }, { // Ensure that pending votes don't survive authorization status changes. This - // corner case can only appear if a signer is quickly added, remove and then + // corner case can only appear if a signer is quickly added, removed and then // readded (or the inverse), while one of the original voters dropped. If a // past vote is left cached in the system somewhere, this will interfere with // the final signer outcome. diff --git a/consensus/consensus.go b/consensus/consensus.go index 8cbd32c88..865238cee 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -79,8 +79,7 @@ type Engine interface { // Finalize runs any post-transaction state modifications (e.g. block rewards) // and assembles the final block. - // - // Note, the block header and state database might be updated to reflect any + // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) diff --git a/consensus/ethash/algorithm.go b/consensus/ethash/algorithm.go index 365fe5520..a737bc636 100644 --- a/consensus/ethash/algorithm.go +++ b/consensus/ethash/algorithm.go @@ -53,7 +53,6 @@ type hasher func(dest []byte, data []byte) // makeHasher creates a repetitive hasher, allowing the same hash data structures // to be reused between hash runs instead of requiring new ones to be created. -// // The returned function is not thread safe! func makeHasher(h hash.Hash) hasher { return func(dest []byte, data []byte) { @@ -82,7 +81,6 @@ func seedHash(block uint64) []byte { // memory, then performing two passes of Sergio Demian Lerner's RandMemoHash // algorithm from Strict Memory Hard Hashing Functions (2014). The output is a // set of 524288 64-byte values. -// // This method places the result into dest in machine byte order. func generateCache(dest []uint32, epoch uint64, seed []byte) { // Print some debug logs to allow analysis on low end devices @@ -220,7 +218,6 @@ func generateDatasetItem(cache []uint32, index uint32, keccak512 hasher) []byte } // generateDataset generates the entire ethash dataset for mining. -// // This method places the result into dest in machine byte order. func generateDataset(dest []uint32, epoch uint64, cache []uint32) { // Print some debug logs to allow analysis on low end devices diff --git a/consensus/ethash/algorithm_go1.8_test.go b/consensus/ethash/algorithm_go1.8_test.go index fdc302318..a822944a6 100644 --- a/consensus/ethash/algorithm_go1.8_test.go +++ b/consensus/ethash/algorithm_go1.8_test.go @@ -20,7 +20,7 @@ package ethash import "testing" -// Tests whether the dataset size calculator work correctly by cross checking the +// Tests whether the dataset size calculator works correctly by cross checking the // hard coded lookup table with the value generated by it. func TestSizeCalculations(t *testing.T) { var tests []uint64 diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index a6c1432e3..dd9c81fd4 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -218,7 +218,6 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo // verifyHeader checks whether a header conforms to the consensus rules of the // stock Ethereum ethash engine. -// // See YP section 4.3.4. "Block Header Validity" func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { // Ensure that the header's extra-data section is of a reasonable size @@ -286,7 +285,6 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * // CalcDifficulty is the difficulty adjustment algorithm. It returns // the difficulty that a new block should have when created at time // given the parent block's time and difficulty. -// // TODO (karalabe): Move the chain maker into this package and make this private! func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { next := new(big.Int).Add(parent.Number, common.Big1) @@ -462,7 +460,6 @@ var ( // AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded. -// // TODO (karalabe): Move the chain maker into this package and make this private! func AccumulateRewards(state *state.StateDB, header *types.Header, uncles []*types.Header) { reward := new(big.Int).Set(blockReward) diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index 94a9ea332..dd6147072 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -308,14 +308,14 @@ func (d *dataset) release() { // MakeCache generates a new ethash cache and optionally stores it to disk. func MakeCache(block uint64, dir string) { - c := cache{epoch: block/epochLength + 1} + c := cache{epoch: block / epochLength} c.generate(dir, math.MaxInt32, false) c.release() } // MakeDataset generates a new ethash dataset and optionally stores it to disk. func MakeDataset(block uint64, dir string) { - d := dataset{epoch: block/epochLength + 1} + d := dataset{epoch: block / epochLength} d.generate(dir, math.MaxInt32, false) d.release() } @@ -355,7 +355,7 @@ type Ethash struct { // New creates a full sized ethash PoW scheme. func New(cachedir string, cachesinmem, cachesondisk int, dagdir string, dagsinmem, dagsondisk int) *Ethash { if cachesinmem <= 0 { - log.Warn("One ethash cache must alwast be in memory", "requested", cachesinmem) + log.Warn("One ethash cache must always be in memory", "requested", cachesinmem) cachesinmem = 1 } if cachedir != "" && cachesondisk > 0 { @@ -412,7 +412,7 @@ func NewFakeDelayer(delay time.Duration) *Ethash { return &Ethash{fakeMode: true, fakeDelay: delay} } -// NewFullFaker creates a ethash consensus engine with a full fake scheme that +// NewFullFaker creates an ethash consensus engine with a full fake scheme that // accepts all blocks as valid, without checking any consensus rules whatsoever. func NewFullFaker() *Ethash { return &Ethash{fakeMode: true, fakeFull: true} diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go index 67d4adb44..9b22bd7a5 100644 --- a/consensus/misc/dao.go +++ b/consensus/misc/dao.go @@ -54,7 +54,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header) if header.Number.Cmp(config.DAOForkBlock) < 0 || header.Number.Cmp(limit) >= 0 { return nil } - // Depending whether we support or oppose the fork, validate the extra-data contents + // Depending on whether we support or oppose the fork, validate the extra-data contents if config.DAOForkSupport { if !bytes.Equal(header.Extra, params.DAOForkBlockExtra) { return ErrBadProDAOExtra diff --git a/contracts/chequebook/cheque.go b/contracts/chequebook/cheque.go index 7e0f7eafc..bd635705e 100644 --- a/contracts/chequebook/cheque.go +++ b/contracts/chequebook/cheque.go @@ -49,7 +49,7 @@ import ( // TODO(zelig): watch peer solvency and notify of bouncing cheques // TODO(zelig): enable paying with cheque by signing off -// Some functionality require interacting with the blockchain: +// Some functionality requires interacting with the blockchain: // * setting current balance on peer's chequebook // * sending the transaction to cash the cheque // * depositing ether to the chequebook @@ -100,13 +100,13 @@ type Chequebook struct { // persisted fields balance *big.Int // not synced with blockchain contractAddr common.Address // contract address - sent map[common.Address]*big.Int //tallies for beneficiarys + sent map[common.Address]*big.Int //tallies for beneficiaries txhash string // tx hash of last deposit tx threshold *big.Int // threshold that triggers autodeposit if not nil buffer *big.Int // buffer to keep on top of balance for fork protection - log log.Logger // contextual logger with the contrac address embedded + log log.Logger // contextual logger with the contract address embedded } func (self *Chequebook) String() string { @@ -442,7 +442,7 @@ type Inbox struct { maxUncashed *big.Int // threshold that triggers autocashing cashed *big.Int // cumulative amount cashed cheque *Cheque // last cheque, nil if none yet received - log log.Logger // contextual logger with the contrac address embedded + log log.Logger // contextual logger with the contract address embedded } // NewInbox creates an Inbox. An Inboxes is not persisted, the cumulative sum is updated @@ -509,9 +509,8 @@ func (self *Inbox) AutoCash(cashInterval time.Duration, maxUncashed *big.Int) { self.autoCash(cashInterval) } -// autoCash starts a loop that periodically clears the last check +// autoCash starts a loop that periodically clears the last cheque // if the peer is trusted. Clearing period could be 24h or a week. -// // The caller must hold self.lock. func (self *Inbox) autoCash(cashInterval time.Duration) { if self.quit != nil { @@ -557,10 +556,10 @@ func (self *Inbox) Receive(promise swap.Promise) (*big.Int, error) { var sum *big.Int if self.cheque == nil { - // the sum is checked against the blockchain once a check is received + // the sum is checked against the blockchain once a cheque is received tally, err := self.session.Sent(self.beneficiary) if err != nil { - return nil, fmt.Errorf("inbox: error calling backend to set amount: %v", err) + return nil, fmt.Errorf("inbox: error calling backend to set amount: %v", err) } sum = tally } else { diff --git a/contracts/chequebook/cheque_test.go b/contracts/chequebook/cheque_test.go index d5b343024..1f8b71129 100644 --- a/contracts/chequebook/cheque_test.go +++ b/contracts/chequebook/cheque_test.go @@ -414,21 +414,10 @@ func TestCash(t *testing.T) { t.Fatalf("expected no error, got %v", err) } backend.Commit() - // expBalance := big.NewInt(2) - // gotBalance := backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } // after 3x interval time and 2 cheques received, exactly one cashing tx is sent time.Sleep(4 * interval) backend.Commit() - // expBalance = big.NewInt(4) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } - // after stopping autocash no more tx are sent ch2, err := chbook.Issue(addr1, amount) if err != nil { @@ -441,11 +430,6 @@ func TestCash(t *testing.T) { } time.Sleep(2 * interval) backend.Commit() - // expBalance = big.NewInt(4) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } // autocash below 1 chbook.balance = big.NewInt(2) @@ -456,11 +440,6 @@ func TestCash(t *testing.T) { t.Fatalf("expected no error, got %v", err) } backend.Commit() - // expBalance = big.NewInt(4) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } ch4, err := chbook.Issue(addr1, amount) if err != nil { @@ -479,13 +458,6 @@ func TestCash(t *testing.T) { } backend.Commit() - // 2 checks of amount 1 received, exactly 1 tx is sent - // expBalance = big.NewInt(6) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } - // autochash on receipt when maxUncashed is 0 chbook.balance = new(big.Int).Set(common.Big2) chbox.AutoCash(0, common.Big0) @@ -495,11 +467,6 @@ func TestCash(t *testing.T) { t.Fatalf("expected no error, got %v", err) } backend.Commit() - // expBalance = big.NewInt(5) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } ch6, err := chbook.Issue(addr1, amount) if err != nil { @@ -511,21 +478,11 @@ func TestCash(t *testing.T) { t.Fatalf("expected no error, got %v", err) } backend.Commit() - // expBalance = big.NewInt(4) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } _, err = chbox.Receive(ch6) if err != nil { t.Fatalf("expected no error, got %v", err) } backend.Commit() - // expBalance = big.NewInt(6) - // gotBalance = backend.BalanceAt(addr1) - // if gotBalance.Cmp(expBalance) != 0 { - // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance) - // } } diff --git a/contracts/ens/README.md b/contracts/ens/README.md index 274fc14cd..c09b47e39 100644 --- a/contracts/ens/README.md +++ b/contracts/ens/README.md @@ -3,12 +3,12 @@ ## Usage Full documentation for the Ethereum Name Service [can be found as EIP 137](https://github.com/ethereum/EIPs/issues/137). -This package offers a simple binding that streamlines the registration arbitrary utf8 domain names to swarm content hashes. +This package offers a simple binding that streamlines the registration of arbitrary UTF8 domain names to swarm content hashes. ## Development The SOL file in contract subdirectory implements the ENS root registry, a simple -first-in-first-served registrar for the root namespace, and a simple resolver contract; +first-in, first-served registrar for the root namespace, and a simple resolver contract; they're used in tests, and can be used to deploy these contracts for your own purposes. The solidity source code can be found at [github.com/arachnid/ens/](https://github.com/arachnid/ens/). diff --git a/contracts/ens/ens.go b/contracts/ens/ens.go index 7806742cf..83ca9b63b 100644 --- a/contracts/ens/ens.go +++ b/contracts/ens/ens.go @@ -52,7 +52,7 @@ func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contra }, nil } -// DeployENS deploys an instance of the ENS nameservice, with a 'first in first served' root registrar. +// DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar. func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (*ENS, error) { // Deploy the ENS registry ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend, transactOpts.From) diff --git a/contracts/release/contract_test.go b/contracts/release/contract_test.go index 348e9aabe..0b2b2f048 100644 --- a/contracts/release/contract_test.go +++ b/contracts/release/contract_test.go @@ -79,7 +79,7 @@ func TestSignerPromotion(t *testing.T) { // Gradually promote the keys, until all are authorized keys = append([]*ecdsa.PrivateKey{key}, keys...) for i := 1; i < len(keys); i++ { - // Check that no votes are accepted from the not yet authed user + // Check that no votes are accepted from the not yet authorized user if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[i]), common.Address{}); err != nil { t.Fatalf("Iter #%d: failed invalid promotion attempt: %v", i, err) } @@ -216,7 +216,7 @@ func TestVersionRelease(t *testing.T) { // Gradually push releases, always requiring more signers than previously keys = append([]*ecdsa.PrivateKey{key}, keys...) for i := 1; i < len(keys); i++ { - // Check that no votes are accepted from the not yet authed user + // Check that no votes are accepted from the not yet authorized user if _, err := oracle.Release(bind.NewKeyedTransactor(keys[i]), 0, 0, 0, [20]byte{0}); err != nil { t.Fatalf("Iter #%d: failed invalid release attempt: %v", i, err) } diff --git a/core/state_transition.go b/core/state_transition.go index 21830e806..0ae9d7fcb 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -243,7 +243,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big ret, st.gas, vmerr = evm.Call(sender, st.to().Address(), st.data, st.gas, st.value) } if vmerr != nil { - log.Debug("VM returned with error", "err", err) + log.Debug("VM returned with error", "err", vmerr) // The only possible consensus-error would be if there wasn't // sufficient balance to make the transfer happen. The first // balance transfer may never fail. diff --git a/core/types/block.go b/core/types/block.go index 8ca3d0e89..1d00d9f93 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -381,7 +381,7 @@ func (b *Block) Hash() common.Hash { if hash := b.hash.Load(); hash != nil { return hash.(common.Hash) } - v := rlpHash(b.header) + v := b.header.Hash() b.hash.Store(v) return v } diff --git a/core/vm/gen_structlog.go b/core/vm/gen_structlog.go new file mode 100644 index 000000000..1c86b2256 --- /dev/null +++ b/core/vm/gen_structlog.go @@ -0,0 +1,95 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package vm + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" +) + +func (s StructLog) MarshalJSON() ([]byte, error) { + type StructLog struct { + Pc uint64 `json:"pc"` + Op OpCode `json:"op"` + Gas math.HexOrDecimal64 `json:"gas"` + GasCost math.HexOrDecimal64 `json:"gasCost"` + Memory hexutil.Bytes `json:"memory"` + Stack []*math.HexOrDecimal256 `json:"stack"` + Storage map[common.Hash]common.Hash `json:"-"` + Depth int `json:"depth"` + Err error `json:"error"` + OpName string `json:"opName"` + MemorySize int `json:"memSize"` + } + var enc StructLog + enc.Pc = s.Pc + enc.Op = s.Op + enc.Gas = math.HexOrDecimal64(s.Gas) + enc.GasCost = math.HexOrDecimal64(s.GasCost) + enc.Memory = s.Memory + if s.Stack != nil { + enc.Stack = make([]*math.HexOrDecimal256, len(s.Stack)) + for k, v := range s.Stack { + enc.Stack[k] = (*math.HexOrDecimal256)(v) + } + } + enc.Storage = s.Storage + enc.Depth = s.Depth + enc.Err = s.Err + enc.OpName = s.OpName() + enc.MemorySize = s.MemorySize() + return json.Marshal(&enc) +} + +func (s *StructLog) UnmarshalJSON(input []byte) error { + type StructLog struct { + Pc *uint64 `json:"pc"` + Op *OpCode `json:"op"` + Gas *math.HexOrDecimal64 `json:"gas"` + GasCost *math.HexOrDecimal64 `json:"gasCost"` + Memory hexutil.Bytes `json:"memory"` + Stack []*math.HexOrDecimal256 `json:"stack"` + Storage map[common.Hash]common.Hash `json:"-"` + Depth *int `json:"depth"` + Err *error `json:"error"` + } + var dec StructLog + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Pc != nil { + s.Pc = *dec.Pc + } + if dec.Op != nil { + s.Op = *dec.Op + } + if dec.Gas != nil { + s.Gas = uint64(*dec.Gas) + } + if dec.GasCost != nil { + s.GasCost = uint64(*dec.GasCost) + } + if dec.Memory != nil { + s.Memory = dec.Memory + } + if dec.Stack != nil { + s.Stack = make([]*big.Int, len(dec.Stack)) + for k, v := range dec.Stack { + s.Stack[k] = (*big.Int)(v) + } + } + if dec.Storage != nil { + s.Storage = dec.Storage + } + if dec.Depth != nil { + s.Depth = *dec.Depth + } + if dec.Err != nil { + s.Err = *dec.Err + } + return nil +} diff --git a/core/vm/logger.go b/core/vm/logger.go index 825025b05..405ab169c 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -21,8 +21,10 @@ import ( "fmt" "io" "math/big" + "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" ) @@ -47,18 +49,38 @@ type LogConfig struct { Limit int // maximum length of output, but zero means unlimited } +//go:generate gencodec -type StructLog -field-override structLogMarshaling -out gen_structlog.go + // StructLog is emitted to the EVM each cycle and lists information about the current internal state // prior to the execution of the statement. type StructLog struct { - Pc uint64 - Op OpCode - Gas uint64 - GasCost uint64 - Memory []byte - Stack []*big.Int - Storage map[common.Hash]common.Hash - Depth int - Err error + Pc uint64 `json:"pc"` + Op OpCode `json:"op"` + Gas uint64 `json:"gas"` + GasCost uint64 `json:"gasCost"` + Memory []byte `json:"memory"` + Stack []*big.Int `json:"stack"` + Storage map[common.Hash]common.Hash `json:"-"` + Depth int `json:"depth"` + Err error `json:"error"` +} + +// overrides for gencodec +type structLogMarshaling struct { + Stack []*math.HexOrDecimal256 + Gas math.HexOrDecimal64 + GasCost math.HexOrDecimal64 + Memory hexutil.Bytes + OpName string `json:"opName"` + MemorySize int `json:"memSize"` +} + +func (s *StructLog) OpName() string { + return s.Op.String() +} + +func (s *StructLog) MemorySize() int { + return len(s.Memory) } // Tracer is used to collect execution traces from an EVM transaction @@ -68,6 +90,7 @@ type StructLog struct { // if you need to retain them beyond the current call. type Tracer interface { CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error + CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error } // StructLogger is an EVM state logger and implements Tracer. @@ -82,7 +105,7 @@ type StructLogger struct { changedValues map[common.Address]Storage } -// NewLogger returns a new logger +// NewStructLogger returns a new logger func NewStructLogger(cfg *LogConfig) *StructLogger { logger := &StructLogger{ changedValues: make(map[common.Address]Storage), @@ -93,9 +116,9 @@ func NewStructLogger(cfg *LogConfig) *StructLogger { return logger } -// captureState logs a new structured log message and pushes it out to the environment +// CaptureState logs a new structured log message and pushes it out to the environment // -// captureState also tracks SSTORE ops to track dirty values. +// CaptureState also tracks SSTORE ops to track dirty values. func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { // check if already accumulated the specified number of logs if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { @@ -164,6 +187,11 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui return nil } +func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error { + fmt.Printf("0x%x", output) + return nil +} + // StructLogs returns a list of captured log entries func (l *StructLogger) StructLogs() []StructLog { return l.logs diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 94265626f..aa386a995 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -125,7 +125,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { } // Create executes the code using the EVM create method -func Create(input []byte, cfg *Config) ([]byte, common.Address, error) { +func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { if cfg == nil { cfg = new(Config) } @@ -141,13 +141,13 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, error) { ) // Call the code with the given configuration. - code, address, _, err := vmenv.Create( + code, address, leftOverGas, err := vmenv.Create( sender, input, cfg.GasLimit, cfg.Value, ) - return code, address, err + return code, address, leftOverGas, err } // Call executes the code given by the contract's address. It will return the @@ -155,14 +155,14 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, error) { // // Call, unlike Execute, requires a config and also requires the State field to // be set. -func Call(address common.Address, input []byte, cfg *Config) ([]byte, error) { +func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) { setDefaults(cfg) vmenv := NewEnv(cfg, cfg.State) sender := cfg.State.GetOrNewStateObject(cfg.Origin) // Call the code with the given configuration. - ret, _, err := vmenv.Call( + ret, leftOverGas, err := vmenv.Call( sender, address, input, @@ -170,5 +170,5 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, error) { cfg.Value, ) - return ret, err + return ret, leftOverGas, err } diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index fe39e97a0..7f40770d2 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -106,7 +106,7 @@ func TestCall(t *testing.T) { byte(vm.RETURN), }) - ret, err := Call(address, nil, &Config{State: state}) + ret, _, err := Call(address, nil, &Config{State: state}) if err != nil { t.Fatal("didn't expect error", err) } diff --git a/internal/ethapi/tracer.go b/internal/ethapi/tracer.go index d34363564..fc66839ea 100644 --- a/internal/ethapi/tracer.go +++ b/internal/ethapi/tracer.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "math/big" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -344,6 +345,12 @@ func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, return nil } +// CaptureEnd is called after the call finishes +func (jst *JavascriptTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error { + //TODO! @Arachnid please figure out of there's anything we can use this method for + return nil +} + // GetResult calls the Javascript 'result' function and returns its value, or any accumulated error func (jst *JavascriptTracer) GetResult() (result interface{}, err error) { if jst.err != nil { diff --git a/mobile/android_test.go b/mobile/android_test.go index 6f5076d64..345e009b4 100644 --- a/mobile/android_test.go +++ b/mobile/android_test.go @@ -37,6 +37,9 @@ package go; import android.test.InstrumentationTestCase; import android.test.MoreAsserts; +import java.math.BigInteger; +import java.util.Arrays; + import org.ethereum.geth.*; public class AndroidTest extends InstrumentationTestCase { @@ -115,6 +118,32 @@ public class AndroidTest extends InstrumentationTestCase { fail(e.toString()); } } + + // Tests that recovering transaction signers works for both Homestead and EIP155 + // signatures too. Regression test for go-ethereum issue #14599. + public void testIssue14599() { + try { + byte[] preEIP155RLP = new BigInteger("f901fc8032830138808080b901ae60056013565b6101918061001d6000396000f35b3360008190555056006001600060e060020a6000350480630a874df61461003a57806341c0e1b514610058578063a02b161e14610066578063dbbdf0831461007757005b610045600435610149565b80600160a060020a031660005260206000f35b610060610161565b60006000f35b6100716004356100d4565b60006000f35b61008560043560243561008b565b60006000f35b600054600160a060020a031632600160a060020a031614156100ac576100b1565b6100d0565b8060018360005260205260406000208190555081600060005260206000a15b5050565b600054600160a060020a031633600160a060020a031614158015610118575033600160a060020a0316600182600052602052604060002054600160a060020a031614155b61012157610126565b610146565b600060018260005260205260406000208190555080600060005260206000a15b50565b60006001826000526020526040600020549050919050565b600054600160a060020a031633600160a060020a0316146101815761018f565b600054600160a060020a0316ff5b561ca0c5689ed1ad124753d54576dfb4b571465a41900a1dff4058d8adf16f752013d0a01221cbd70ec28c94a3b55ec771bcbc70778d6ee0b51ca7ea9514594c861b1884", 16).toByteArray(); + preEIP155RLP = Arrays.copyOfRange(preEIP155RLP, 1, preEIP155RLP.length); + + byte[] postEIP155RLP = new BigInteger("f86b80847735940082520894ef5bbb9bba2e1ca69ef81b23a8727d889f3ef0a1880de0b6b3a7640000802ba06fef16c44726a102e6d55a651740636ef8aec6df3ebf009e7b0c1f29e4ac114aa057e7fbc69760b522a78bb568cfc37a58bfdcf6ea86cb8f9b550263f58074b9cc", 16).toByteArray(); + postEIP155RLP = Arrays.copyOfRange(postEIP155RLP, 1, postEIP155RLP.length); + + Transaction preEIP155 = new Transaction(preEIP155RLP); + Transaction postEIP155 = new Transaction(postEIP155RLP); + + preEIP155.getFrom(null); // Homestead should accept homestead + preEIP155.getFrom(new BigInt(4)); // EIP155 should accept homestead (missing chain ID) + postEIP155.getFrom(new BigInt(4)); // EIP155 should accept EIP 155 + + try { + postEIP155.getFrom(null); + fail("EIP155 transaction accepted by Homestead"); + } catch (Exception e) {} + } catch (Exception e) { + fail(e.toString()); + } + } } ` diff --git a/mobile/types.go b/mobile/types.go index 7900e7287..02282f7a3 100644 --- a/mobile/types.go +++ b/mobile/types.go @@ -264,8 +264,11 @@ func (tx *Transaction) GetHash() *Hash { return &Hash{tx.tx.Hash()} } func (tx *Transaction) GetSigHash() *Hash { return &Hash{tx.tx.SigHash(types.HomesteadSigner{})} } func (tx *Transaction) GetCost() *BigInt { return &BigInt{tx.tx.Cost()} } -func (tx *Transaction) GetFrom() (address *Address, _ error) { - from, err := types.Sender(types.HomesteadSigner{}, tx.tx) +func (tx *Transaction) GetFrom(chainID *BigInt) (address *Address, _ error) { + if chainID == nil { // Null passed from mobile app + chainID = new(BigInt) + } + from, err := types.Sender(types.NewEIP155Signer(chainID.bigint), tx.tx) return &Address{from}, err } diff --git a/rlp/decode.go b/rlp/decode.go index ee0b7dbcd..78ccf6275 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -55,7 +55,7 @@ type Decoder interface { // To decode into a pointer, Decode will decode into the value pointed // to. If the pointer is nil, a new value of the pointer's element // type is allocated. If the pointer is non-nil, the existing value -// will reused. +// will be reused. // // To decode into a struct, Decode expects the input to be an RLP // list. The decoded elements of the list are assigned to each public @@ -290,7 +290,7 @@ func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) { } case tag.tail: // A slice with "tail" tag can occur as the last field - // of a struct and is upposed to swallow all remaining + // of a struct and is supposed to swallow all remaining // list elements. The struct decoder already called s.List, // proceed directly to decoding the elements. dec = func(s *Stream, val reflect.Value) error { @@ -741,7 +741,7 @@ func (s *Stream) uint(maxbits int) (uint64, error) { } // Bool reads an RLP string of up to 1 byte and returns its contents -// as an boolean. If the input does not contain an RLP string, the +// as a boolean. If the input does not contain an RLP string, the // returned error will be ErrExpectedString. func (s *Stream) Bool() (bool, error) { num, err := s.uint(8) diff --git a/rlp/doc.go b/rlp/doc.go index 72667416c..b3a81fe23 100644 --- a/rlp/doc.go +++ b/rlp/doc.go @@ -17,13 +17,13 @@ /* Package rlp implements the RLP serialization format. -The purpose of RLP (Recursive Linear Prefix) qis to encode arbitrarily +The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily nested arrays of binary data, and RLP is the main encoding method used to serialize objects in Ethereum. The only purpose of RLP is to encode structure; encoding specific atomic data types (eg. strings, ints, floats) is left up to higher-order protocols; in Ethereum integers must be represented in big endian binary form with no leading zeroes -(thus making the integer value zero be equivalent to the empty byte +(thus making the integer value zero equivalent to the empty byte array). RLP values are distinguished by a type tag. The type tag precedes the diff --git a/rlp/encode.go b/rlp/encode.go index c20897efe..44592c2f5 100644 --- a/rlp/encode.go +++ b/rlp/encode.go @@ -478,7 +478,7 @@ func writeEncoder(val reflect.Value, w *encbuf) error { // with a pointer receiver. func writeEncoderNoPtr(val reflect.Value, w *encbuf) error { if !val.CanAddr() { - // We can't get the address. It would be possible make the + // We can't get the address. It would be possible to make the // value addressable by creating a shallow copy, but this // creates other problems so we're not doing it (yet). // @@ -583,7 +583,7 @@ func makePtrWriter(typ reflect.Type) (writer, error) { return writer, err } -// putint writes i to the beginning of b in with big endian byte +// putint writes i to the beginning of b in big endian byte // order, using the least number of bytes needed to represent i. func putint(b []byte, i uint64) (size int) { switch { diff --git a/rlp/raw.go b/rlp/raw.go index 33aae6ee5..6bf1c1df8 100644 --- a/rlp/raw.go +++ b/rlp/raw.go @@ -22,7 +22,7 @@ import ( ) // RawValue represents an encoded RLP value and can be used to delay -// RLP decoding or precompute an encoding. Note that the decoder does +// RLP decoding or to precompute an encoding. Note that the decoder does // not verify whether the content of RawValues is valid RLP. type RawValue []byte diff --git a/trie/hasher.go b/trie/hasher.go index 85b6b60f5..672456e2d 100644 --- a/trie/hasher.go +++ b/trie/hasher.go @@ -50,7 +50,7 @@ func returnHasherToPool(h *hasher) { } // hash collapses a node down into a hash node, also returning a copy of the -// original node initialzied with the computed hash to replace the original one. +// original node initialized with the computed hash to replace the original one. func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error) { // If we're not storing the node, just hashing, use available cached data if hash, dirty := n.cache(); hash != nil { diff --git a/trie/secure_trie_test.go b/trie/secure_trie_test.go index 159640fda..d74102e2a 100644 --- a/trie/secure_trie_test.go +++ b/trie/secure_trie_test.go @@ -51,7 +51,7 @@ func makeTestSecureTrie() (ethdb.Database, *SecureTrie, map[string][]byte) { content[string(key)] = val trie.Update(key, val) - // Add some other data to inflate th trie + // Add some other data to inflate the trie for j := byte(3); j < 13; j++ { key, val = common.LeftPadBytes([]byte{j, i}, 32), []byte{j, i} content[string(key)] = val diff --git a/trie/sync_test.go b/trie/sync_test.go index 1e27cbb67..d778555b9 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -42,7 +42,7 @@ func makeTestTrie() (ethdb.Database, *Trie, map[string][]byte) { content[string(key)] = val trie.Update(key, val) - // Add some other data to inflate th trie + // Add some other data to inflate the trie for j := byte(3); j < 13; j++ { key, val = common.LeftPadBytes([]byte{j, i}, 32), []byte{j, i} content[string(key)] = val @@ -78,7 +78,7 @@ func checkTrieConsistency(db Database, root common.Hash) error { // Create and iterate a trie rooted in a subnode trie, err := New(root, db) if err != nil { - return nil // // Consider a non existent state consistent + return nil // Consider a non existent state consistent } it := trie.NodeIterator(nil) for it.Next(true) { @@ -310,7 +310,7 @@ func TestIncompleteTrieSync(t *testing.T) { for _, result := range results { added = append(added, result.Hash) } - // Check that all known sub-tries in the synced trie is complete + // Check that all known sub-tries in the synced trie are complete for _, root := range added { if err := checkTrieConsistency(dstDb, root); err != nil { t.Fatalf("trie inconsistent: %v", err) diff --git a/trie/trie.go b/trie/trie.go index 5759f97e3..cbe496574 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -40,7 +40,7 @@ var ( ) // CacheMisses retrieves a global counter measuring the number of cache misses -// the trie did since process startup. This isn't useful for anything apart from +// the trie had since process startup. This isn't useful for anything apart from // trie debugging purposes. func CacheMisses() int64 { return cacheMissCounter.Count() @@ -87,14 +87,14 @@ type Trie struct { originalRoot common.Hash // Cache generation values. - // cachegen increase by one with each commit operation. + // cachegen increases by one with each commit operation. // new nodes are tagged with the current generation and unloaded // when their generation is older than than cachegen-cachelimit. cachegen, cachelimit uint16 } // SetCacheLimit sets the number of 'cache generations' to keep. -// A cache generations is created by a call to Commit. +// A cache generation is created by a call to Commit. func (t *Trie) SetCacheLimit(l uint16) { t.cachelimit = l } |