diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index e2e25180a1..959b501565 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -6,6 +6,7 @@ accounts/abi @gballet
consensus @karalabe
core/ @karalabe @holiman
eth/ @karalabe
+graphql/ @gballet
les/ @zsfelfoldi
light/ @zsfelfoldi
mobile/ @karalabe
diff --git a/.gitignore b/.gitignore
index 3e0009e167..3016facee0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ profile.cov
/dashboard/assets/node_modules
/dashboard/assets/stats.json
/dashboard/assets/bundle.js
+/dashboard/assets/bundle.js.map
/dashboard/assets/package-lock.json
**/yarn-error.log
diff --git a/README.md b/README.md
index 02a8775084..ea8b0a499d 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,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 both a Go (version 1.9 or later) and a C compiler.
+Building geth requires both a Go (version 1.10 or later) and a C compiler.
You can install them using your favourite package manager.
Once the dependencies are installed, run
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index de81db1344..7371dfb1f1 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -66,7 +66,7 @@ type SimulatedBackend struct {
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
- database := ethdb.NewMemDatabase()
+ database := rawdb.NewMemoryDatabase()
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil)
diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go
index 46e0b38d00..eae12b3f4d 100644
--- a/accounts/abi/bind/bind_test.go
+++ b/accounts/abi/bind/bind_test.go
@@ -670,7 +670,7 @@ var bindTests = []struct {
`Eventer`,
`
contract Eventer {
- event SimpleEvent (
+ event SimpleEvent (
address indexed Addr,
bytes32 indexed Id,
bool indexed Flag,
@@ -698,10 +698,18 @@ var bindTests = []struct {
function raiseDynamicEvent(string str, bytes blob) {
DynamicEvent(str, blob, str, blob);
}
+
+ event FixedBytesEvent (
+ bytes24 indexed IndexedBytes,
+ bytes24 NonIndexedBytes
+ );
+ function raiseFixedBytesEvent(bytes24 blob) {
+ FixedBytesEvent(blob, blob);
+ }
}
`,
- `6060604052341561000f57600080fd5b61042c8061001e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063528300ff1461005c578063630c31e2146100fc578063c7d116dd14610156575b600080fd5b341561006757600080fd5b6100fa600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610194565b005b341561010757600080fd5b610154600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035600019169060200190919080351515906020019091908035906020019091905050610367565b005b341561016157600080fd5b610192600480803590602001909190803560010b90602001909190803563ffffffff169060200190919050506103c3565b005b806040518082805190602001908083835b6020831015156101ca57805182526020820191506020810190506020830392506101a5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020826040518082805190602001908083835b60208310151561022d5780518252602082019150602081019050602083039250610208565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f3281fd4f5e152dd3385df49104a3f633706e21c9e80672e88d3bcddf33101f008484604051808060200180602001838103835285818151815260200191508051906020019080838360005b838110156102c15780820151818401526020810190506102a6565b50505050905090810190601f1680156102ee5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b8381101561032757808201518184015260208101905061030c565b50505050905090810190601f1680156103545780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a35050565b81151583600019168573ffffffffffffffffffffffffffffffffffffffff167f1f097de4289df643bd9c11011cc61367aa12983405c021056e706eb5ba1250c8846040518082815260200191505060405180910390a450505050565b8063ffffffff168260010b847f3ca7f3a77e5e6e15e781850bc82e32adfa378a2a609370db24b4d0fae10da2c960405160405180910390a45050505600a165627a7a72305820d1f8a8bbddbc5bb29f285891d6ae1eef8420c52afdc05e1573f6114d8e1714710029`,
- `[{"constant":false,"inputs":[{"name":"str","type":"string"},{"name":"blob","type":"bytes"}],"name":"raiseDynamicEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"id","type":"bytes32"},{"name":"flag","type":"bool"},{"name":"value","type":"uint256"}],"name":"raiseSimpleEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"number","type":"uint256"},{"name":"short","type":"int16"},{"name":"long","type":"uint32"}],"name":"raiseNodataEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Addr","type":"address"},{"indexed":true,"name":"Id","type":"bytes32"},{"indexed":true,"name":"Flag","type":"bool"},{"indexed":false,"name":"Value","type":"uint256"}],"name":"SimpleEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Number","type":"uint256"},{"indexed":true,"name":"Short","type":"int16"},{"indexed":true,"name":"Long","type":"uint32"}],"name":"NodataEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"IndexedString","type":"string"},{"indexed":true,"name":"IndexedBytes","type":"bytes"},{"indexed":false,"name":"NonIndexedString","type":"string"},{"indexed":false,"name":"NonIndexedBytes","type":"bytes"}],"name":"DynamicEvent","type":"event"}]`,
+ `608060405234801561001057600080fd5b5061043f806100206000396000f3006080604052600436106100615763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663528300ff8114610066578063630c31e2146100ff5780636cc6b94014610138578063c7d116dd1461015b575b600080fd5b34801561007257600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526100fd94369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506101829650505050505050565b005b34801561010b57600080fd5b506100fd73ffffffffffffffffffffffffffffffffffffffff60043516602435604435151560643561033c565b34801561014457600080fd5b506100fd67ffffffffffffffff1960043516610394565b34801561016757600080fd5b506100fd60043560243560010b63ffffffff604435166103d6565b806040518082805190602001908083835b602083106101b25780518252601f199092019160209182019101610193565b51815160209384036101000a6000190180199092169116179052604051919093018190038120875190955087945090928392508401908083835b6020831061020b5780518252601f1990920191602091820191016101ec565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f3281fd4f5e152dd3385df49104a3f633706e21c9e80672e88d3bcddf33101f008484604051808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561029c578181015183820152602001610284565b50505050905090810190601f1680156102c95780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156102fc5781810151838201526020016102e4565b50505050905090810190601f1680156103295780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a35050565b60408051828152905183151591859173ffffffffffffffffffffffffffffffffffffffff8816917f1f097de4289df643bd9c11011cc61367aa12983405c021056e706eb5ba1250c8919081900360200190a450505050565b6040805167ffffffffffffffff19831680825291517fcdc4c1b1aed5524ffb4198d7a5839a34712baef5fa06884fac7559f4a5854e0a9181900360200190a250565b8063ffffffff168260010b847f3ca7f3a77e5e6e15e781850bc82e32adfa378a2a609370db24b4d0fae10da2c960405160405180910390a45050505600a165627a7a72305820468b5843bf653145bd924b323c64ef035d3dd922c170644b44d61aa666ea6eee0029`,
+ `[{"constant":false,"inputs":[{"name":"str","type":"string"},{"name":"blob","type":"bytes"}],"name":"raiseDynamicEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"id","type":"bytes32"},{"name":"flag","type":"bool"},{"name":"value","type":"uint256"}],"name":"raiseSimpleEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"blob","type":"bytes24"}],"name":"raiseFixedBytesEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"number","type":"uint256"},{"name":"short","type":"int16"},{"name":"long","type":"uint32"}],"name":"raiseNodataEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Addr","type":"address"},{"indexed":true,"name":"Id","type":"bytes32"},{"indexed":true,"name":"Flag","type":"bool"},{"indexed":false,"name":"Value","type":"uint256"}],"name":"SimpleEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Number","type":"uint256"},{"indexed":true,"name":"Short","type":"int16"},{"indexed":true,"name":"Long","type":"uint32"}],"name":"NodataEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"IndexedString","type":"string"},{"indexed":true,"name":"IndexedBytes","type":"bytes"},{"indexed":false,"name":"NonIndexedString","type":"string"},{"indexed":false,"name":"NonIndexedBytes","type":"bytes"}],"name":"DynamicEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"IndexedBytes","type":"bytes24"},{"indexed":false,"name":"NonIndexedBytes","type":"bytes24"}],"name":"FixedBytesEvent","type":"event"}]`,
`
"math/big"
"time"
@@ -812,6 +820,33 @@ var bindTests = []struct {
if err = dit.Error(); err != nil {
t.Fatalf("dynamic event iteration failed: %v", err)
}
+ // Test raising and filtering for events with fixed bytes components
+ var fblob [24]byte
+ copy(fblob[:], []byte("Fixed Bytes"))
+
+ if _, err := eventer.RaiseFixedBytesEvent(auth, fblob); err != nil {
+ t.Fatalf("failed to raise fixed bytes event: %v", err)
+ }
+ sim.Commit()
+
+ fit, err := eventer.FilterFixedBytesEvent(nil, [][24]byte{fblob})
+ if err != nil {
+ t.Fatalf("failed to filter for fixed bytes events: %v", err)
+ }
+ defer fit.Close()
+
+ if !fit.Next() {
+ t.Fatalf("fixed bytes log not found: %v", fit.Error())
+ }
+ if fit.Event.NonIndexedBytes != fblob || fit.Event.IndexedBytes != fblob {
+ t.Errorf("fixed bytes log content mismatch: have %v, want {'%x', '%x'}", fit.Event, fblob, fblob)
+ }
+ if fit.Next() {
+ t.Errorf("unexpected fixed bytes event found: %+v", fit.Event)
+ }
+ if err = fit.Error(); err != nil {
+ t.Fatalf("fixed bytes event iteration failed: %v", err)
+ }
// Test subscribing to an event and raising it afterwards
ch := make(chan *EventerSimpleEvent, 16)
sub, err := eventer.WatchSimpleEvent(nil, ch, nil, nil, nil)
diff --git a/accounts/abi/bind/topics.go b/accounts/abi/bind/topics.go
index 600dfcda97..af9c272cdb 100644
--- a/accounts/abi/bind/topics.go
+++ b/accounts/abi/bind/topics.go
@@ -83,8 +83,10 @@ func makeTopics(query ...[]interface{}) ([][]common.Hash, error) {
val := reflect.ValueOf(rule)
switch {
+
+ // static byte array
case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8:
- reflect.Copy(reflect.ValueOf(topic[common.HashLength-val.Len():]), val)
+ reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val)
default:
return nil, fmt.Errorf("unsupported indexed type: %T", rule)
@@ -175,8 +177,10 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er
default:
// Ran out of custom types, try the crazies
switch {
+
+ // static byte array
case arg.Type.T == abi.FixedBytesTy:
- reflect.Copy(field, reflect.ValueOf(topics[0][common.HashLength-arg.Type.Size:]))
+ reflect.Copy(field, reflect.ValueOf(topics[0][:arg.Type.Size]))
default:
return fmt.Errorf("unsupported indexed type: %v", arg.Type)
diff --git a/accounts/abi/bind/topics_test.go b/accounts/abi/bind/topics_test.go
new file mode 100644
index 0000000000..e6f745a15e
--- /dev/null
+++ b/accounts/abi/bind/topics_test.go
@@ -0,0 +1,103 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package bind
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func TestMakeTopics(t *testing.T) {
+ type args struct {
+ query [][]interface{}
+ }
+ tests := []struct {
+ name string
+ args args
+ want [][]common.Hash
+ wantErr bool
+ }{
+ {
+ "support fixed byte types, right padded to 32 bytes",
+ args{[][]interface{}{{[5]byte{1, 2, 3, 4, 5}}}},
+ [][]common.Hash{{common.Hash{1, 2, 3, 4, 5}}},
+ false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := makeTopics(tt.args.query...)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("makeTopics() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestParseTopics(t *testing.T) {
+ type bytesStruct struct {
+ StaticBytes [5]byte
+ }
+ bytesType, _ := abi.NewType("bytes5", nil)
+ type args struct {
+ createObj func() interface{}
+ resultObj func() interface{}
+ fields abi.Arguments
+ topics []common.Hash
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "support fixed byte types, right padded to 32 bytes",
+ args: args{
+ createObj: func() interface{} { return &bytesStruct{} },
+ resultObj: func() interface{} { return &bytesStruct{StaticBytes: [5]byte{1, 2, 3, 4, 5}} },
+ fields: abi.Arguments{abi.Argument{
+ Name: "staticBytes",
+ Type: bytesType,
+ Indexed: true,
+ }},
+ topics: []common.Hash{
+ {1, 2, 3, 4, 5},
+ },
+ },
+ wantErr: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ createObj := tt.args.createObj()
+ if err := parseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
+ t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ resultObj := tt.args.resultObj()
+ if !reflect.DeepEqual(createObj, resultObj) {
+ t.Errorf("parseTopics() = %v, want %v", createObj, resultObj)
+ }
+ })
+ }
+}
diff --git a/accounts/usbwallet/wallet.go b/accounts/usbwallet/wallet.go
index feab505c9b..2ddfa30a6c 100644
--- a/accounts/usbwallet/wallet.go
+++ b/accounts/usbwallet/wallet.go
@@ -274,9 +274,7 @@ func (w *wallet) close() error {
w.device = nil
w.accounts, w.paths = nil, nil
- w.driver.Close()
-
- return nil
+ return w.driver.Close()
}
// Accounts implements accounts.Wallet, returning the list of accounts pinned to
diff --git a/cmd/clef/README.md b/cmd/clef/README.md
index 036e71b286..956957f3d1 100644
--- a/cmd/clef/README.md
+++ b/cmd/clef/README.md
@@ -661,7 +661,7 @@ OBS! A slight deviation from `json` standard is in place: every request and resp
Whereas the `json` specification allows for linebreaks, linebreaks __should not__ be used in this communication channel, to make
things simpler for both parties.
-### ApproveTx
+### ApproveTx / `ui_approveTx`
Invoked when there's a transaction for approval.
@@ -673,13 +673,13 @@ Here's a method invocation:
curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/
```
-
+Results in the following invocation on the UI:
```json
{
"jsonrpc": "2.0",
"id": 1,
- "method": "ApproveTx",
+ "method": "ui_approveTx",
"params": [
{
"transaction": {
@@ -724,7 +724,7 @@ curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","me
{
"jsonrpc": "2.0",
"id": 1,
- "method": "ApproveTx",
+ "method": "ui_approveTx",
"params": [
{
"transaction": {
@@ -767,7 +767,7 @@ One which has missing `to`, but with no `data`:
{
"jsonrpc": "2.0",
"id": 3,
- "method": "ApproveTx",
+ "method": "ui_approveTx",
"params": [
{
"transaction": {
@@ -796,33 +796,7 @@ One which has missing `to`, but with no `data`:
}
```
-### ApproveExport
-
-Invoked when a request to export an account has been made.
-
-#### Sample call
-
-```json
-
-{
- "jsonrpc": "2.0",
- "id": 7,
- "method": "ApproveExport",
- "params": [
- {
- "address": "0x0000000000000000000000000000000000000000",
- "meta": {
- "remote": "signer binary",
- "local": "main",
- "scheme": "in-proc"
- }
- }
- ]
-}
-
-```
-
-### ApproveListing
+### ApproveListing / `ui_approveListing`
Invoked when a request for account listing has been made.
@@ -833,7 +807,7 @@ Invoked when a request for account listing has been made.
{
"jsonrpc": "2.0",
"id": 5,
- "method": "ApproveListing",
+ "method": "ui_approveListing",
"params": [
{
"accounts": [
@@ -860,7 +834,7 @@ Invoked when a request for account listing has been made.
```
-### ApproveSignData
+### ApproveSignData / `ui_approveSignData`
#### Sample call
@@ -868,7 +842,7 @@ Invoked when a request for account listing has been made.
{
"jsonrpc": "2.0",
"id": 4,
- "method": "ApproveSignData",
+ "method": "ui_approveSignData",
"params": [
{
"address": "0x123409812340981234098123409812deadbeef42",
@@ -886,7 +860,7 @@ Invoked when a request for account listing has been made.
```
-### ShowInfo
+### ShowInfo / `ui_showInfo`
The UI should show the info to the user. Does not expect response.
@@ -896,7 +870,7 @@ The UI should show the info to the user. Does not expect response.
{
"jsonrpc": "2.0",
"id": 9,
- "method": "ShowInfo",
+ "method": "ui_showInfo",
"params": [
{
"text": "Tests completed"
@@ -906,7 +880,7 @@ The UI should show the info to the user. Does not expect response.
```
-### ShowError
+### ShowError / `ui_showError`
The UI should show the info to the user. Does not expect response.
@@ -925,7 +899,7 @@ The UI should show the info to the user. Does not expect response.
```
-### OnApproved
+### OnApprovedTx / `ui_onApprovedTx`
`OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions.
@@ -933,7 +907,7 @@ When implementing rate-limited rules, this callback should be used.
TLDR; Use this method to keep track of signed transactions, instead of using the data in `ApproveTx`.
-### OnSignerStartup
+### OnSignerStartup / `ui_onSignerStartup`
This method provide the UI with information about what API version the signer uses (both internal and external) aswell as build-info and external api,
in k/v-form.
@@ -944,7 +918,7 @@ Example call:
{
"jsonrpc": "2.0",
"id": 1,
- "method": "OnSignerStartup",
+ "method": "ui_onSignerStartup",
"params": [
{
"info": {
diff --git a/cmd/clef/datatypes.md b/cmd/clef/datatypes.md
index e345a2bbd5..a26c1c9375 100644
--- a/cmd/clef/datatypes.md
+++ b/cmd/clef/datatypes.md
@@ -35,8 +35,7 @@ Response to SignDataRequest
Example:
```json
{
- "approved": true,
- "Password": "apassword"
+ "approved": true
}
```
### SignDataResponse - deny
@@ -46,8 +45,7 @@ Response to SignDataRequest
Example:
```json
{
- "approved": false,
- "Password": ""
+ "approved": false
}
```
### SignTxRequest
@@ -89,9 +87,9 @@ Example:
}
}
```
-### SignDataResponse - approve
+### SignTxResponse - approve
-Response to SignDataRequest. This response needs to contain the `transaction`, because the UI is free to make modifications to the transaction.
+Response to request to sign a transaction. This response needs to contain the `transaction`, because the UI is free to make modifications to the transaction.
Example:
```json
@@ -105,19 +103,26 @@ Example:
"nonce": "0x4",
"data": "0x04030201"
},
- "approved": true,
- "password": "apassword"
+ "approved": true
}
```
-### SignDataResponse - deny
+### SignTxResponse - deny
-Response to SignDataRequest. When denying a request, there's no need to provide the transaction in return
+Response to SignTxRequest. When denying a request, there's no need to provide the transaction in return
Example:
```json
{
- "approved": false,
- "Password": ""
+ "transaction": {
+ "from": "0x",
+ "to": null,
+ "gas": "0x0",
+ "gasPrice": "0x0",
+ "value": "0x0",
+ "nonce": "0x0",
+ "data": null
+ },
+ "approved": false
}
```
### OnApproved - SignTransactionResult
@@ -164,7 +169,7 @@ Example:
```
### UserInputResponse
-Response to SignDataRequest
+Response to UserInputRequest
Example:
```json
@@ -198,7 +203,7 @@ Example:
}
}
```
-### UserInputResponse
+### ListResponse
Response to list request. The response contains a list of all addresses to show to the caller. Note: the UI is free to respond with any address the caller, regardless of whether it exists or not
diff --git a/cmd/clef/intapi_changelog.md b/cmd/clef/intapi_changelog.md
index db3353bb7d..b7d4937cdd 100644
--- a/cmd/clef/intapi_changelog.md
+++ b/cmd/clef/intapi_changelog.md
@@ -1,5 +1,40 @@
### Changelog for internal API (ui-api)
+### 6.0.0
+
+Removed `password` from responses to operations which require them. This is for two reasons,
+
+- Consistency between how rulesets operate and how manual processing works. A rule can `Approve` but require the actual password to be stored in the clef storage.
+With this change, the same stored password can be used even if rulesets are not enabled, but storage is.
+- It also removes the usability-shortcut that a UI might otherwise want to implement; remembering passwords. Since we now will not require the
+password on every `Approve`, there's no need for the UI to cache it locally.
+ - In a future update, we'll likely add `clef_storePassword` to the internal API, so the user can store it via his UI (currently only CLI works).
+
+Affected datatypes:
+- `SignTxResponse`
+- `SignDataResponse`
+- `NewAccountResponse`
+
+If `clef` requires a password, the `OnInputRequired` will be used to collect it.
+
+
+### 5.0.0
+
+Changed the namespace format to adhere to the legacy ethereum format: `name_methodName`. Changes:
+
+* `ApproveTx` -> `ui_approveTx`
+* `ApproveSignData` -> `ui_approveSignData`
+* `ApproveExport` -> `removed`
+* `ApproveImport` -> `removed`
+* `ApproveListing` -> `ui_approveListing`
+* `ApproveNewAccount` -> `ui_approveNewAccount`
+* `ShowError` -> `ui_showError`
+* `ShowInfo` -> `ui_showInfo`
+* `OnApprovedTx` -> `ui_onApprovedTx`
+* `OnSignerStartup` -> `ui_onSignerStartup`
+* `OnInputRequired` -> `ui_onInputRequired`
+
+
### 4.0.0
* Bidirectional communication implemented, so the UI can query `clef` via the stdin/stdout RPC channel. Methods implemented are:
diff --git a/cmd/clef/main.go b/cmd/clef/main.go
index 088701eeee..a900312459 100644
--- a/cmd/clef/main.go
+++ b/cmd/clef/main.go
@@ -119,7 +119,7 @@ var (
ruleFlag = cli.StringFlag{
Name: "rules",
Usage: "Enable rule-engine",
- Value: "rules.json",
+ Value: "",
}
stdiouiFlag = cli.BoolFlag{
Name: "stdio-ui",
@@ -371,17 +371,14 @@ func signer(c *cli.Context) error {
log.Info("Loaded 4byte db", "signatures", db.Size(), "file", fourByteDb, "local", fourByteLocal)
var (
- api core.ExternalAPI
+ api core.ExternalAPI
+ pwStorage storage.Storage = &storage.NoStorage{}
)
configDir := c.GlobalString(configdirFlag.Name)
if stretchedKey, err := readMasterKey(c, ui); err != nil {
log.Info("No master seed provided, rules disabled", "error", err)
} else {
-
- if err != nil {
- utils.Fatalf(err.Error())
- }
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
// Generate domain specific keys
@@ -390,30 +387,31 @@ func signer(c *cli.Context) error {
confkey := crypto.Keccak256([]byte("config"), stretchedKey)
// Initialize the encrypted storages
- pwStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey)
+ pwStorage = storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey)
jsStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "jsstorage.json"), jskey)
configStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "config.json"), confkey)
//Do we have a rule-file?
- ruleJS, err := ioutil.ReadFile(c.GlobalString(ruleFlag.Name))
- if err != nil {
- log.Info("Could not load rulefile, rules not enabled", "file", "rulefile")
- } else {
- hasher := sha256.New()
- hasher.Write(ruleJS)
- shasum := hasher.Sum(nil)
- storedShasum := configStorage.Get("ruleset_sha256")
- if storedShasum != hex.EncodeToString(shasum) {
- log.Info("Could not validate ruleset hash, rules not enabled", "got", hex.EncodeToString(shasum), "expected", storedShasum)
+ if ruleFile := c.GlobalString(ruleFlag.Name); ruleFile != "" {
+ ruleJS, err := ioutil.ReadFile(c.GlobalString(ruleFile))
+ if err != nil {
+ log.Info("Could not load rulefile, rules not enabled", "file", "rulefile")
} else {
- // Initialize rules
- ruleEngine, err := rules.NewRuleEvaluator(ui, jsStorage, pwStorage)
- if err != nil {
- utils.Fatalf(err.Error())
+ shasum := sha256.Sum256(ruleJS)
+ foundShaSum := hex.EncodeToString(shasum[:])
+ storedShasum := configStorage.Get("ruleset_sha256")
+ if storedShasum != foundShaSum {
+ log.Info("Could not validate ruleset hash, rules not enabled", "got", foundShaSum, "expected", storedShasum)
+ } else {
+ // Initialize rules
+ ruleEngine, err := rules.NewRuleEvaluator(ui, jsStorage)
+ if err != nil {
+ utils.Fatalf(err.Error())
+ }
+ ruleEngine.Init(string(ruleJS))
+ ui = ruleEngine
+ log.Info("Rule engine configured", "file", c.String(ruleFlag.Name))
}
- ruleEngine.Init(string(ruleJS))
- ui = ruleEngine
- log.Info("Rule engine configured", "file", c.String(ruleFlag.Name))
}
}
}
@@ -427,7 +425,7 @@ func signer(c *cli.Context) error {
log.Info("Starting signer", "chainid", chainId, "keystore", ksLoc,
"light-kdf", lightKdf, "advanced", advanced)
am := core.StartClefAccountManager(ksLoc, nousb, lightKdf)
- apiImpl := core.NewSignerAPI(am, chainId, nousb, ui, db, advanced)
+ apiImpl := core.NewSignerAPI(am, chainId, nousb, ui, db, advanced, pwStorage)
// Establish the bidirectional communication, by creating a new UI backend and registering
// it with the UI.
@@ -640,68 +638,124 @@ func testExternalUI(api *core.SignerAPI) {
ctx := context.WithValue(context.Background(), "remote", "clef binary")
ctx = context.WithValue(ctx, "scheme", "in-proc")
ctx = context.WithValue(ctx, "local", "main")
-
errs := make([]string, 0)
- api.UI.ShowInfo("Testing 'ShowInfo'")
- api.UI.ShowError("Testing 'ShowError'")
+ a := common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef")
- checkErr := func(method string, err error) {
- if err != nil && err != core.ErrRequestDenied {
- errs = append(errs, fmt.Sprintf("%v: %v", method, err.Error()))
+ queryUser := func(q string) string {
+ resp, err := api.UI.OnInputRequired(core.UserInputRequest{
+ Title: "Testing",
+ Prompt: q,
+ })
+ if err != nil {
+ errs = append(errs, err.Error())
+ }
+ return resp.Text
+ }
+ expectResponse := func(testcase, question, expect string) {
+ if got := queryUser(question); got != expect {
+ errs = append(errs, fmt.Sprintf("%s: got %v, expected %v", testcase, got, expect))
}
}
- var err error
-
- cliqueHeader := types.Header{
- common.HexToHash("0000H45H"),
- common.HexToHash("0000H45H"),
- common.HexToAddress("0000H45H"),
- common.HexToHash("0000H00H"),
- common.HexToHash("0000H45H"),
- common.HexToHash("0000H45H"),
- types.Bloom{},
- big.NewInt(1337),
- big.NewInt(1337),
- 1338,
- 1338,
- big.NewInt(1338),
- []byte("Extra data Extra data Extra data Extra data Extra data Extra data Extra data Extra data"),
- common.HexToHash("0x0000H45H"),
- types.BlockNonce{},
- }
- cliqueRlp, err := rlp.EncodeToBytes(cliqueHeader)
- if err != nil {
- utils.Fatalf("Should not error: %v", err)
- }
- addr, err := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899")
- if err != nil {
- utils.Fatalf("Should not error: %v", err)
- }
- _, err = api.SignData(ctx, "application/clique", *addr, cliqueRlp)
- checkErr("SignData", err)
-
- _, err = api.SignTransaction(ctx, core.SendTxArgs{From: common.MixedcaseAddress{}}, nil)
- checkErr("SignTransaction", err)
- _, err = api.SignData(ctx, "text/plain", common.MixedcaseAddress{}, common.Hex2Bytes("01020304"))
- checkErr("SignData", err)
- //_, err = api.SignTypedData(ctx, common.MixedcaseAddress{}, core.TypedData{})
- //checkErr("SignTypedData", err)
- _, err = api.List(ctx)
- checkErr("List", err)
- _, err = api.New(ctx)
- checkErr("New", err)
-
- api.UI.ShowInfo("Tests completed")
-
- if len(errs) > 0 {
- log.Error("Got errors")
- for _, e := range errs {
- log.Error(e)
+ expectApprove := func(testcase string, err error) {
+ if err == nil || err == accounts.ErrUnknownAccount {
+ return
}
- } else {
- log.Info("No errors")
+ errs = append(errs, fmt.Sprintf("%v: expected no error, got %v", testcase, err.Error()))
}
+ expectDeny := func(testcase string, err error) {
+ if err == nil || err != core.ErrRequestDenied {
+ errs = append(errs, fmt.Sprintf("%v: expected ErrRequestDenied, got %v", testcase, err))
+ }
+ }
+
+ // Test display of info and error
+ {
+ api.UI.ShowInfo("If you see this message, enter 'yes' to next question")
+ expectResponse("showinfo", "Did you see the message? [yes/no]", "yes")
+ api.UI.ShowError("If you see this message, enter 'yes' to the next question")
+ expectResponse("showerror", "Did you see the message? [yes/no]", "yes")
+ }
+ { // Sign data test - clique header
+ api.UI.ShowInfo("Please approve the next request for signing a clique header")
+ cliqueHeader := types.Header{
+ common.HexToHash("0000H45H"),
+ common.HexToHash("0000H45H"),
+ common.HexToAddress("0000H45H"),
+ common.HexToHash("0000H00H"),
+ common.HexToHash("0000H45H"),
+ common.HexToHash("0000H45H"),
+ types.Bloom{},
+ big.NewInt(1337),
+ big.NewInt(1337),
+ 1338,
+ 1338,
+ big.NewInt(1338),
+ []byte("Extra data Extra data Extra data Extra data Extra data Extra data Extra data Extra data"),
+ common.HexToHash("0x0000H45H"),
+ types.BlockNonce{},
+ }
+ cliqueRlp, err := rlp.EncodeToBytes(cliqueHeader)
+ if err != nil {
+ utils.Fatalf("Should not error: %v", err)
+ }
+ addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899")
+ _, err = api.SignData(ctx, accounts.MimetypeClique, *addr, hexutil.Encode(cliqueRlp))
+ expectApprove("signdata - clique header", err)
+ }
+ { // Sign data test - plain text
+ api.UI.ShowInfo("Please approve the next request for signing text")
+ addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899")
+ _, err := api.SignData(ctx, accounts.MimetypeTextPlain, *addr, hexutil.Encode([]byte("hello world")))
+ expectApprove("signdata - text", err)
+ }
+ { // Sign data test - plain text reject
+ api.UI.ShowInfo("Please deny the next request for signing text")
+ addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899")
+ _, err := api.SignData(ctx, accounts.MimetypeTextPlain, *addr, hexutil.Encode([]byte("hello world")))
+ expectDeny("signdata - text", err)
+ }
+ { // Sign transaction
+
+ api.UI.ShowInfo("Please reject next transaction")
+ data := hexutil.Bytes([]byte{})
+ to := common.NewMixedcaseAddress(a)
+ tx := core.SendTxArgs{
+ Data: &data,
+ Nonce: 0x1,
+ Value: hexutil.Big(*big.NewInt(6)),
+ From: common.NewMixedcaseAddress(a),
+ To: &to,
+ GasPrice: hexutil.Big(*big.NewInt(5)),
+ Gas: 1000,
+ Input: nil,
+ }
+ _, err := api.SignTransaction(ctx, tx, nil)
+ expectDeny("signtransaction [1]", err)
+ expectResponse("signtransaction [2]", "Did you see any warnings for the last transaction? (yes/no)", "no")
+ }
+ { // Listing
+ api.UI.ShowInfo("Please reject listing-request")
+ _, err := api.List(ctx)
+ expectDeny("list", err)
+ }
+ { // Import
+ api.UI.ShowInfo("Please reject new account-request")
+ _, err := api.New(ctx)
+ expectDeny("newaccount", err)
+ }
+ { // Metadata
+ api.UI.ShowInfo("Please check if you see the Origin in next listing (approve or deny)")
+ api.List(context.WithValue(ctx, "Origin", "origin.com"))
+ expectResponse("metadata - origin", "Did you see origin (origin.com)? [yes/no] ", "yes")
+ }
+
+ for _, e := range errs {
+ log.Error(e)
+ }
+ result := fmt.Sprintf("Tests completed. %d errors:\n%s\n", len(errs), strings.Join(errs, "\n"))
+ api.UI.ShowInfo(result)
+
}
// getPassPhrase retrieves the password associated with clef, either fetched
@@ -798,7 +852,7 @@ func GenDoc(ctx *cli.Context) {
}
{ // Sign plain text response
add("SignDataResponse - approve", "Response to SignDataRequest",
- &core.SignDataResponse{Password: "apassword", Approved: true})
+ &core.SignDataResponse{Approved: true})
add("SignDataResponse - deny", "Response to SignDataRequest",
&core.SignDataResponse{})
}
@@ -833,9 +887,9 @@ func GenDoc(ctx *cli.Context) {
}
{ // Sign tx response
data := hexutil.Bytes([]byte{0x04, 0x03, 0x02, 0x01})
- add("SignDataResponse - approve", "Response to SignDataRequest. This response needs to contain the `transaction`"+
+ add("SignTxResponse - approve", "Response to request to sign a transaction. This response needs to contain the `transaction`"+
", because the UI is free to make modifications to the transaction.",
- &core.SignTxResponse{Password: "apassword", Approved: true,
+ &core.SignTxResponse{Approved: true,
Transaction: core.SendTxArgs{
Data: &data,
Nonce: 0x4,
@@ -846,9 +900,9 @@ func GenDoc(ctx *cli.Context) {
Gas: 1000,
Input: nil,
}})
- add("SignDataResponse - deny", "Response to SignDataRequest. When denying a request, there's no need to "+
+ add("SignTxResponse - deny", "Response to SignTxRequest. When denying a request, there's no need to "+
"provide the transaction in return",
- &core.SignDataResponse{})
+ &core.SignTxResponse{})
}
{ // WHen a signed tx is ready to go out
desc := "SignTransactionResult is used in the call `clef` -> `OnApprovedTx(result)`" +
@@ -874,7 +928,7 @@ func GenDoc(ctx *cli.Context) {
{ // User input
add("UserInputRequest", "Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free)",
&core.UserInputRequest{IsPassword: true, Title: "The title here", Prompt: "The question to ask the user"})
- add("UserInputResponse", "Response to SignDataRequest",
+ add("UserInputResponse", "Response to UserInputRequest",
&core.UserInputResponse{Text: "The textual response from user"})
}
{ // List request
@@ -888,7 +942,7 @@ func GenDoc(ctx *cli.Context) {
{b, accounts.URL{Scheme: "keystore", Path: "/path/to/keyfile/b"}}},
})
- add("UserInputResponse", "Response to list request. The response contains a list of all addresses to show to the caller. "+
+ add("ListResponse", "Response to list request. The response contains a list of all addresses to show to the caller. "+
"Note: the UI is free to respond with any address the caller, regardless of whether it exists or not",
&core.ListResponse{
Accounts: []accounts.Account{
diff --git a/cmd/evm/internal/compiler/compiler.go b/cmd/evm/internal/compiler/compiler.go
index 753ca62264..54981b6697 100644
--- a/cmd/evm/internal/compiler/compiler.go
+++ b/cmd/evm/internal/compiler/compiler.go
@@ -25,7 +25,7 @@ import (
func Compile(fn string, src []byte, debug bool) (string, error) {
compiler := asm.NewCompiler(debug)
- compiler.Feed(asm.Lex(fn, src, debug))
+ compiler.Feed(asm.Lex(src, debug))
bin, compileErrors := compiler.Compile()
if len(compileErrors) > 0 {
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index c732c8b574..bc5d00cfbe 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -31,10 +31,10 @@ import (
"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/rawdb"
"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"
@@ -99,12 +99,12 @@ func runCmd(ctx *cli.Context) error {
if ctx.GlobalString(GenesisFlag.Name) != "" {
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
genesisConfig = gen
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := gen.ToBlock(db)
statedb, _ = state.New(genesis.Root(), state.NewDatabase(db))
chainConfig = gen.Config
} else {
- statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
genesisConfig = new(core.Genesis)
}
if ctx.GlobalString(SenderFlag.Name) != "" {
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 6d41261f80..72aace1c63 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -29,14 +29,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/syndtr/goleveldb/leveldb/util"
"gopkg.in/urfave/cli.v1"
)
@@ -193,7 +191,7 @@ func initGenesis(ctx *cli.Context) error {
defer stack.Close()
for _, name := range []string{"chaindata", "lightchaindata"} {
- chaindb, err := stack.OpenDatabase(name, 0, 0)
+ chaindb, err := stack.OpenDatabase(name, 0, 0, "")
if err != nil {
utils.Fatalf("Failed to open database: %v", err)
}
@@ -201,6 +199,7 @@ func initGenesis(ctx *cli.Context) error {
if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err)
}
+ chaindb.Close()
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
}
return nil
@@ -213,8 +212,8 @@ func importChain(ctx *cli.Context) error {
stack := makeFullNode(ctx)
defer stack.Close()
- chain, chainDb := utils.MakeChain(ctx, stack)
- defer chainDb.Close()
+ chain, db := utils.MakeChain(ctx, stack)
+ defer db.Close()
// Start periodically gathering memory profiles
var peakMemAlloc, peakMemSys uint64
@@ -249,23 +248,18 @@ func importChain(ctx *cli.Context) error {
fmt.Printf("Import done in %v.\n\n", time.Since(start))
// Output pre-compaction stats mostly to see the import trashing
- db := chainDb.(*ethdb.LDBDatabase)
-
- stats, err := db.LDB().GetProperty("leveldb.stats")
+ stats, err := db.Stat("leveldb.stats")
if err != nil {
utils.Fatalf("Failed to read database stats: %v", err)
}
fmt.Println(stats)
- ioStats, err := db.LDB().GetProperty("leveldb.iostats")
+ ioStats, err := db.Stat("leveldb.iostats")
if err != nil {
utils.Fatalf("Failed to read database iostats: %v", err)
}
fmt.Println(ioStats)
- fmt.Printf("Trie cache misses: %d\n", trie.CacheMisses())
- fmt.Printf("Trie cache unloads: %d\n\n", trie.CacheUnloads())
-
// Print the memory statistics used by the importing
mem := new(runtime.MemStats)
runtime.ReadMemStats(mem)
@@ -282,23 +276,22 @@ func importChain(ctx *cli.Context) error {
// Compact the entire database to more accurately measure disk io and print the stats
start = time.Now()
fmt.Println("Compacting entire database...")
- if err = db.LDB().CompactRange(util.Range{}); err != nil {
+ if err = db.Compact(nil, nil); err != nil {
utils.Fatalf("Compaction failed: %v", err)
}
fmt.Printf("Compaction done in %v.\n\n", time.Since(start))
- stats, err = db.LDB().GetProperty("leveldb.stats")
+ stats, err = db.Stat("leveldb.stats")
if err != nil {
utils.Fatalf("Failed to read database stats: %v", err)
}
fmt.Println(stats)
- ioStats, err = db.LDB().GetProperty("leveldb.iostats")
+ ioStats, err = db.Stat("leveldb.iostats")
if err != nil {
utils.Fatalf("Failed to read database iostats: %v", err)
}
fmt.Println(ioStats)
-
return nil
}
@@ -344,10 +337,10 @@ func importPreimages(ctx *cli.Context) error {
stack := makeFullNode(ctx)
defer stack.Close()
- diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase)
+ db := utils.MakeChainDatabase(ctx, stack)
start := time.Now()
- if err := utils.ImportPreimages(diskdb, ctx.Args().First()); err != nil {
+ if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil {
utils.Fatalf("Import error: %v\n", err)
}
fmt.Printf("Import done in %v\n", time.Since(start))
@@ -362,10 +355,10 @@ func exportPreimages(ctx *cli.Context) error {
stack := makeFullNode(ctx)
defer stack.Close()
- diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase)
+ db := utils.MakeChainDatabase(ctx, stack)
start := time.Now()
- if err := utils.ExportPreimages(diskdb, ctx.Args().First()); err != nil {
+ if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil {
utils.Fatalf("Export error: %v\n", err)
}
fmt.Printf("Export done in %v\n", time.Since(start))
@@ -386,7 +379,7 @@ func copyDb(ctx *cli.Context) error {
dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil)
// Create a source peer to satisfy downloader requests from
- db, err := ethdb.NewLDBDatabase(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256)
+ db, err := rawdb.NewLevelDBDatabase(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256, "")
if err != nil {
return err
}
@@ -413,11 +406,10 @@ func copyDb(ctx *cli.Context) error {
// Compact the entire database to remove any sync overhead
start = time.Now()
fmt.Println("Compacting entire database...")
- if err = chainDb.(*ethdb.LDBDatabase).LDB().CompactRange(util.Range{}); err != nil {
+ if err = db.Compact(nil, nil); err != nil {
utils.Fatalf("Compaction failed: %v", err)
}
fmt.Printf("Compaction done in %v.\n\n", time.Since(start))
-
return nil
}
diff --git a/cmd/geth/dao_test.go b/cmd/geth/dao_test.go
index 52983ff2af..cb06038ec8 100644
--- a/cmd/geth/dao_test.go
+++ b/cmd/geth/dao_test.go
@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -121,7 +120,7 @@ func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBloc
}
// Retrieve the DAO config flag from the database
path := filepath.Join(datadir, "geth", "chaindata")
- db, err := ethdb.NewLDBDatabase(path, 0, 0)
+ db, err := rawdb.NewLevelDBDatabase(path, 0, 0, "")
if err != nil {
t.Fatalf("test %d: failed to open test database: %v", test, err)
}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index a331abc9fd..f966905a92 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -102,7 +102,6 @@ var (
utils.CacheDatabaseFlag,
utils.CacheTrieFlag,
utils.CacheGCFlag,
- utils.TrieCacheGenFlag,
utils.ListenPortFlag,
utils.MaxPeersFlag,
utils.MaxPendingPeersFlag,
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 0338e447e4..a4787fff2b 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -139,7 +139,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.CacheDatabaseFlag,
utils.CacheTrieFlag,
utils.CacheGCFlag,
- utils.TrieCacheGenFlag,
},
},
{
diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go
index 0e1e5e39ba..a941b37579 100644
--- a/cmd/swarm/config.go
+++ b/cmd/swarm/config.go
@@ -255,8 +255,8 @@ func cmdLineOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Con
currentConfig.LocalStoreParams.DbCapacity = storeCapacity
}
- if storeCacheCapacity := ctx.GlobalUint(SwarmStoreCacheCapacity.Name); storeCacheCapacity != 0 {
- currentConfig.LocalStoreParams.CacheCapacity = storeCacheCapacity
+ if ctx.GlobalIsSet(SwarmStoreCacheCapacity.Name) {
+ currentConfig.LocalStoreParams.CacheCapacity = ctx.GlobalUint(SwarmStoreCacheCapacity.Name)
}
if ctx.GlobalIsSet(SwarmBootnodeModeFlag.Name) {
diff --git a/cmd/swarm/run_test.go b/cmd/swarm/run_test.go
index 4a6a56d9b8..9681c8990a 100644
--- a/cmd/swarm/run_test.go
+++ b/cmd/swarm/run_test.go
@@ -82,6 +82,18 @@ func TestMain(m *testing.M) {
func runSwarm(t *testing.T, args ...string) *cmdtest.TestCmd {
tt := cmdtest.NewTestCmd(t, nil)
+ found := false
+ for _, v := range args {
+ if v == "--bootnodes" {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ args = append([]string{"--bootnodes", ""}, args...)
+ }
+
// Boot "swarm". This actually runs the test binary but the TestMain
// function will prevent any tests from running.
tt.Run("swarm-test", args...)
@@ -252,6 +264,7 @@ func existingTestNode(t *testing.T, dir string, bzzaccount string) *testNode {
// start the node
node.Cmd = runSwarm(t,
+ "--bootnodes", "",
"--port", p2pPort,
"--nat", "extip:127.0.0.1",
"--datadir", dir,
@@ -327,6 +340,7 @@ func newTestNode(t *testing.T, dir string) *testNode {
// start the node
node.Cmd = runSwarm(t,
+ "--bootnodes", "",
"--port", p2pPort,
"--nat", "extip:127.0.0.1",
"--datadir", dir,
diff --git a/cmd/swarm/swarm-smoke/upload_and_sync.go b/cmd/swarm/swarm-smoke/upload_and_sync.go
index 90230df253..23b7d56884 100644
--- a/cmd/swarm/swarm-smoke/upload_and_sync.go
+++ b/cmd/swarm/swarm-smoke/upload_and_sync.go
@@ -23,6 +23,7 @@ import (
"io/ioutil"
"math/rand"
"os"
+ "strings"
"sync"
"time"
@@ -67,41 +68,50 @@ func uploadAndSyncCmd(ctx *cli.Context, tuid string) error {
}
func trackChunks(testData []byte) error {
- log.Warn("Test timed out; running chunk debug sequence")
+ log.Warn("Test timed out, running chunk debug sequence")
addrs, err := getAllRefs(testData)
if err != nil {
return err
}
- log.Trace("All references retrieved")
- // has-chunks
+ for i, ref := range addrs {
+ log.Trace(fmt.Sprintf("ref %d", i), "ref", ref)
+ }
+
for _, host := range hosts {
httpHost := fmt.Sprintf("ws://%s:%d", host, 8546)
- log.Trace("Calling `Has` on host", "httpHost", httpHost)
+
+ hostChunks := []string{}
+
rpcClient, err := rpc.Dial(httpHost)
if err != nil {
- log.Trace("Error dialing host", "err", err)
+ log.Error("Error dialing host", "err", err)
return err
}
- log.Trace("rpc dial ok")
+
var hasInfo []api.HasInfo
err = rpcClient.Call(&hasInfo, "bzz_has", addrs)
if err != nil {
- log.Trace("Error calling host", "err", err)
+ log.Error("Error calling host", "err", err)
return err
}
- log.Trace("rpc call ok")
+
count := 0
for _, info := range hasInfo {
- if !info.Has {
+ if info.Has {
+ hostChunks = append(hostChunks, "1")
+ } else {
+ hostChunks = append(hostChunks, "0")
count++
- log.Error("Host does not have chunk", "host", httpHost, "chunk", info.Addr)
}
}
+
if count == 0 {
- log.Info("Host reported to have all chunks", "host", httpHost)
+ log.Info("host reported to have all chunks", "host", host)
}
+
+ log.Trace("chunks", "chunks", strings.Join(hostChunks, ""), "host", host)
}
return nil
}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index f23aa5775b..74a8c7f394 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -238,7 +238,7 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
}
// ImportPreimages imports a batch of exported hash preimages into the database.
-func ImportPreimages(db *ethdb.LDBDatabase, fn string) error {
+func ImportPreimages(db ethdb.Database, fn string) error {
log.Info("Importing preimages", "file", fn)
// Open the file handle and potentially unwrap the gzip stream
@@ -285,7 +285,7 @@ func ImportPreimages(db *ethdb.LDBDatabase, fn string) error {
// 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 {
+func ExportPreimages(db ethdb.Database, fn string) error {
log.Info("Exporting preimages", "file", fn)
// Open the file handle and potentially wrap with a gzip stream
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 4db59097d7..e00f92fa75 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -37,7 +37,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
"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/crypto"
"github.com/ethereum/go-ethereum/dashboard"
@@ -350,11 +349,6 @@ var (
Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
Value: 25,
}
- TrieCacheGenFlag = cli.IntFlag{
- Name: "trie-cache-gens",
- Usage: "Number of trie node generations to keep in memory",
- Value: int(state.MaxTrieCacheGen),
- }
// Miner settings
MiningEnabledFlag = cli.BoolFlag{
Name: "mine",
@@ -779,6 +773,7 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
node, err := enode.ParseV4(url)
if err != nil {
log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
+ continue
}
cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
}
@@ -806,12 +801,14 @@ func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
for _, url := range urls {
- node, err := discv5.ParseNode(url)
- if err != nil {
- log.Error("Bootstrap URL invalid", "enode", url, "err", err)
- continue
+ if url != "" {
+ node, err := discv5.ParseNode(url)
+ if err != nil {
+ log.Error("Bootstrap URL invalid", "enode", url, "err", err)
+ continue
+ }
+ cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
}
- cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
}
}
@@ -1432,10 +1429,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.MinerGasPrice = big.NewInt(1)
}
}
- // TODO(fjl): move trie cache generations into config
- if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
- state.MaxTrieCacheGen = uint16(gen)
- }
}
// SetDashboardConfig applies dashboard related command line flags to the config.
@@ -1548,7 +1541,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
if ctx.GlobalString(SyncModeFlag.Name) == "light" {
name = "lightchaindata"
}
- chainDb, err := stack.OpenDatabase(name, cache, handles)
+ chainDb, err := stack.OpenDatabase(name, cache, handles, "")
if err != nil {
Fatalf("Could not open database: %v", err)
}
diff --git a/common/types.go b/common/types.go
index 48043788fd..98c83edd4f 100644
--- a/common/types.go
+++ b/common/types.go
@@ -202,9 +202,6 @@ func IsHexAddress(s string) bool {
// Bytes gets the string representation of the underlying address.
func (a Address) Bytes() []byte { return a[:] }
-// Big converts an address to a big integer.
-func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
-
// Hash converts an address to a hash by left-padding it with zeros.
func (a Address) Hash() Hash { return BytesToHash(a[:]) }
diff --git a/common/types_test.go b/common/types_test.go
index 7095ccd019..fffd673c6e 100644
--- a/common/types_test.go
+++ b/common/types_test.go
@@ -114,8 +114,8 @@ func TestAddressUnmarshalJSON(t *testing.T) {
if test.ShouldErr {
t.Errorf("test #%d: expected error, got none", i)
}
- if v.Big().Cmp(test.Output) != 0 {
- t.Errorf("test #%d: address mismatch: have %v, want %v", i, v.Big(), test.Output)
+ if got := new(big.Int).SetBytes(v.Bytes()); got.Cmp(test.Output) != 0 {
+ t.Errorf("test #%d: address mismatch: have %v, want %v", i, got, test.Output)
}
}
}
diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go
index 489b85898a..fc08722efd 100644
--- a/consensus/clique/snapshot_test.go
+++ b/consensus/clique/snapshot_test.go
@@ -24,10 +24,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -400,7 +400,7 @@ func TestClique(t *testing.T) {
copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:])
}
// Create a pristine blockchain with the genesis injected
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis.Commit(db)
// Assemble a chain of headers from the cast votes
diff --git a/core/asm/lex_test.go b/core/asm/lex_test.go
index e6901d4e37..16e0ad458d 100644
--- a/core/asm/lex_test.go
+++ b/core/asm/lex_test.go
@@ -22,7 +22,7 @@ import (
)
func lexAll(src string) []token {
- ch := Lex("test.asm", []byte(src), false)
+ ch := Lex([]byte(src), false)
var tokens []token
for i := range ch {
diff --git a/core/asm/lexer.go b/core/asm/lexer.go
index 91caeb27bc..00526242e4 100644
--- a/core/asm/lexer.go
+++ b/core/asm/lexer.go
@@ -95,7 +95,7 @@ type lexer struct {
// lex lexes the program by name with the given source. It returns a
// channel on which the tokens are delivered.
-func Lex(name string, source []byte, debug bool) <-chan token {
+func Lex(source []byte, debug bool) <-chan token {
ch := make(chan token)
l := &lexer{
input: string(source),
diff --git a/core/bench_test.go b/core/bench_test.go
index 53cba05170..e0ccef788d 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -150,14 +150,14 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Create the database in memory or in a temporary directory.
var db ethdb.Database
if !disk {
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
} else {
dir, err := ioutil.TempDir("", "eth-core-bench")
if err != nil {
b.Fatalf("cannot create temporary directory: %v", err)
}
defer os.RemoveAll(dir)
- db, err = ethdb.NewLDBDatabase(dir, 128, 128)
+ db, err = rawdb.NewLevelDBDatabase(dir, 128, 128, "")
if err != nil {
b.Fatalf("cannot create temporary database: %v", err)
}
@@ -255,7 +255,7 @@ func benchWriteChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("cannot create temporary directory: %v", err)
}
- db, err := ethdb.NewLDBDatabase(dir, 128, 1024)
+ db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "")
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
@@ -272,7 +272,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
}
defer os.RemoveAll(dir)
- db, err := ethdb.NewLDBDatabase(dir, 128, 1024)
+ db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "")
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
@@ -283,7 +283,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
- db, err := ethdb.NewLDBDatabase(dir, 128, 1024)
+ db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "")
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
diff --git a/core/block_validator.go b/core/block_validator.go
index 3b9496fece..b36ca56d7f 100644
--- a/core/block_validator.go
+++ b/core/block_validator.go
@@ -77,7 +77,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned.
-func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
+func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
header := block.Header()
if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
diff --git a/core/block_validator_test.go b/core/block_validator_test.go
index 9319a7835d..06e2ba1a4f 100644
--- a/core/block_validator_test.go
+++ b/core/block_validator_test.go
@@ -22,9 +22,9 @@ import (
"time"
"github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -32,7 +32,7 @@ import (
func TestHeaderVerification(t *testing.T) {
// Create a simple chain to verify
var (
- testdb = ethdb.NewMemDatabase()
+ testdb = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig}
genesis = gspec.MustCommit(testdb)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
@@ -84,7 +84,7 @@ func TestHeaderConcurrentVerification32(t *testing.T) { testHeaderConcurrentVeri
func testHeaderConcurrentVerification(t *testing.T, threads int) {
// Create a simple chain to verify
var (
- testdb = ethdb.NewMemDatabase()
+ testdb = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig}
genesis = gspec.MustCommit(testdb)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
@@ -156,7 +156,7 @@ func TestHeaderConcurrentAbortion32(t *testing.T) { testHeaderConcurrentAbortion
func testHeaderConcurrentAbortion(t *testing.T, threads int) {
// Create a simple chain to verify
var (
- testdb = ethdb.NewMemDatabase()
+ testdb = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig}
genesis = gspec.MustCommit(testdb)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil)
diff --git a/core/blockchain.go b/core/blockchain.go
index 7b4f4b3038..c4481588f9 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -43,7 +43,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/hashicorp/golang-lru"
+ lru "github.com/hashicorp/golang-lru"
)
var (
@@ -291,7 +291,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
defer bc.chainmu.Unlock()
// Rewind the header chain, deleting all block bodies until then
- delFn := func(db rawdb.DatabaseDeleter, hash common.Hash, num uint64) {
+ delFn := func(db ethdb.Deleter, hash common.Hash, num uint64) {
rawdb.DeleteBody(db, hash, num)
}
bc.hc.SetHead(head, delFn)
@@ -342,7 +342,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
if block == nil {
return fmt.Errorf("non existent block [%x…]", hash[:4])
}
- if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB(), 0); err != nil {
+ if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB()); err != nil {
return err
}
// If all checks out, manually set the head block
@@ -1221,9 +1221,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
parent := it.previous()
if parent == nil {
- parent = bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
+ parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
}
- state, err := state.New(parent.Root(), bc.stateCache)
+ state, err := state.New(parent.Root, bc.stateCache)
if err != nil {
return it.index, events, coalescedLogs, err
}
@@ -1236,7 +1236,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
return it.index, events, coalescedLogs, err
}
// Validate the state using the default validator
- if err := bc.Validator().ValidateState(block, parent, state, receipts, usedGas); err != nil {
+ if err := bc.Validator().ValidateState(block, state, receipts, usedGas); err != nil {
bc.reportBlock(block, receipts, err)
return it.index, events, coalescedLogs, err
}
@@ -1368,7 +1368,7 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i
// blocks to regenerate the required state
localTd := bc.GetTd(current.Hash(), current.NumberU64())
if localTd.Cmp(externTd) > 0 {
- log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().NumberU64(), "sidetd", externTd, "localtd", localTd)
+ log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd)
return it.index, nil, nil, err
}
// Gather all the sidechain hashes (full blocks may be memory heavy)
@@ -1376,7 +1376,7 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i
hashes []common.Hash
numbers []uint64
)
- parent := bc.GetHeader(it.previous().Hash(), it.previous().NumberU64())
+ parent := it.previous()
for parent != nil && !bc.HasState(parent.Root) {
hashes = append(hashes, parent.Hash())
numbers = append(numbers, parent.Number.Uint64())
diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go
index f07e24d750..e2a385164c 100644
--- a/core/blockchain_insert.go
+++ b/core/blockchain_insert.go
@@ -111,12 +111,12 @@ func (it *insertIterator) next() (*types.Block, error) {
return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index])
}
-// previous returns the previous block was being processed, or nil
-func (it *insertIterator) previous() *types.Block {
+// previous returns the previous header that was being processed, or nil.
+func (it *insertIterator) previous() *types.Header {
if it.index < 1 {
return nil
}
- return it.chain[it.index-1]
+ return it.chain[it.index-1].Header()
}
// first returns the first block in the it.
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 1ac7b03fc6..d1681ce3b6 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -46,7 +46,7 @@ var (
// header only chain.
func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) {
var (
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
genesis = new(Genesis).MustCommit(db)
)
@@ -149,7 +149,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
blockchain.reportBlock(block, receipts, err)
return err
}
- err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas)
+ err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
@@ -586,7 +586,7 @@ func testInsertNonceError(t *testing.T, full bool) {
func TestFastVsFullChains(t *testing.T) {
// Configure and generate a sample block chain
var (
- gendb = ethdb.NewMemDatabase()
+ gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
@@ -616,7 +616,7 @@ func TestFastVsFullChains(t *testing.T) {
}
})
// Import the chain as an archive node for the comparison baseline
- archiveDb := ethdb.NewMemDatabase()
+ archiveDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer archive.Stop()
@@ -625,7 +625,7 @@ func TestFastVsFullChains(t *testing.T) {
t.Fatalf("failed to process block %d: %v", n, err)
}
// Fast import the chain as a non-archive node to test
- fastDb := ethdb.NewMemDatabase()
+ fastDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer fast.Stop()
@@ -674,7 +674,7 @@ func TestFastVsFullChains(t *testing.T) {
func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Configure and generate a sample block chain
var (
- gendb = ethdb.NewMemDatabase()
+ gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
@@ -702,7 +702,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
}
}
// Import the chain as an archive node and ensure all pointers are updated
- archiveDb := ethdb.NewMemDatabase()
+ archiveDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
@@ -716,7 +716,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
assert(t, "archive", archive, height/2, height/2, height/2)
// Import the chain as a non-archive node and ensure all pointers are updated
- fastDb := ethdb.NewMemDatabase()
+ fastDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer fast.Stop()
@@ -736,7 +736,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
assert(t, "fast", fast, height/2, height/2, 0)
// Import the chain as a light node and ensure all pointers are updated
- lightDb := ethdb.NewMemDatabase()
+ lightDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(lightDb)
light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
@@ -759,7 +759,7 @@ func TestChainTxReorgs(t *testing.T) {
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
gspec = &Genesis{
Config: params.TestChainConfig,
GasLimit: 3141592,
@@ -871,7 +871,7 @@ func TestLogReorgs(t *testing.T) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
// this code generates a log
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
@@ -915,7 +915,7 @@ func TestLogReorgs(t *testing.T) {
func TestReorgSideEvent(t *testing.T) {
var (
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{
@@ -1043,7 +1043,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
func TestEIP155Transition(t *testing.T) {
// Configure and generate a sample block chain
var (
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
@@ -1146,7 +1146,7 @@ func TestEIP155Transition(t *testing.T) {
func TestEIP161AccountRemoval(t *testing.T) {
// Configure and generate a sample block chain
var (
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
@@ -1218,7 +1218,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
@@ -1234,7 +1234,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
}
// Import the canonical and fork chain side by side, verifying the current block
// and current header consistency
- diskdb := ethdb.NewMemDatabase()
+ diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@@ -1263,7 +1263,7 @@ func TestTrieForkGC(t *testing.T) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
@@ -1278,7 +1278,7 @@ func TestTrieForkGC(t *testing.T) {
forks[i] = fork[0]
}
// Import the canonical and fork chain side by side, forcing the trie cache to cache both
- diskdb := ethdb.NewMemDatabase()
+ diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@@ -1309,7 +1309,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
// Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker()
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db)
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
@@ -1317,7 +1317,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
// Import the shared chain and the original canonical one
- diskdb := ethdb.NewMemDatabase()
+ diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@@ -1377,7 +1377,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
)
// Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker()
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := gspec.MustCommit(db)
blockGenerator := func(i int, block *BlockGen) {
@@ -1399,7 +1399,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Import the shared chain and the original canonical one
- diskdb := ethdb.NewMemDatabase()
+ diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@@ -1477,7 +1477,7 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
func TestLowDiffLongChain(t *testing.T) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db)
// We must use a pretty long chain to ensure that the fork doesn't overtake us
@@ -1488,7 +1488,7 @@ func TestLowDiffLongChain(t *testing.T) {
})
// Import the canonical chain
- diskdb := ethdb.NewMemDatabase()
+ diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@@ -1531,12 +1531,12 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db)
// Generate and import the canonical chain
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, nil)
- diskdb := ethdb.NewMemDatabase()
+ diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
if err != nil {
diff --git a/core/chain_indexer.go b/core/chain_indexer.go
index 1adde1fcb4..26538260cc 100644
--- a/core/chain_indexer.go
+++ b/core/chain_indexer.go
@@ -97,7 +97,7 @@ type ChainIndexer struct {
// NewChainIndexer creates a new chain indexer to do background processing on
// chain segments of a given size after certain number of confirmations passed.
// The throttling parameter might be used to prevent database thrashing.
-func NewChainIndexer(chainDb, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer {
+func NewChainIndexer(chainDb ethdb.Database, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer {
c := &ChainIndexer{
chainDb: chainDb,
indexDb: indexDb,
diff --git a/core/chain_indexer_test.go b/core/chain_indexer_test.go
index a029dec626..abf5b3cc14 100644
--- a/core/chain_indexer_test.go
+++ b/core/chain_indexer_test.go
@@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/ethdb"
)
// Runs multiple tests with randomized parameters.
@@ -49,7 +48,7 @@ func TestChainIndexerWithChildren(t *testing.T) {
// multiple backends. The section size and required confirmation count parameters
// are randomized.
func testChainIndexer(t *testing.T, count int) {
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
defer db.Close()
// Create a chain of indexers and ensure they all report empty
@@ -60,7 +59,7 @@ func testChainIndexer(t *testing.T, count int) {
confirmsReq = uint64(rand.Intn(10))
)
backends[i] = &testChainIndexBackend{t: t, processCh: make(chan uint64)}
- backends[i].indexer = NewChainIndexer(db, ethdb.NewTable(db, string([]byte{byte(i)})), backends[i], sectionSize, confirmsReq, 0, fmt.Sprintf("indexer-%d", i))
+ backends[i].indexer = NewChainIndexer(db, rawdb.NewTable(db, string([]byte{byte(i)})), backends[i], sectionSize, confirmsReq, 0, fmt.Sprintf("indexer-%d", i))
if sections, _, _ := backends[i].indexer.Sections(); sections != 0 {
t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, 0)
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 64b64fd6a3..32e3888d55 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -21,10 +21,10 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -36,7 +36,7 @@ func ExampleGenerateChain() {
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
)
// Ensure that key1 has some funds in the genesis block.
diff --git a/core/dao_test.go b/core/dao_test.go
index 966139bce3..4e8dba9e84 100644
--- a/core/dao_test.go
+++ b/core/dao_test.go
@@ -21,8 +21,8 @@ import (
"testing"
"github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -32,13 +32,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
forkBlock := big.NewInt(32)
// Generate a common prefix for both pro-forkers and non-forkers
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
gspec := new(Genesis)
genesis := gspec.MustCommit(db)
prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
// Create the concurrent, conflicting two nodes
- proDb := ethdb.NewMemDatabase()
+ proDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(proDb)
proConf := *params.TestChainConfig
@@ -48,7 +48,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer proBc.Stop()
- conDb := ethdb.NewMemDatabase()
+ conDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(conDb)
conConf := *params.TestChainConfig
@@ -67,7 +67,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
// Create a pro-fork block, and try to feed into the no-fork chain
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
@@ -92,7 +92,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
}
// Create a no-fork block, and try to feed into the pro-fork chain
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
@@ -118,7 +118,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
}
}
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
@@ -138,7 +138,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
}
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
diff --git a/core/genesis.go b/core/genesis.go
index cbb6eecd28..4aa129966f 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -134,7 +134,7 @@ type GenesisMismatchError struct {
}
func (e *GenesisMismatchError) Error() string {
- return fmt.Sprintf("database already contains an incompatible genesis block (have %x, new %x)", e.Stored[:8], e.New[:8])
+ return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
}
// SetupGenesisBlock writes or updates the genesis block in db.
@@ -228,7 +228,7 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
// to the given database (or discards it if nil).
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
if db == nil {
- db = ethdb.NewMemDatabase()
+ db = rawdb.NewMemoryDatabase()
}
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
for addr, account := range g.Alloc {
diff --git a/core/genesis_test.go b/core/genesis_test.go
index c7d54f2057..c6bcd0aa54 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -141,7 +141,7 @@ func TestSetupGenesis(t *testing.T) {
}
for _, test := range tests {
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
config, hash, err := test.fn(db)
// Check the return values.
if !reflect.DeepEqual(err, test.wantErr) {
diff --git a/core/headerchain.go b/core/headerchain.go
index 8904dd887b..027cb798fe 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -33,7 +33,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
- "github.com/hashicorp/golang-lru"
+ lru "github.com/hashicorp/golang-lru"
)
const (
@@ -455,7 +455,7 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
// DeleteCallback is a callback function that is called by SetHead before
// each header is deleted.
-type DeleteCallback func(rawdb.DatabaseDeleter, common.Hash, uint64)
+type DeleteCallback func(ethdb.Deleter, common.Hash, uint64)
// SetHead rewinds the local chain to a new head. Everything above the new head
// will be deleted and the new one set.
diff --git a/core/helper_test.go b/core/helper_test.go
index 051384d854..e61c92dcdd 100644
--- a/core/helper_test.go
+++ b/core/helper_test.go
@@ -19,6 +19,7 @@ package core
import (
"container/list"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@@ -78,7 +79,7 @@ func (tm *TestManager) Db() ethdb.Database {
func NewTestManager() *TestManager {
testManager := &TestManager{}
testManager.eventMux = new(event.TypeMux)
- testManager.db = ethdb.NewMemDatabase()
+ testManager.db = rawdb.NewMemoryDatabase()
// testManager.txPool = NewTxPool(testManager)
// testManager.blockChain = NewBlockChain(testManager)
// testManager.stateManager = NewStateManager(testManager)
diff --git a/core/mkalloc.go b/core/mkalloc.go
index 565e8c5826..5118a4fcb3 100644
--- a/core/mkalloc.go
+++ b/core/mkalloc.go
@@ -52,7 +52,8 @@ func makelist(g *core.Genesis) allocList {
if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 {
panic(fmt.Sprintf("can't encode account %x", addr))
}
- a = append(a, allocItem{addr.Big(), account.Balance})
+ bigAddr := new(big.Int).SetBytes(addr.Bytes())
+ a = append(a, allocItem{bigAddr, account.Balance})
}
sort.Sort(a)
return a
diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go
index 8a95dafe95..ea923f9d18 100644
--- a/core/rawdb/accessors_chain.go
+++ b/core/rawdb/accessors_chain.go
@@ -23,12 +23,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
)
// ReadCanonicalHash retrieves the hash assigned to a canonical block number.
-func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash {
+func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
data, _ := db.Get(headerHashKey(number))
if len(data) == 0 {
return common.Hash{}
@@ -37,21 +38,21 @@ func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash {
}
// WriteCanonicalHash stores the hash assigned to a canonical block number.
-func WriteCanonicalHash(db DatabaseWriter, hash common.Hash, number uint64) {
+func WriteCanonicalHash(db ethdb.Writer, hash common.Hash, number uint64) {
if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil {
log.Crit("Failed to store number to hash mapping", "err", err)
}
}
// DeleteCanonicalHash removes the number to hash canonical mapping.
-func DeleteCanonicalHash(db DatabaseDeleter, number uint64) {
+func DeleteCanonicalHash(db ethdb.Deleter, number uint64) {
if err := db.Delete(headerHashKey(number)); err != nil {
log.Crit("Failed to delete number to hash mapping", "err", err)
}
}
// ReadHeaderNumber returns the header number assigned to a hash.
-func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 {
+func ReadHeaderNumber(db ethdb.Reader, hash common.Hash) *uint64 {
data, _ := db.Get(headerNumberKey(hash))
if len(data) != 8 {
return nil
@@ -61,7 +62,7 @@ func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 {
}
// ReadHeadHeaderHash retrieves the hash of the current canonical head header.
-func ReadHeadHeaderHash(db DatabaseReader) common.Hash {
+func ReadHeadHeaderHash(db ethdb.Reader) common.Hash {
data, _ := db.Get(headHeaderKey)
if len(data) == 0 {
return common.Hash{}
@@ -70,14 +71,14 @@ func ReadHeadHeaderHash(db DatabaseReader) common.Hash {
}
// WriteHeadHeaderHash stores the hash of the current canonical head header.
-func WriteHeadHeaderHash(db DatabaseWriter, hash common.Hash) {
+func WriteHeadHeaderHash(db ethdb.Writer, hash common.Hash) {
if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last header's hash", "err", err)
}
}
// ReadHeadBlockHash retrieves the hash of the current canonical head block.
-func ReadHeadBlockHash(db DatabaseReader) common.Hash {
+func ReadHeadBlockHash(db ethdb.Reader) common.Hash {
data, _ := db.Get(headBlockKey)
if len(data) == 0 {
return common.Hash{}
@@ -86,14 +87,14 @@ func ReadHeadBlockHash(db DatabaseReader) common.Hash {
}
// WriteHeadBlockHash stores the head block's hash.
-func WriteHeadBlockHash(db DatabaseWriter, hash common.Hash) {
+func WriteHeadBlockHash(db ethdb.Writer, hash common.Hash) {
if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last block's hash", "err", err)
}
}
// ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
-func ReadHeadFastBlockHash(db DatabaseReader) common.Hash {
+func ReadHeadFastBlockHash(db ethdb.Reader) common.Hash {
data, _ := db.Get(headFastBlockKey)
if len(data) == 0 {
return common.Hash{}
@@ -102,7 +103,7 @@ func ReadHeadFastBlockHash(db DatabaseReader) common.Hash {
}
// WriteHeadFastBlockHash stores the hash of the current fast-sync head block.
-func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) {
+func WriteHeadFastBlockHash(db ethdb.Writer, hash common.Hash) {
if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last fast block's hash", "err", err)
}
@@ -110,7 +111,7 @@ func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) {
// ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow
// reporting correct numbers across restarts.
-func ReadFastTrieProgress(db DatabaseReader) uint64 {
+func ReadFastTrieProgress(db ethdb.Reader) uint64 {
data, _ := db.Get(fastTrieProgressKey)
if len(data) == 0 {
return 0
@@ -120,20 +121,20 @@ func ReadFastTrieProgress(db DatabaseReader) uint64 {
// WriteFastTrieProgress stores the fast sync trie process counter to support
// retrieving it across restarts.
-func WriteFastTrieProgress(db DatabaseWriter, count uint64) {
+func WriteFastTrieProgress(db ethdb.Writer, count uint64) {
if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil {
log.Crit("Failed to store fast sync trie progress", "err", err)
}
}
// ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
-func ReadHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
+func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(headerKey(number, hash))
return data
}
// HasHeader verifies the existence of a block header corresponding to the hash.
-func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool {
+func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool {
if has, err := db.Has(headerKey(number, hash)); !has || err != nil {
return false
}
@@ -141,7 +142,7 @@ func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool {
}
// ReadHeader retrieves the block header corresponding to the hash.
-func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header {
+func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header {
data := ReadHeaderRLP(db, hash, number)
if len(data) == 0 {
return nil
@@ -156,7 +157,7 @@ func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Heade
// WriteHeader stores a block header into the database and also stores the hash-
// to-number mapping.
-func WriteHeader(db DatabaseWriter, header *types.Header) {
+func WriteHeader(db ethdb.Writer, header *types.Header) {
// Write the hash -> number mapping
var (
hash = header.Hash()
@@ -179,30 +180,36 @@ func WriteHeader(db DatabaseWriter, header *types.Header) {
}
// DeleteHeader removes all block header data associated with a hash.
-func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) {
- if err := db.Delete(headerKey(number, hash)); err != nil {
- log.Crit("Failed to delete header", "err", err)
- }
+func DeleteHeader(db ethdb.Deleter, hash common.Hash, number uint64) {
+ deleteHeaderWithoutNumber(db, hash, number)
if err := db.Delete(headerNumberKey(hash)); err != nil {
log.Crit("Failed to delete hash to number mapping", "err", err)
}
}
+// deleteHeaderWithoutNumber removes only the block header but does not remove
+// the hash to number mapping.
+func deleteHeaderWithoutNumber(db ethdb.Deleter, hash common.Hash, number uint64) {
+ if err := db.Delete(headerKey(number, hash)); err != nil {
+ log.Crit("Failed to delete header", "err", err)
+ }
+}
+
// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
-func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
+func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(blockBodyKey(number, hash))
return data
}
// WriteBodyRLP stores an RLP encoded block body into the database.
-func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
+func WriteBodyRLP(db ethdb.Writer, hash common.Hash, number uint64, rlp rlp.RawValue) {
if err := db.Put(blockBodyKey(number, hash), rlp); err != nil {
log.Crit("Failed to store block body", "err", err)
}
}
// HasBody verifies the existence of a block body corresponding to the hash.
-func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool {
+func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
return false
}
@@ -210,7 +217,7 @@ func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool {
}
// ReadBody retrieves the block body corresponding to the hash.
-func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
+func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body {
data := ReadBodyRLP(db, hash, number)
if len(data) == 0 {
return nil
@@ -224,7 +231,7 @@ func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
}
// WriteBody storea a block body into the database.
-func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) {
+func WriteBody(db ethdb.Writer, hash common.Hash, number uint64, body *types.Body) {
data, err := rlp.EncodeToBytes(body)
if err != nil {
log.Crit("Failed to RLP encode body", "err", err)
@@ -233,15 +240,21 @@ func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.B
}
// DeleteBody removes all block body data associated with a hash.
-func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) {
+func DeleteBody(db ethdb.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(blockBodyKey(number, hash)); err != nil {
log.Crit("Failed to delete block body", "err", err)
}
}
-// ReadTd retrieves a block's total difficulty corresponding to the hash.
-func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
+// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
+func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(headerTDKey(number, hash))
+ return data
+}
+
+// ReadTd retrieves a block's total difficulty corresponding to the hash.
+func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int {
+ data := ReadTdRLP(db, hash, number)
if len(data) == 0 {
return nil
}
@@ -254,7 +267,7 @@ func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
}
// WriteTd stores the total difficulty of a block into the database.
-func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) {
+func WriteTd(db ethdb.Writer, hash common.Hash, number uint64, td *big.Int) {
data, err := rlp.EncodeToBytes(td)
if err != nil {
log.Crit("Failed to RLP encode block total difficulty", "err", err)
@@ -265,7 +278,7 @@ func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) {
}
// DeleteTd removes all block total difficulty data associated with a hash.
-func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
+func DeleteTd(db ethdb.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(headerTDKey(number, hash)); err != nil {
log.Crit("Failed to delete block total difficulty", "err", err)
}
@@ -273,17 +286,23 @@ func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
// HasReceipts verifies the existence of all the transaction receipts belonging
// to a block.
-func HasReceipts(db DatabaseReader, hash common.Hash, number uint64) bool {
+func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
return false
}
return true
}
-// ReadReceipts retrieves all the transaction receipts belonging to a block.
-func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts {
- // Retrieve the flattened receipt slice
+// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
+func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(blockReceiptsKey(number, hash))
+ return data
+}
+
+// ReadReceipts retrieves all the transaction receipts belonging to a block.
+func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts {
+ // Retrieve the flattened receipt slice
+ data := ReadReceiptsRLP(db, hash, number)
if len(data) == 0 {
return nil
}
@@ -311,7 +330,7 @@ func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Rece
}
// WriteReceipts stores all the transaction receipts belonging to a block.
-func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) {
+func WriteReceipts(db ethdb.Writer, hash common.Hash, number uint64, receipts types.Receipts) {
// Convert the receipts into their storage form and serialize them
storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
for i, receipt := range receipts {
@@ -328,7 +347,7 @@ func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts
}
// DeleteReceipts removes all receipt data associated with a block hash.
-func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
+func DeleteReceipts(db ethdb.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
log.Crit("Failed to delete block receipts", "err", err)
}
@@ -340,7 +359,7 @@ func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
//
// Note, due to concurrent download of header and block body the header and thus
// canonical hash can be stored in the database but the body data not (yet).
-func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block {
+func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
header := ReadHeader(db, hash, number)
if header == nil {
return nil
@@ -353,21 +372,30 @@ func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block
}
// WriteBlock serializes a block into the database, header and body separately.
-func WriteBlock(db DatabaseWriter, block *types.Block) {
+func WriteBlock(db ethdb.Writer, block *types.Block) {
WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
WriteHeader(db, block.Header())
}
// DeleteBlock removes all block data associated with a hash.
-func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) {
+func DeleteBlock(db ethdb.Deleter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number)
DeleteHeader(db, hash, number)
DeleteBody(db, hash, number)
DeleteTd(db, hash, number)
}
+// deleteBlockWithoutNumber removes all block data associated with a hash, except
+// the hash to number mapping.
+func deleteBlockWithoutNumber(db ethdb.Deleter, hash common.Hash, number uint64) {
+ DeleteReceipts(db, hash, number)
+ deleteHeaderWithoutNumber(db, hash, number)
+ DeleteBody(db, hash, number)
+ DeleteTd(db, hash, number)
+}
+
// FindCommonAncestor returns the last common ancestor of two block headers
-func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header {
+func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header {
for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
if a == nil {
diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go
index 37e0d4fda1..9f6e9cdb3e 100644
--- a/core/rawdb/accessors_chain_test.go
+++ b/core/rawdb/accessors_chain_test.go
@@ -23,14 +23,13 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
)
// Tests block header storage and retrieval operations.
func TestHeaderStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
// Create a test header to move around the database and make sure it's really new
header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
@@ -63,7 +62,7 @@ func TestHeaderStorage(t *testing.T) {
// Tests block body storage and retrieval operations.
func TestBodyStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
// Create a test body to move around the database and make sure it's really new
body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
@@ -101,7 +100,7 @@ func TestBodyStorage(t *testing.T) {
// Tests block storage and retrieval operations.
func TestBlockStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
// Create a test block to move around the database and make sure it's really new
block := types.NewBlockWithHeader(&types.Header{
@@ -151,7 +150,7 @@ func TestBlockStorage(t *testing.T) {
// Tests that partial block contents don't get reassembled into full blocks.
func TestPartialBlockStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
block := types.NewBlockWithHeader(&types.Header{
Extra: []byte("test block"),
UncleHash: types.EmptyUncleHash,
@@ -185,7 +184,7 @@ func TestPartialBlockStorage(t *testing.T) {
// Tests block total difficulty storage and retrieval operations.
func TestTdStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
// Create a test TD to move around the database and make sure it's really new
hash, td := common.Hash{}, big.NewInt(314)
@@ -208,7 +207,7 @@ func TestTdStorage(t *testing.T) {
// Tests that canonical numbers can be mapped to hashes and retrieved.
func TestCanonicalMappingStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
// Create a test canonical number and assinged hash to move around
hash, number := common.Hash{0: 0xff}, uint64(314)
@@ -231,7 +230,7 @@ func TestCanonicalMappingStorage(t *testing.T) {
// Tests that head headers and head blocks can be assigned, individually.
func TestHeadStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
@@ -266,7 +265,7 @@ func TestHeadStorage(t *testing.T) {
// Tests that receipts associated with a single block can be stored and retrieved.
func TestBlockReceiptStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
receipt1 := &types.Receipt{
Status: types.ReceiptStatusFailed,
diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go
index e6f7782a12..d90a430129 100644
--- a/core/rawdb/accessors_indexes.go
+++ b/core/rawdb/accessors_indexes.go
@@ -19,13 +19,14 @@ package rawdb
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
)
// ReadTxLookupEntry retrieves the positional metadata associated with a transaction
// hash to allow retrieving the transaction or receipt by hash.
-func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) common.Hash {
+func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) common.Hash {
data, _ := db.Get(txLookupKey(hash))
if len(data) == 0 {
return common.Hash{}
@@ -44,7 +45,7 @@ func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) common.Hash {
// WriteTxLookupEntries stores a positional metadata for every transaction from
// a block, enabling hash based transaction and receipt lookups.
-func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) {
+func WriteTxLookupEntries(db ethdb.Writer, block *types.Block) {
for _, tx := range block.Transactions() {
if err := db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes()); err != nil {
log.Crit("Failed to store transaction lookup entry", "err", err)
@@ -53,13 +54,13 @@ func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) {
}
// DeleteTxLookupEntry removes all transaction data associated with a hash.
-func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) {
+func DeleteTxLookupEntry(db ethdb.Deleter, hash common.Hash) {
db.Delete(txLookupKey(hash))
}
// ReadTransaction retrieves a specific transaction from the database, along with
// its added positional metadata.
-func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
+func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
blockHash := ReadTxLookupEntry(db, hash)
if blockHash == (common.Hash{}) {
return nil, common.Hash{}, 0, 0
@@ -84,7 +85,7 @@ func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, c
// ReadReceipt retrieves a specific transaction receipt from the database, along with
// its added positional metadata.
-func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) {
+func ReadReceipt(db ethdb.Reader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) {
blockHash := ReadTxLookupEntry(db, hash)
if blockHash == (common.Hash{}) {
return nil, common.Hash{}, 0, 0
@@ -105,13 +106,13 @@ func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Ha
// ReadBloomBits retrieves the compressed bloom bit vector belonging to the given
// section and bit index from the.
-func ReadBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) ([]byte, error) {
+func ReadBloomBits(db ethdb.Reader, bit uint, section uint64, head common.Hash) ([]byte, error) {
return db.Get(bloomBitsKey(bit, section, head))
}
// WriteBloomBits stores the compressed bloom bits vector belonging to the given
// section and bit index.
-func WriteBloomBits(db DatabaseWriter, bit uint, section uint64, head common.Hash, bits []byte) {
+func WriteBloomBits(db ethdb.Writer, bit uint, section uint64, head common.Hash, bits []byte) {
if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil {
log.Crit("Failed to store bloom bits", "err", err)
}
diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go
index bed03a5e6b..ca74ba6af1 100644
--- a/core/rawdb/accessors_indexes_test.go
+++ b/core/rawdb/accessors_indexes_test.go
@@ -22,13 +22,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
)
// Tests that positional lookup metadata can be stored and retrieved.
func TestLookupStorage(t *testing.T) {
- db := ethdb.NewMemDatabase()
+ db := NewMemoryDatabase()
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22})
diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go
index 82e4bf0455..1361b0d731 100644
--- a/core/rawdb/accessors_metadata.go
+++ b/core/rawdb/accessors_metadata.go
@@ -20,13 +20,14 @@ import (
"encoding/json"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
// ReadDatabaseVersion retrieves the version number of the database.
-func ReadDatabaseVersion(db DatabaseReader) *uint64 {
+func ReadDatabaseVersion(db ethdb.Reader) *uint64 {
var version uint64
enc, _ := db.Get(databaseVerisionKey)
@@ -41,7 +42,7 @@ func ReadDatabaseVersion(db DatabaseReader) *uint64 {
}
// WriteDatabaseVersion stores the version number of the database
-func WriteDatabaseVersion(db DatabaseWriter, version uint64) {
+func WriteDatabaseVersion(db ethdb.Writer, version uint64) {
enc, err := rlp.EncodeToBytes(version)
if err != nil {
log.Crit("Failed to encode database version", "err", err)
@@ -52,7 +53,7 @@ func WriteDatabaseVersion(db DatabaseWriter, version uint64) {
}
// ReadChainConfig retrieves the consensus settings based on the given genesis hash.
-func ReadChainConfig(db DatabaseReader, hash common.Hash) *params.ChainConfig {
+func ReadChainConfig(db ethdb.Reader, hash common.Hash) *params.ChainConfig {
data, _ := db.Get(configKey(hash))
if len(data) == 0 {
return nil
@@ -66,7 +67,7 @@ func ReadChainConfig(db DatabaseReader, hash common.Hash) *params.ChainConfig {
}
// WriteChainConfig writes the chain config settings to the database.
-func WriteChainConfig(db DatabaseWriter, hash common.Hash, cfg *params.ChainConfig) {
+func WriteChainConfig(db ethdb.Writer, hash common.Hash, cfg *params.ChainConfig) {
if cfg == nil {
return
}
@@ -80,13 +81,13 @@ func WriteChainConfig(db DatabaseWriter, hash common.Hash, cfg *params.ChainConf
}
// ReadPreimage retrieves a single preimage of the provided hash.
-func ReadPreimage(db DatabaseReader, hash common.Hash) []byte {
+func ReadPreimage(db ethdb.Reader, hash common.Hash) []byte {
data, _ := db.Get(preimageKey(hash))
return data
}
// WritePreimages writes the provided set of preimages to the database.
-func WritePreimages(db DatabaseWriter, preimages map[common.Hash][]byte) {
+func WritePreimages(db ethdb.Writer, preimages map[common.Hash][]byte) {
for hash, preimage := range preimages {
if err := db.Put(preimageKey(hash), preimage); err != nil {
log.Crit("Failed to store trie preimage", "err", err)
diff --git a/core/rawdb/database.go b/core/rawdb/database.go
new file mode 100644
index 0000000000..b4c5dea708
--- /dev/null
+++ b/core/rawdb/database.go
@@ -0,0 +1,52 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package rawdb
+
+import (
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/ethdb/leveldb"
+ "github.com/ethereum/go-ethereum/ethdb/memorydb"
+)
+
+// NewDatabase creates a high level database on top of a given key-value data
+// store without a freezer moving immutable chain segments into cold storage.
+func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
+ return db
+}
+
+// NewMemoryDatabase creates an ephemeral in-memory key-value database without a
+// freezer moving immutable chain segments into cold storage.
+func NewMemoryDatabase() ethdb.Database {
+ return NewDatabase(memorydb.New())
+}
+
+// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database with
+// an initial starting capacity, but without a freezer moving immutable chain
+// segments into cold storage.
+func NewMemoryDatabaseWithCap(size int) ethdb.Database {
+ return NewDatabase(memorydb.NewWithCap(size))
+}
+
+// NewLevelDBDatabase creates a persistent key-value database without a freezer
+// moving immutable chain segments into cold storage.
+func NewLevelDBDatabase(file string, cache int, handles int, namespace string) (ethdb.Database, error) {
+ db, err := leveldb.New(file, cache, handles, namespace)
+ if err != nil {
+ return nil, err
+ }
+ return NewDatabase(db), nil
+}
diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go
index 3bb86e7ffb..87dbf94fc0 100644
--- a/core/rawdb/schema.go
+++ b/core/rawdb/schema.go
@@ -78,6 +78,11 @@ func encodeBlockNumber(number uint64) []byte {
return enc
}
+// headerKeyPrefix = headerPrefix + num (uint64 big endian)
+func headerKeyPrefix(number uint64) []byte {
+ return append(headerPrefix, encodeBlockNumber(number)...)
+}
+
// headerKey = headerPrefix + num (uint64 big endian) + hash
func headerKey(number uint64, hash common.Hash) []byte {
return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
diff --git a/core/rawdb/table.go b/core/rawdb/table.go
new file mode 100644
index 0000000000..974df681bd
--- /dev/null
+++ b/core/rawdb/table.go
@@ -0,0 +1,150 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package rawdb
+
+import (
+ "github.com/ethereum/go-ethereum/ethdb"
+)
+
+// table is a wrapper around a database that prefixes each key access with a pre-
+// configured string.
+type table struct {
+ db ethdb.Database
+ prefix string
+}
+
+// NewTable returns a database object that prefixes all keys with a given string.
+func NewTable(db ethdb.Database, prefix string) ethdb.Database {
+ return &table{
+ db: db,
+ prefix: prefix,
+ }
+}
+
+// Close is a noop to implement the Database interface.
+func (t *table) Close() error {
+ return nil
+}
+
+// Has retrieves if a prefixed version of a key is present in the database.
+func (t *table) Has(key []byte) (bool, error) {
+ return t.db.Has(append([]byte(t.prefix), key...))
+}
+
+// Get retrieves the given prefixed key if it's present in the database.
+func (t *table) Get(key []byte) ([]byte, error) {
+ return t.db.Get(append([]byte(t.prefix), key...))
+}
+
+// Put inserts the given value into the database at a prefixed version of the
+// provided key.
+func (t *table) Put(key []byte, value []byte) error {
+ return t.db.Put(append([]byte(t.prefix), key...), value)
+}
+
+// Delete removes the given prefixed key from the database.
+func (t *table) Delete(key []byte) error {
+ return t.db.Delete(append([]byte(t.prefix), key...))
+}
+
+// NewIterator creates a binary-alphabetical iterator over the entire keyspace
+// contained within the database.
+func (t *table) NewIterator() ethdb.Iterator {
+ return t.NewIteratorWithPrefix(nil)
+}
+
+// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset
+// of database content with a particular key prefix.
+func (t *table) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator {
+ return t.db.NewIteratorWithPrefix(append([]byte(t.prefix), prefix...))
+}
+
+// Stat returns a particular internal stat of the database.
+func (t *table) Stat(property string) (string, error) {
+ return t.db.Stat(property)
+}
+
+// Compact flattens the underlying data store for the given key range. In essence,
+// deleted and overwritten versions are discarded, and the data is rearranged to
+// reduce the cost of operations needed to access them.
+//
+// A nil start is treated as a key before all keys in the data store; a nil limit
+// is treated as a key after all keys in the data store. If both is nil then it
+// will compact entire data store.
+func (t *table) Compact(start []byte, limit []byte) error {
+ // If no start was specified, use the table prefix as the first value
+ if start == nil {
+ start = []byte(t.prefix)
+ }
+ // If no limit was specified, use the first element not matching the prefix
+ // as the limit
+ if limit == nil {
+ limit = []byte(t.prefix)
+ for i := len(limit) - 1; i >= 0; i-- {
+ // Bump the current character, stopping if it doesn't overflow
+ limit[i]++
+ if limit[i] > 0 {
+ break
+ }
+ // Character overflown, proceed to the next or nil if the last
+ if i == 0 {
+ limit = nil
+ }
+ }
+ }
+ // Range correctly calculated based on table prefix, delegate down
+ return t.db.Compact(start, limit)
+}
+
+// NewBatch creates a write-only database that buffers changes to its host db
+// until a final write is called, each operation prefixing all keys with the
+// pre-configured string.
+func (t *table) NewBatch() ethdb.Batch {
+ return &tableBatch{t.db.NewBatch(), t.prefix}
+}
+
+// tableBatch is a wrapper around a database batch that prefixes each key access
+// with a pre-configured string.
+type tableBatch struct {
+ batch ethdb.Batch
+ prefix string
+}
+
+// Put inserts the given value into the batch for later committing.
+func (b *tableBatch) Put(key, value []byte) error {
+ return b.batch.Put(append([]byte(b.prefix), key...), value)
+}
+
+// Delete inserts the a key removal into the batch for later committing.
+func (b *tableBatch) Delete(key []byte) error {
+ return b.batch.Delete(append([]byte(b.prefix), key...))
+}
+
+// ValueSize retrieves the amount of data queued up for writing.
+func (b *tableBatch) ValueSize() int {
+ return b.batch.ValueSize()
+}
+
+// Write flushes any accumulated data to disk.
+func (b *tableBatch) Write() error {
+ return b.batch.Write()
+}
+
+// Reset resets the batch for reuse.
+func (b *tableBatch) Reset() {
+ b.batch.Reset()
+}
diff --git a/core/state/database.go b/core/state/database.go
index f6ea144b9b..8798b73806 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -18,7 +18,6 @@ package state
import (
"fmt"
- "sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
@@ -26,14 +25,7 @@ import (
lru "github.com/hashicorp/golang-lru"
)
-// Trie cache generation limit after which to evict trie nodes from memory.
-var MaxTrieCacheGen = uint16(120)
-
const (
- // Number of past tries to keep. This value is chosen such that
- // reasonable chain reorg depths will hit an existing trie.
- maxPastTries = 12
-
// Number of codehash->size associations to keep.
codeSizeCacheSize = 100000
)
@@ -59,28 +51,61 @@ type Database interface {
TrieDB() *trie.Database
}
-// Trie is a Ethereum Merkle Trie.
+// Trie is a Ethereum Merkle Patricia trie.
type Trie interface {
+ // GetKey returns the sha3 preimage of a hashed key that was previously used
+ // to store a value.
+ //
+ // TODO(fjl): remove this when SecureTrie is removed
+ GetKey([]byte) []byte
+
+ // TryGet returns the value for key stored in the trie. The value bytes must
+ // not be modified by the caller. If a node was not found in the database, a
+ // trie.MissingNodeError is returned.
TryGet(key []byte) ([]byte, error)
+
+ // TryUpdate associates key with value in the trie. If value has length zero, any
+ // existing value is deleted from the trie. The value bytes must not be modified
+ // by the caller while they are stored in the trie. If a node was not found in the
+ // database, a trie.MissingNodeError is returned.
TryUpdate(key, value []byte) error
+
+ // TryDelete removes any existing value for key from the trie. If a node was not
+ // found in the database, a trie.MissingNodeError is returned.
TryDelete(key []byte) error
- Commit(onleaf trie.LeafCallback) (common.Hash, error)
+
+ // Hash returns the root hash of the trie. It does not write to the database and
+ // can be used even if the trie doesn't have one.
Hash() common.Hash
+
+ // Commit writes all nodes to the trie's memory database, tracking the internal
+ // and external (for account tries) references.
+ Commit(onleaf trie.LeafCallback) (common.Hash, error)
+
+ // NodeIterator returns an iterator that returns nodes of the trie. Iteration
+ // starts at the key after the given start key.
NodeIterator(startKey []byte) trie.NodeIterator
- GetKey([]byte) []byte // TODO(fjl): remove this when SecureTrie is removed
- Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error
+
+ // Prove constructs a Merkle proof for key. The result contains all encoded nodes
+ // on the path to the value at key. The value itself is also included in the last
+ // node and can be retrieved by verifying the proof.
+ //
+ // If the trie does not contain a value for key, the returned proof contains all
+ // nodes of the longest existing prefix of the key (at least the root), ending
+ // with the node that proves the absence of the key.
+ Prove(key []byte, fromLevel uint, proofDb ethdb.Writer) error
}
// NewDatabase creates a backing store for state. The returned database is safe for
-// concurrent use and retains a few recent expanded trie nodes in memory. To keep
-// more historical state in memory, use the NewDatabaseWithCache constructor.
+// concurrent use, but does not retain any recent trie nodes in memory. To keep some
+// historical state in memory, use the NewDatabaseWithCache constructor.
func NewDatabase(db ethdb.Database) Database {
return NewDatabaseWithCache(db, 0)
}
-// NewDatabase creates a backing store for state. The returned database is safe for
-// concurrent use and retains both a few recent expanded trie nodes in memory, as
-// well as a lot of collapsed RLP trie nodes in a large memory cache.
+// NewDatabaseWithCache creates a backing store for state. The returned database
+// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
+// large memory cache.
func NewDatabaseWithCache(db ethdb.Database, cache int) Database {
csc, _ := lru.New(codeSizeCacheSize)
return &cachingDB{
@@ -91,50 +116,22 @@ func NewDatabaseWithCache(db ethdb.Database, cache int) Database {
type cachingDB struct {
db *trie.Database
- mu sync.Mutex
- pastTries []*trie.SecureTrie
codeSizeCache *lru.Cache
}
-// OpenTrie opens the main account trie.
+// OpenTrie opens the main account trie at a specific root hash.
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
- db.mu.Lock()
- defer db.mu.Unlock()
-
- for i := len(db.pastTries) - 1; i >= 0; i-- {
- if db.pastTries[i].Hash() == root {
- return cachedTrie{db.pastTries[i].Copy(), db}, nil
- }
- }
- tr, err := trie.NewSecure(root, db.db, MaxTrieCacheGen)
- if err != nil {
- return nil, err
- }
- return cachedTrie{tr, db}, nil
-}
-
-func (db *cachingDB) pushTrie(t *trie.SecureTrie) {
- db.mu.Lock()
- defer db.mu.Unlock()
-
- if len(db.pastTries) >= maxPastTries {
- copy(db.pastTries, db.pastTries[1:])
- db.pastTries[len(db.pastTries)-1] = t
- } else {
- db.pastTries = append(db.pastTries, t)
- }
+ return trie.NewSecure(root, db.db)
}
// OpenStorageTrie opens the storage trie of an account.
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
- return trie.NewSecure(root, db.db, 0)
+ return trie.NewSecure(root, db.db)
}
// CopyTrie returns an independent copy of the given trie.
func (db *cachingDB) CopyTrie(t Trie) Trie {
switch t := t.(type) {
- case cachedTrie:
- return cachedTrie{t.SecureTrie.Copy(), db}
case *trie.SecureTrie:
return t.Copy()
default:
@@ -164,21 +161,3 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro
func (db *cachingDB) TrieDB() *trie.Database {
return db.db
}
-
-// cachedTrie inserts its trie into a cachingDB on commit.
-type cachedTrie struct {
- *trie.SecureTrie
- db *cachingDB
-}
-
-func (m cachedTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
- root, err := m.SecureTrie.Commit(onleaf)
- if err == nil {
- m.db.pushTrie(m.SecureTrie)
- }
- return root, err
-}
-
-func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
- return m.SecureTrie.Prove(key, fromLevel, proofDb)
-}
diff --git a/core/state/iterator_test.go b/core/state/iterator_test.go
index 9e46c851cd..69f51c4c7d 100644
--- a/core/state/iterator_test.go
+++ b/core/state/iterator_test.go
@@ -51,7 +51,9 @@ func TestNodeIteratorCoverage(t *testing.T) {
t.Errorf("state entry not reported %x", hash)
}
}
- for _, key := range db.TrieDB().DiskDB().(*ethdb.MemDatabase).Keys() {
+ it := db.TrieDB().DiskDB().(ethdb.Database).NewIterator()
+ for it.Next() {
+ key := it.Key()
if bytes.HasPrefix(key, []byte("secure-key-")) {
continue
}
@@ -59,4 +61,5 @@ func TestNodeIteratorCoverage(t *testing.T) {
t.Errorf("state entry not reported %x", key)
}
}
+ it.Release()
}
diff --git a/core/state/managed_state_test.go b/core/state/managed_state_test.go
index 3d9c4e8676..fdfde96adf 100644
--- a/core/state/managed_state_test.go
+++ b/core/state/managed_state_test.go
@@ -20,13 +20,13 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/core/rawdb"
)
var addr = common.BytesToAddress([]byte("test"))
func create() (*ManagedState, *account) {
- statedb, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
ms := ManageState(statedb)
ms.StateDB.SetNonce(addr, 100)
ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr))
diff --git a/core/state/state_test.go b/core/state/state_test.go
index a09273f3b1..606f2a6f6e 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -22,13 +22,14 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
checker "gopkg.in/check.v1"
)
type StateSuite struct {
- db *ethdb.MemDatabase
+ db ethdb.Database
state *StateDB
}
@@ -87,7 +88,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
}
func (s *StateSuite) SetUpTest(c *checker.C) {
- s.db = ethdb.NewMemDatabase()
+ s.db = rawdb.NewMemoryDatabase()
s.state, _ = New(common.Hash{}, NewDatabase(s.db))
}
@@ -141,7 +142,7 @@ func (s *StateSuite) TestSnapshotEmpty(c *checker.C) {
// use testing instead of checker because checker does not support
// printing/logging in tests (-check.vv does not work)
func TestSnapshot2(t *testing.T) {
- state, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()))
+ state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
stateobjaddr0 := toAddr([]byte("so0"))
stateobjaddr1 := toAddr([]byte("so1"))
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 8ad25a5824..4c00092f4e 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -37,8 +37,8 @@ type revision struct {
}
var (
- // emptyState is the known hash of an empty state trie entry.
- emptyState = crypto.Keccak256Hash(nil)
+ // emptyRoot is the known root hash of an empty trie.
+ emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256Hash(nil)
@@ -653,7 +653,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
if err := rlp.DecodeBytes(leaf, &account); err != nil {
return nil
}
- if account.Root != emptyState {
+ if account.Root != emptyRoot {
s.db.TrieDB().Reference(account.Root, parent)
}
code := common.BytesToHash(account.CodeHash)
@@ -662,6 +662,5 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
}
return nil
})
- log.Debug("Trie cache stats after commit", "misses", trie.CacheMisses(), "unloads", trie.CacheUnloads())
return root, err
}
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index 69392d972e..c2d2b2f692 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -31,15 +31,15 @@ import (
check "gopkg.in/check.v1"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/ethdb"
)
// Tests that updating a state trie does not leak any database writes prior to
// actually committing the state.
func TestUpdateLeaks(t *testing.T) {
// Create an empty state database
- db := ethdb.NewMemDatabase()
+ db := rawdb.NewMemoryDatabase()
state, _ := New(common.Hash{}, NewDatabase(db))
// Update it with some accounts
@@ -56,18 +56,19 @@ func TestUpdateLeaks(t *testing.T) {
state.IntermediateRoot(false)
}
// Ensure that no data was leaked into the database
- for _, key := range db.Keys() {
- value, _ := db.Get(key)
- t.Errorf("State leaked into database: %x -> %x", key, value)
+ it := db.NewIterator()
+ for it.Next() {
+ t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value())
}
+ it.Release()
}
// Tests that no intermediate state of an object is stored into the database,
// only the one right before the commit.
func TestIntermediateLeaks(t *testing.T) {
// Create two state databases, one transitioning to the final state, the other final from the beginning
- transDb := ethdb.NewMemDatabase()
- finalDb := ethdb.NewMemDatabase()
+ transDb := rawdb.NewMemoryDatabase()
+ finalDb := rawdb.NewMemoryDatabase()
transState, _ := New(common.Hash{}, NewDatabase(transDb))
finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
@@ -103,16 +104,20 @@ func TestIntermediateLeaks(t *testing.T) {
if _, err := finalState.Commit(false); err != nil {
t.Fatalf("failed to commit final state: %v", err)
}
- for _, key := range finalDb.Keys() {
+ it := finalDb.NewIterator()
+ for it.Next() {
+ key := it.Key()
if _, err := transDb.Get(key); err != nil {
- val, _ := finalDb.Get(key)
- t.Errorf("entry missing from the transition database: %x -> %x", key, val)
+ t.Errorf("entry missing from the transition database: %x -> %x", key, it.Value())
}
}
- for _, key := range transDb.Keys() {
+ it.Release()
+
+ it = transDb.NewIterator()
+ for it.Next() {
+ key := it.Key()
if _, err := finalDb.Get(key); err != nil {
- val, _ := transDb.Get(key)
- t.Errorf("extra entry in the transition database: %x -> %x", key, val)
+ t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value())
}
}
}
@@ -122,7 +127,7 @@ func TestIntermediateLeaks(t *testing.T) {
// https://github.com/ethereum/go-ethereum/pull/15549.
func TestCopy(t *testing.T) {
// Create a random state test to copy and modify "independently"
- orig, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()))
+ orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
for i := byte(0); i < 255; i++ {
obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
@@ -342,7 +347,7 @@ func (test *snapshotTest) String() string {
func (test *snapshotTest) run() bool {
// Run all actions and create snapshots.
var (
- state, _ = New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()))
+ state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
snapshotRevs = make([]int, len(test.snapshots))
sindex = 0
)
@@ -433,7 +438,7 @@ func (s *StateSuite) TestTouchDelete(c *check.C) {
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
func TestCopyOfCopy(t *testing.T) {
- sdb, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()))
+ sdb, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
addr := common.HexToAddress("aaaa")
sdb.SetBalance(addr, big.NewInt(42))
diff --git a/core/state/sync.go b/core/state/sync.go
index c566e79073..5290411a3b 100644
--- a/core/state/sync.go
+++ b/core/state/sync.go
@@ -20,12 +20,13 @@ import (
"bytes"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
// NewStateSync create a new state trie download scheduler.
-func NewStateSync(root common.Hash, database trie.DatabaseReader) *trie.Sync {
+func NewStateSync(root common.Hash, database ethdb.Reader) *trie.Sync {
var syncer *trie.Sync
callback := func(leaf []byte, parent common.Hash) error {
var obj Account
diff --git a/core/state/sync_test.go b/core/state/sync_test.go
index 3177401608..ab4718b04c 100644
--- a/core/state/sync_test.go
+++ b/core/state/sync_test.go
@@ -22,6 +22,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
@@ -38,7 +39,7 @@ type testAccount struct {
// makeTestState create a sample test state to test node-wise reconstruction.
func makeTestState() (Database, common.Hash, []*testAccount) {
// Create an empty state
- db := NewDatabase(ethdb.NewMemDatabase())
+ db := NewDatabase(rawdb.NewMemoryDatabase())
state, _ := New(common.Hash{}, db)
// Fill it with some arbitrary data
@@ -124,7 +125,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
// Tests that an empty state is not scheduled for syncing.
func TestEmptyStateSync(t *testing.T) {
empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
- if req := NewStateSync(empty, ethdb.NewMemDatabase()).Missing(1); len(req) != 0 {
+ if req := NewStateSync(empty, rawdb.NewMemoryDatabase()).Missing(1); len(req) != 0 {
t.Errorf("content requested for empty state: %v", req)
}
}
@@ -139,7 +140,7 @@ func testIterativeStateSync(t *testing.T, batch int) {
srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
- dstDb := ethdb.NewMemDatabase()
+ dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb)
queue := append([]common.Hash{}, sched.Missing(batch)...)
@@ -171,7 +172,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
- dstDb := ethdb.NewMemDatabase()
+ dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb)
queue := append([]common.Hash{}, sched.Missing(0)...)
@@ -208,7 +209,7 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
- dstDb := ethdb.NewMemDatabase()
+ dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb)
queue := make(map[common.Hash]struct{})
@@ -248,7 +249,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
- dstDb := ethdb.NewMemDatabase()
+ dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb)
queue := make(map[common.Hash]struct{})
@@ -295,7 +296,7 @@ func TestIncompleteStateSync(t *testing.T) {
checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot)
// Create a destination state and sync with the scheduler
- dstDb := ethdb.NewMemDatabase()
+ dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb)
added := []common.Hash{}
diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go
index e1c2e06696..50c73cf535 100644
--- a/core/tx_pool_test.go
+++ b/core/tx_pool_test.go
@@ -27,10 +27,10 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
)
@@ -78,7 +78,7 @@ func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ec
}
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
key, _ := crypto.GenerateKey()
@@ -163,7 +163,7 @@ func (c *testChain) State() (*state.StateDB, error) {
// a state change between those fetches.
stdb := c.statedb
if *c.trigger {
- c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
// simulate that the new head block included tx0 and tx1
c.statedb.SetNonce(c.address, 2)
c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether))
@@ -181,7 +181,7 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
var (
key, _ = crypto.GenerateKey()
address = crypto.PubkeyToAddress(key.PublicKey)
- statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
trigger = false
)
@@ -335,7 +335,7 @@ func TestTransactionChainFork(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
@@ -364,7 +364,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
@@ -554,7 +554,7 @@ func TestTransactionPostponing(t *testing.T) {
t.Parallel()
// Create the pool to test the postponing with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@@ -769,7 +769,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
t.Parallel()
// Create the pool to test the limit enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -857,7 +857,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
evictionInterval = time.Second
// Create the pool to test the non-expiration enforcement
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1011,7 +1011,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
t.Parallel()
// Create the pool to test the limit enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1057,7 +1057,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
t.Parallel()
// Create the pool to test the limit enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1091,7 +1091,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
t.Parallel()
// Create the pool to test the limit enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1139,7 +1139,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
t.Parallel()
// Create the pool to test the pricing enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@@ -1260,7 +1260,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
t.Parallel()
// Create the pool to test the pricing enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@@ -1322,7 +1322,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Parallel()
// Create the pool to test the pricing enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1428,7 +1428,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
t.Parallel()
// Create the pool to test the pricing enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1494,7 +1494,7 @@ func TestTransactionReplacement(t *testing.T) {
t.Parallel()
// Create the pool to test the pricing enforcement with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@@ -1588,7 +1588,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
os.Remove(journal)
// Create the original pool to inject transaction into the journal
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
@@ -1686,7 +1686,7 @@ func TestTransactionStatusCheck(t *testing.T) {
t.Parallel()
// Create the pool to test the status retrievals with
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
diff --git a/core/types.go b/core/types.go
index d0bbaf0aa7..5c963e6652 100644
--- a/core/types.go
+++ b/core/types.go
@@ -32,7 +32,7 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and
// gas used.
- ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
+ ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
}
// Processor is an interface for processing blocks using a given initial state.
diff --git a/core/vm/common.go b/core/vm/common.go
index 17de38decb..d592a9410d 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -23,13 +23,31 @@ import (
"github.com/ethereum/go-ethereum/common/math"
)
-// calculates the memory size required for a step
-func calcMemSize(off, l *big.Int) *big.Int {
- if l.Sign() == 0 {
- return common.Big0
+// calcMemSize64 calculates the required memory size, and returns
+// the size and whether the result overflowed uint64
+func calcMemSize64(off, l *big.Int) (uint64, bool) {
+ if !l.IsUint64() {
+ return 0, true
}
+ return calcMemSize64WithUint(off, l.Uint64())
+}
- return new(big.Int).Add(off, l)
+// calcMemSize64WithUint calculates the required memory size, and returns
+// the size and whether the result overflowed uint64
+// Identical to calcMemSize64, but length is a uint64
+func calcMemSize64WithUint(off *big.Int, length64 uint64) (uint64, bool) {
+ // if length is zero, memsize is always zero, regardless of offset
+ if length64 == 0 {
+ return 0, false
+ }
+ // Check that offset doesn't overflow
+ if !off.IsUint64() {
+ return 0, true
+ }
+ offset64 := off.Uint64()
+ val := offset64 + length64
+ // if value < either of it's parts, then it overflowed
+ return val, val < offset64
}
// getData returns a slice from the data based on the start and size and pads
@@ -59,7 +77,7 @@ func getDataBig(data []byte, start *big.Int, size *big.Int) []byte {
// bigUint64 returns the integer casted to a uint64 and returns whether it
// overflowed in the process.
func bigUint64(v *big.Int) (uint64, bool) {
- return v.Uint64(), v.BitLen() > 64
+ return v.Uint64(), !v.IsUint64()
}
// toWordSize returns the ceiled word size required for memory expansion.
diff --git a/core/vm/gas.go b/core/vm/gas.go
index dba1b3a02f..022a84f243 100644
--- a/core/vm/gas.go
+++ b/core/vm/gas.go
@@ -43,11 +43,11 @@ func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.
// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
// is smaller than the requested amount. Therefor we return the new gas instead
// of returning an error.
- if callCost.BitLen() > 64 || gas < callCost.Uint64() {
+ if !callCost.IsUint64() || gas < callCost.Uint64() {
return gas, nil
}
}
- if callCost.BitLen() > 64 {
+ if !callCost.IsUint64() {
return 0, errGasUintOverflow
}
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index f22463c331..6400c1324f 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -57,12 +57,6 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
return 0, nil
}
-func constGasFunc(gas uint64) gasFunc {
- return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return gas, nil
- }
-}
-
func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -521,15 +515,3 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac
}
return gas, nil
}
-
-func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return GasFastestStep, nil
-}
-
-func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return GasFastestStep, nil
-}
-
-func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return GasFastestStep, nil
-}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 5195e716b2..2a062d7e77 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -18,7 +18,6 @@ package vm
import (
"errors"
- "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -35,6 +34,7 @@ var (
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
errExecutionReverted = errors.New("evm: execution reverted")
errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded")
+ errInvalidJump = errors.New("evm: invalid jump destination")
)
func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
@@ -405,7 +405,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
}
func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Address().Big())
+ stack.push(interpreter.intPool.get().SetBytes(contract.Address().Bytes()))
return nil, nil
}
@@ -416,12 +416,12 @@ func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
}
func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.evm.Origin.Big())
+ stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Origin.Bytes()))
return nil, nil
}
func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Caller().Big())
+ stack.push(interpreter.intPool.get().SetBytes(contract.Caller().Bytes()))
return nil, nil
}
@@ -467,7 +467,7 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contrac
)
defer interpreter.intPool.put(memOffset, dataOffset, length, end)
- if end.BitLen() > 64 || uint64(len(interpreter.returnData)) < end.Uint64() {
+ if !end.IsUint64() || uint64(len(interpreter.returnData)) < end.Uint64() {
return nil, errReturnDataOutOfBounds
}
memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[dataOffset.Uint64():end.Uint64()])
@@ -572,7 +572,7 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, me
}
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.evm.Coinbase.Big())
+ stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Coinbase.Bytes()))
return nil, nil
}
@@ -645,8 +645,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
pos := stack.pop()
if !contract.validJumpdest(pos) {
- nop := contract.GetOp(pos.Uint64())
- return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
+ return nil, errInvalidJump
}
*pc = pos.Uint64()
@@ -658,8 +657,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
pos, cond := stack.pop(), stack.pop()
if cond.Sign() != 0 {
if !contract.validJumpdest(pos) {
- nop := contract.GetOp(pos.Uint64())
- return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
+ return nil, errInvalidJump
}
*pc = pos.Uint64()
} else {
@@ -711,7 +709,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
stack.push(interpreter.intPool.getZero())
} else {
- stack.push(addr.Big())
+ stack.push(interpreter.intPool.get().SetBytes(addr.Bytes()))
}
contract.Gas += returnGas
interpreter.intPool.put(value, offset, size)
@@ -739,7 +737,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
if suberr != nil {
stack.push(interpreter.intPool.getZero())
} else {
- stack.push(addr.Big())
+ stack.push(interpreter.intPool.get().SetBytes(addr.Bytes()))
}
contract.Gas += returnGas
interpreter.intPool.put(endowment, offset, size, salt)
@@ -912,6 +910,21 @@ func makeLog(size int) executionFunc {
}
}
+// opPush1 is a specialized version of pushN
+func opPush1(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ var (
+ codeLen = uint64(len(contract.Code))
+ integer = interpreter.intPool.get()
+ )
+ *pc += 1
+ if *pc < codeLen {
+ stack.push(integer.SetUint64(uint64(contract.Code[*pc])))
+ } else {
+ stack.push(integer.SetUint64(0))
+ }
+ return nil, nil
+}
+
// make push instruction function
func makePush(size uint64, pushByteSize int) executionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index c9dc3c00c6..4176653700 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -118,22 +118,6 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
}
}
-func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
- if in.evm.chainRules.IsByzantium {
- if in.readOnly {
- // If the interpreter is operating in readonly mode, make sure no
- // state-modifying operation is performed. The 3rd stack item
- // for a call operation is the value. Transferring value from one
- // account to the others means the state is modified and should also
- // return with an error.
- if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) {
- return errWriteProtection
- }
- }
- }
- return nil
-}
-
// Run loops and evaluates the contract's code with the given input data and returns
// the return byte-slice and an error if one occurred.
//
@@ -217,19 +201,35 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
if !operation.valid {
return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
}
- if err = operation.validateStack(stack); err != nil {
- return nil, err
+ // Validate stack
+ if sLen := stack.len(); sLen < operation.minStack {
+ return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack)
+ } else if sLen > operation.maxStack {
+ return nil, fmt.Errorf("stack limit reached %d (%d)", sLen, operation.maxStack)
}
// If the operation is valid, enforce and write restrictions
- if err = in.enforceRestrictions(op, operation, stack); err != nil {
- return nil, err
+ if in.readOnly && in.evm.chainRules.IsByzantium {
+ // If the interpreter is operating in readonly mode, make sure no
+ // state-modifying operation is performed. The 3rd stack item
+ // for a call operation is the value. Transferring value from one
+ // account to the others means the state is modified and should also
+ // return with an error.
+ if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) {
+ return nil, errWriteProtection
+ }
+ }
+ // Static portion of gas
+ if !contract.UseGas(operation.constantGas) {
+ return nil, ErrOutOfGas
}
var memorySize uint64
// calculate the new memory size and expand the memory to fit
// the operation
+ // Memory check needs to be done prior to evaluating the dynamic gas portion,
+ // to detect calculation overflows
if operation.memorySize != nil {
- memSize, overflow := bigUint64(operation.memorySize(stack))
+ memSize, overflow := operation.memorySize(stack)
if overflow {
return nil, errGasUintOverflow
}
@@ -239,11 +239,14 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
return nil, errGasUintOverflow
}
}
+ // Dynamic portion of gas
// consume the gas and return an error if not enough gas is available.
// 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
+ if operation.dynamicGas != nil {
+ cost, err = operation.dynamicGas(in.gasTable, in.evm, contract, stack, mem, memorySize)
+ if err != nil || !contract.UseGas(cost) {
+ return nil, ErrOutOfGas
+ }
}
if memorySize > 0 {
mem.Resize(memorySize)
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index deedf70cdb..425436f9e5 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -18,27 +18,30 @@ package vm
import (
"errors"
- "math/big"
"github.com/ethereum/go-ethereum/params"
)
type (
- executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
- gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
- stackValidationFunc func(*Stack) error
- memorySizeFunc func(*Stack) *big.Int
+ executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
+ gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
+ // memorySizeFunc returns the required size, and whether the operation overflowed a uint64
+ memorySizeFunc func(*Stack) (size uint64, overflow bool)
)
var errGasUintOverflow = errors.New("gas uint64 overflow")
type operation struct {
// execute is the operation function
- execute executionFunc
- // gasCost is the gas function and returns the gas required for execution
- gasCost gasFunc
- // validateStack validates the stack (size) for the operation
- validateStack stackValidationFunc
+ execute executionFunc
+ constantGas uint64
+ dynamicGas gasFunc
+ // minStack tells how many stack items are required
+ minStack int
+ // maxStack specifies the max length the stack can have for this operation
+ // to not overflow the stack.
+ maxStack int
+
// memorySize returns the memory size required for the operation
memorySize memorySizeFunc
@@ -63,37 +66,42 @@ func newConstantinopleInstructionSet() [256]operation {
// instructions that can be executed during the byzantium phase.
instructionSet := newByzantiumInstructionSet()
instructionSet[SHL] = operation{
- execute: opSHL,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSHL,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
}
instructionSet[SHR] = operation{
- execute: opSHR,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSHR,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
}
instructionSet[SAR] = operation{
- execute: opSAR,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSAR,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
}
instructionSet[EXTCODEHASH] = operation{
- execute: opExtCodeHash,
- gasCost: gasExtCodeHash,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opExtCodeHash,
+ dynamicGas: gasExtCodeHash,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
}
instructionSet[CREATE2] = operation{
- execute: opCreate2,
- gasCost: gasCreate2,
- validateStack: makeStackFunc(4, 1),
- memorySize: memoryCreate2,
- valid: true,
- writes: true,
- returns: true,
+ execute: opCreate2,
+ dynamicGas: gasCreate2,
+ minStack: minStack(4, 1),
+ maxStack: maxStack(4, 1),
+ memorySize: memoryCreate2,
+ valid: true,
+ writes: true,
+ returns: true,
}
return instructionSet
}
@@ -104,34 +112,38 @@ func newByzantiumInstructionSet() [256]operation {
// instructions that can be executed during the homestead phase.
instructionSet := newHomesteadInstructionSet()
instructionSet[STATICCALL] = operation{
- execute: opStaticCall,
- gasCost: gasStaticCall,
- validateStack: makeStackFunc(6, 1),
- memorySize: memoryStaticCall,
- valid: true,
- returns: true,
+ execute: opStaticCall,
+ dynamicGas: gasStaticCall,
+ minStack: minStack(6, 1),
+ maxStack: maxStack(6, 1),
+ memorySize: memoryStaticCall,
+ valid: true,
+ returns: true,
}
instructionSet[RETURNDATASIZE] = operation{
- execute: opReturnDataSize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opReturnDataSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
}
instructionSet[RETURNDATACOPY] = operation{
- execute: opReturnDataCopy,
- gasCost: gasReturnDataCopy,
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryReturnDataCopy,
- valid: true,
+ execute: opReturnDataCopy,
+ dynamicGas: gasReturnDataCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryReturnDataCopy,
+ valid: true,
}
instructionSet[REVERT] = operation{
- execute: opRevert,
- gasCost: gasRevert,
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryRevert,
- valid: true,
- reverts: true,
- returns: true,
+ execute: opRevert,
+ dynamicGas: gasRevert,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryRevert,
+ valid: true,
+ reverts: true,
+ returns: true,
}
return instructionSet
}
@@ -141,12 +153,13 @@ func newByzantiumInstructionSet() [256]operation {
func newHomesteadInstructionSet() [256]operation {
instructionSet := newFrontierInstructionSet()
instructionSet[DELEGATECALL] = operation{
- execute: opDelegateCall,
- gasCost: gasDelegateCall,
- validateStack: makeStackFunc(6, 1),
- memorySize: memoryDelegateCall,
- valid: true,
- returns: true,
+ execute: opDelegateCall,
+ dynamicGas: gasDelegateCall,
+ minStack: minStack(6, 1),
+ maxStack: maxStack(6, 1),
+ memorySize: memoryDelegateCall,
+ valid: true,
+ returns: true,
}
return instructionSet
}
@@ -156,811 +169,940 @@ func newHomesteadInstructionSet() [256]operation {
func newFrontierInstructionSet() [256]operation {
return [256]operation{
STOP: {
- execute: opStop,
- gasCost: constGasFunc(0),
- validateStack: makeStackFunc(0, 0),
- halts: true,
- valid: true,
+ execute: opStop,
+ constantGas: 0,
+ minStack: minStack(0, 0),
+ maxStack: maxStack(0, 0),
+ halts: true,
+ valid: true,
},
ADD: {
- execute: opAdd,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opAdd,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
MUL: {
- execute: opMul,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opMul,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SUB: {
- execute: opSub,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSub,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
DIV: {
- execute: opDiv,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opDiv,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SDIV: {
- execute: opSdiv,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSdiv,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
MOD: {
- execute: opMod,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opMod,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SMOD: {
- execute: opSmod,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSmod,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
ADDMOD: {
- execute: opAddmod,
- gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(3, 1),
- valid: true,
+ execute: opAddmod,
+ constantGas: GasMidStep,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ valid: true,
},
MULMOD: {
- execute: opMulmod,
- gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(3, 1),
- valid: true,
+ execute: opMulmod,
+ constantGas: GasMidStep,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ valid: true,
},
EXP: {
- execute: opExp,
- gasCost: gasExp,
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opExp,
+ dynamicGas: gasExp,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SIGNEXTEND: {
- execute: opSignExtend,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSignExtend,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
LT: {
- execute: opLt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opLt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
GT: {
- execute: opGt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opGt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SLT: {
- execute: opSlt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSlt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SGT: {
- execute: opSgt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSgt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
EQ: {
- execute: opEq,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opEq,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
ISZERO: {
- execute: opIszero,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opIszero,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
AND: {
- execute: opAnd,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opAnd,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
XOR: {
- execute: opXor,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opXor,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
OR: {
- execute: opOr,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opOr,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
NOT: {
- execute: opNot,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opNot,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
BYTE: {
- execute: opByte,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opByte,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SHA3: {
- execute: opSha3,
- gasCost: gasSha3,
- validateStack: makeStackFunc(2, 1),
- memorySize: memorySha3,
- valid: true,
+ execute: opSha3,
+ dynamicGas: gasSha3,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ memorySize: memorySha3,
+ valid: true,
},
ADDRESS: {
- execute: opAddress,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opAddress,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
BALANCE: {
- execute: opBalance,
- gasCost: gasBalance,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opBalance,
+ dynamicGas: gasBalance,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
ORIGIN: {
- execute: opOrigin,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opOrigin,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLER: {
- execute: opCaller,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCaller,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLVALUE: {
- execute: opCallValue,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCallValue,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLDATALOAD: {
- execute: opCallDataLoad,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opCallDataLoad,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
CALLDATASIZE: {
- execute: opCallDataSize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCallDataSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLDATACOPY: {
- execute: opCallDataCopy,
- gasCost: gasCallDataCopy,
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryCallDataCopy,
- valid: true,
+ execute: opCallDataCopy,
+ dynamicGas: gasCallDataCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryCallDataCopy,
+ valid: true,
},
CODESIZE: {
- execute: opCodeSize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCodeSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CODECOPY: {
- execute: opCodeCopy,
- gasCost: gasCodeCopy,
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryCodeCopy,
- valid: true,
+ execute: opCodeCopy,
+ dynamicGas: gasCodeCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryCodeCopy,
+ valid: true,
},
GASPRICE: {
- execute: opGasprice,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opGasprice,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
EXTCODESIZE: {
- execute: opExtCodeSize,
- gasCost: gasExtCodeSize,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opExtCodeSize,
+ dynamicGas: gasExtCodeSize,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
EXTCODECOPY: {
- execute: opExtCodeCopy,
- gasCost: gasExtCodeCopy,
- validateStack: makeStackFunc(4, 0),
- memorySize: memoryExtCodeCopy,
- valid: true,
+ execute: opExtCodeCopy,
+ dynamicGas: gasExtCodeCopy,
+ minStack: minStack(4, 0),
+ maxStack: maxStack(4, 0),
+ memorySize: memoryExtCodeCopy,
+ valid: true,
},
BLOCKHASH: {
- execute: opBlockhash,
- gasCost: constGasFunc(GasExtStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opBlockhash,
+ constantGas: GasExtStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
COINBASE: {
- execute: opCoinbase,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCoinbase,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
TIMESTAMP: {
- execute: opTimestamp,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opTimestamp,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
NUMBER: {
- execute: opNumber,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opNumber,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
DIFFICULTY: {
- execute: opDifficulty,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opDifficulty,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
GASLIMIT: {
- execute: opGasLimit,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opGasLimit,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
POP: {
- execute: opPop,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(1, 0),
- valid: true,
+ execute: opPop,
+ constantGas: GasQuickStep,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ valid: true,
},
MLOAD: {
- execute: opMload,
- gasCost: gasMLoad,
- validateStack: makeStackFunc(1, 1),
- memorySize: memoryMLoad,
- valid: true,
+ execute: opMload,
+ dynamicGas: gasMLoad,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ memorySize: memoryMLoad,
+ valid: true,
},
MSTORE: {
- execute: opMstore,
- gasCost: gasMStore,
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryMStore,
- valid: true,
+ execute: opMstore,
+ dynamicGas: gasMStore,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryMStore,
+ valid: true,
},
MSTORE8: {
- execute: opMstore8,
- gasCost: gasMStore8,
- memorySize: memoryMStore8,
- validateStack: makeStackFunc(2, 0),
+ execute: opMstore8,
+ dynamicGas: gasMStore8,
+ memorySize: memoryMStore8,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
valid: true,
},
SLOAD: {
- execute: opSload,
- gasCost: gasSLoad,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opSload,
+ dynamicGas: gasSLoad,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
SSTORE: {
- execute: opSstore,
- gasCost: gasSStore,
- validateStack: makeStackFunc(2, 0),
- valid: true,
- writes: true,
+ execute: opSstore,
+ dynamicGas: gasSStore,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ valid: true,
+ writes: true,
},
JUMP: {
- execute: opJump,
- gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(1, 0),
- jumps: true,
- valid: true,
+ execute: opJump,
+ constantGas: GasMidStep,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ jumps: true,
+ valid: true,
},
JUMPI: {
- execute: opJumpi,
- gasCost: constGasFunc(GasSlowStep),
- validateStack: makeStackFunc(2, 0),
- jumps: true,
- valid: true,
+ execute: opJumpi,
+ constantGas: GasSlowStep,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ jumps: true,
+ valid: true,
},
PC: {
- execute: opPc,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opPc,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
MSIZE: {
- execute: opMsize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opMsize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
GAS: {
- execute: opGas,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opGas,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
JUMPDEST: {
- execute: opJumpdest,
- gasCost: constGasFunc(params.JumpdestGas),
- validateStack: makeStackFunc(0, 0),
- valid: true,
+ execute: opJumpdest,
+ constantGas: params.JumpdestGas,
+ minStack: minStack(0, 0),
+ maxStack: maxStack(0, 0),
+ valid: true,
},
PUSH1: {
- execute: makePush(1, 1),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opPush1,
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH2: {
- execute: makePush(2, 2),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(2, 2),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH3: {
- execute: makePush(3, 3),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(3, 3),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH4: {
- execute: makePush(4, 4),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(4, 4),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH5: {
- execute: makePush(5, 5),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(5, 5),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH6: {
- execute: makePush(6, 6),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(6, 6),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH7: {
- execute: makePush(7, 7),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(7, 7),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH8: {
- execute: makePush(8, 8),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(8, 8),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH9: {
- execute: makePush(9, 9),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(9, 9),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH10: {
- execute: makePush(10, 10),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(10, 10),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH11: {
- execute: makePush(11, 11),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(11, 11),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH12: {
- execute: makePush(12, 12),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(12, 12),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH13: {
- execute: makePush(13, 13),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(13, 13),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH14: {
- execute: makePush(14, 14),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(14, 14),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH15: {
- execute: makePush(15, 15),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(15, 15),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH16: {
- execute: makePush(16, 16),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(16, 16),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH17: {
- execute: makePush(17, 17),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(17, 17),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH18: {
- execute: makePush(18, 18),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(18, 18),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH19: {
- execute: makePush(19, 19),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(19, 19),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH20: {
- execute: makePush(20, 20),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(20, 20),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH21: {
- execute: makePush(21, 21),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(21, 21),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH22: {
- execute: makePush(22, 22),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(22, 22),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH23: {
- execute: makePush(23, 23),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(23, 23),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH24: {
- execute: makePush(24, 24),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(24, 24),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH25: {
- execute: makePush(25, 25),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(25, 25),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH26: {
- execute: makePush(26, 26),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(26, 26),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH27: {
- execute: makePush(27, 27),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(27, 27),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH28: {
- execute: makePush(28, 28),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(28, 28),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH29: {
- execute: makePush(29, 29),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(29, 29),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH30: {
- execute: makePush(30, 30),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(30, 30),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH31: {
- execute: makePush(31, 31),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(31, 31),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH32: {
- execute: makePush(32, 32),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(32, 32),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
DUP1: {
- execute: makeDup(1),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(1),
- valid: true,
+ execute: makeDup(1),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(1),
+ maxStack: maxDupStack(1),
+ valid: true,
},
DUP2: {
- execute: makeDup(2),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(2),
- valid: true,
+ execute: makeDup(2),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(2),
+ maxStack: maxDupStack(2),
+ valid: true,
},
DUP3: {
- execute: makeDup(3),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(3),
- valid: true,
+ execute: makeDup(3),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(3),
+ maxStack: maxDupStack(3),
+ valid: true,
},
DUP4: {
- execute: makeDup(4),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(4),
- valid: true,
+ execute: makeDup(4),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(4),
+ maxStack: maxDupStack(4),
+ valid: true,
},
DUP5: {
- execute: makeDup(5),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(5),
- valid: true,
+ execute: makeDup(5),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(5),
+ maxStack: maxDupStack(5),
+ valid: true,
},
DUP6: {
- execute: makeDup(6),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(6),
- valid: true,
+ execute: makeDup(6),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(6),
+ maxStack: maxDupStack(6),
+ valid: true,
},
DUP7: {
- execute: makeDup(7),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(7),
- valid: true,
+ execute: makeDup(7),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(7),
+ maxStack: maxDupStack(7),
+ valid: true,
},
DUP8: {
- execute: makeDup(8),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(8),
- valid: true,
+ execute: makeDup(8),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(8),
+ maxStack: maxDupStack(8),
+ valid: true,
},
DUP9: {
- execute: makeDup(9),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(9),
- valid: true,
+ execute: makeDup(9),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(9),
+ maxStack: maxDupStack(9),
+ valid: true,
},
DUP10: {
- execute: makeDup(10),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(10),
- valid: true,
+ execute: makeDup(10),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(10),
+ maxStack: maxDupStack(10),
+ valid: true,
},
DUP11: {
- execute: makeDup(11),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(11),
- valid: true,
+ execute: makeDup(11),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(11),
+ maxStack: maxDupStack(11),
+ valid: true,
},
DUP12: {
- execute: makeDup(12),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(12),
- valid: true,
+ execute: makeDup(12),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(12),
+ maxStack: maxDupStack(12),
+ valid: true,
},
DUP13: {
- execute: makeDup(13),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(13),
- valid: true,
+ execute: makeDup(13),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(13),
+ maxStack: maxDupStack(13),
+ valid: true,
},
DUP14: {
- execute: makeDup(14),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(14),
- valid: true,
+ execute: makeDup(14),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(14),
+ maxStack: maxDupStack(14),
+ valid: true,
},
DUP15: {
- execute: makeDup(15),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(15),
- valid: true,
+ execute: makeDup(15),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(15),
+ maxStack: maxDupStack(15),
+ valid: true,
},
DUP16: {
- execute: makeDup(16),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(16),
- valid: true,
+ execute: makeDup(16),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(16),
+ maxStack: maxDupStack(16),
+ valid: true,
},
SWAP1: {
- execute: makeSwap(1),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(2),
- valid: true,
+ execute: makeSwap(1),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(2),
+ maxStack: maxSwapStack(2),
+ valid: true,
},
SWAP2: {
- execute: makeSwap(2),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(3),
- valid: true,
+ execute: makeSwap(2),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(3),
+ maxStack: maxSwapStack(3),
+ valid: true,
},
SWAP3: {
- execute: makeSwap(3),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(4),
- valid: true,
+ execute: makeSwap(3),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(4),
+ maxStack: maxSwapStack(4),
+ valid: true,
},
SWAP4: {
- execute: makeSwap(4),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(5),
- valid: true,
+ execute: makeSwap(4),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(5),
+ maxStack: maxSwapStack(5),
+ valid: true,
},
SWAP5: {
- execute: makeSwap(5),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(6),
- valid: true,
+ execute: makeSwap(5),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(6),
+ maxStack: maxSwapStack(6),
+ valid: true,
},
SWAP6: {
- execute: makeSwap(6),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(7),
- valid: true,
+ execute: makeSwap(6),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(7),
+ maxStack: maxSwapStack(7),
+ valid: true,
},
SWAP7: {
- execute: makeSwap(7),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(8),
- valid: true,
+ execute: makeSwap(7),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(8),
+ maxStack: maxSwapStack(8),
+ valid: true,
},
SWAP8: {
- execute: makeSwap(8),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(9),
- valid: true,
+ execute: makeSwap(8),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(9),
+ maxStack: maxSwapStack(9),
+ valid: true,
},
SWAP9: {
- execute: makeSwap(9),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(10),
- valid: true,
+ execute: makeSwap(9),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(10),
+ maxStack: maxSwapStack(10),
+ valid: true,
},
SWAP10: {
- execute: makeSwap(10),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(11),
- valid: true,
+ execute: makeSwap(10),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(11),
+ maxStack: maxSwapStack(11),
+ valid: true,
},
SWAP11: {
- execute: makeSwap(11),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(12),
- valid: true,
+ execute: makeSwap(11),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(12),
+ maxStack: maxSwapStack(12),
+ valid: true,
},
SWAP12: {
- execute: makeSwap(12),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(13),
- valid: true,
+ execute: makeSwap(12),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(13),
+ maxStack: maxSwapStack(13),
+ valid: true,
},
SWAP13: {
- execute: makeSwap(13),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(14),
- valid: true,
+ execute: makeSwap(13),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(14),
+ maxStack: maxSwapStack(14),
+ valid: true,
},
SWAP14: {
- execute: makeSwap(14),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(15),
- valid: true,
+ execute: makeSwap(14),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(15),
+ maxStack: maxSwapStack(15),
+ valid: true,
},
SWAP15: {
- execute: makeSwap(15),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(16),
- valid: true,
+ execute: makeSwap(15),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(16),
+ maxStack: maxSwapStack(16),
+ valid: true,
},
SWAP16: {
- execute: makeSwap(16),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(17),
- valid: true,
+ execute: makeSwap(16),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(17),
+ maxStack: maxSwapStack(17),
+ valid: true,
},
LOG0: {
- execute: makeLog(0),
- gasCost: makeGasLog(0),
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(0),
+ dynamicGas: makeGasLog(0),
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG1: {
- execute: makeLog(1),
- gasCost: makeGasLog(1),
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(1),
+ dynamicGas: makeGasLog(1),
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG2: {
- execute: makeLog(2),
- gasCost: makeGasLog(2),
- validateStack: makeStackFunc(4, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(2),
+ dynamicGas: makeGasLog(2),
+ minStack: minStack(4, 0),
+ maxStack: maxStack(4, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG3: {
- execute: makeLog(3),
- gasCost: makeGasLog(3),
- validateStack: makeStackFunc(5, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(3),
+ dynamicGas: makeGasLog(3),
+ minStack: minStack(5, 0),
+ maxStack: maxStack(5, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG4: {
- execute: makeLog(4),
- gasCost: makeGasLog(4),
- validateStack: makeStackFunc(6, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(4),
+ dynamicGas: makeGasLog(4),
+ minStack: minStack(6, 0),
+ maxStack: maxStack(6, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
CREATE: {
- execute: opCreate,
- gasCost: gasCreate,
- validateStack: makeStackFunc(3, 1),
- memorySize: memoryCreate,
- valid: true,
- writes: true,
- returns: true,
+ execute: opCreate,
+ dynamicGas: gasCreate,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ memorySize: memoryCreate,
+ valid: true,
+ writes: true,
+ returns: true,
},
CALL: {
- execute: opCall,
- gasCost: gasCall,
- validateStack: makeStackFunc(7, 1),
- memorySize: memoryCall,
- valid: true,
- returns: true,
+ execute: opCall,
+ dynamicGas: gasCall,
+ minStack: minStack(7, 1),
+ maxStack: maxStack(7, 1),
+ memorySize: memoryCall,
+ valid: true,
+ returns: true,
},
CALLCODE: {
- execute: opCallCode,
- gasCost: gasCallCode,
- validateStack: makeStackFunc(7, 1),
- memorySize: memoryCall,
- valid: true,
- returns: true,
+ execute: opCallCode,
+ dynamicGas: gasCallCode,
+ minStack: minStack(7, 1),
+ maxStack: maxStack(7, 1),
+ memorySize: memoryCall,
+ valid: true,
+ returns: true,
},
RETURN: {
- execute: opReturn,
- gasCost: gasReturn,
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryReturn,
- halts: true,
- valid: true,
+ execute: opReturn,
+ dynamicGas: gasReturn,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryReturn,
+ halts: true,
+ valid: true,
},
SELFDESTRUCT: {
- execute: opSuicide,
- gasCost: gasSuicide,
- validateStack: makeStackFunc(1, 0),
- halts: true,
- valid: true,
- writes: true,
+ execute: opSuicide,
+ dynamicGas: gasSuicide,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ halts: true,
+ valid: true,
+ writes: true,
},
}
}
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
index 8fa6c90ca7..4fcb41442c 100644
--- a/core/vm/memory_table.go
+++ b/core/vm/memory_table.go
@@ -16,82 +16,98 @@
package vm
-import (
- "math/big"
-
- "github.com/ethereum/go-ethereum/common/math"
-)
-
-func memorySha3(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
+func memorySha3(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
-func memoryCallDataCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
+func memoryCallDataCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
}
-func memoryReturnDataCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
+func memoryReturnDataCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
}
-func memoryCodeCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
+func memoryCodeCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
}
-func memoryExtCodeCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(3))
+func memoryExtCodeCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(3))
}
-func memoryMLoad(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big.NewInt(32))
+func memoryMLoad(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 32)
}
-func memoryMStore8(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big.NewInt(1))
+func memoryMStore8(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 1)
}
-func memoryMStore(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big.NewInt(32))
+func memoryMStore(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 32)
}
-func memoryCreate(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(2))
+func memoryCreate(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(2))
}
-func memoryCreate2(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(2))
+func memoryCreate2(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(2))
}
-func memoryCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(5), stack.Back(6))
- y := calcMemSize(stack.Back(3), stack.Back(4))
-
- return math.BigMax(x, y)
+func memoryCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(3), stack.Back(4))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
+}
+func memoryDelegateCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
}
-func memoryDelegateCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(4), stack.Back(5))
- y := calcMemSize(stack.Back(2), stack.Back(3))
-
- return math.BigMax(x, y)
+func memoryStaticCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
}
-func memoryStaticCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(4), stack.Back(5))
- y := calcMemSize(stack.Back(2), stack.Back(3))
-
- return math.BigMax(x, y)
+func memoryReturn(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
-func memoryReturn(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
+func memoryRevert(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
-func memoryRevert(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
-}
-
-func memoryLog(stack *Stack) *big.Int {
- mSize, mStart := stack.Back(1), stack.Back(0)
- return calcMemSize(mStart, mSize)
+func memoryLog(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index cda49a34b4..db1f6f3822 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -22,10 +22,10 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -99,7 +99,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
setDefaults(cfg)
if cfg.State == nil {
- cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
}
var (
address = common.BytesToAddress([]byte("contract"))
@@ -129,7 +129,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
setDefaults(cfg)
if cfg.State == nil {
- cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
}
var (
vmenv = NewEnv(cfg)
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index bac06e524b..15f545ddca 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -23,9 +23,9 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
@@ -95,7 +95,7 @@ func TestExecute(t *testing.T) {
}
func TestCall(t *testing.T) {
- state, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ state, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
address := common.HexToAddress("0x0a")
state.SetCode(address, []byte{
byte(vm.PUSH1), 10,
@@ -151,7 +151,7 @@ func BenchmarkCall(b *testing.B) {
}
func benchmarkEVM_Create(bench *testing.B, code string) {
var (
- statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
sender = common.BytesToAddress([]byte("sender"))
receiver = common.BytesToAddress([]byte("receiver"))
)
diff --git a/core/vm/stack_table.go b/core/vm/stack_table.go
index a4b1cfcd89..10c12901af 100644
--- a/core/vm/stack_table.go
+++ b/core/vm/stack_table.go
@@ -17,28 +17,26 @@
package vm
import (
- "fmt"
-
"github.com/ethereum/go-ethereum/params"
)
-func makeStackFunc(pop, push int) stackValidationFunc {
- return func(stack *Stack) error {
- if err := stack.require(pop); err != nil {
- return err
- }
-
- if stack.len()+push-pop > int(params.StackLimit) {
- return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit)
- }
- return nil
- }
+func minSwapStack(n int) int {
+ return minStack(n, n)
+}
+func maxSwapStack(n int) int {
+ return maxStack(n, n)
}
-func makeDupStackFunc(n int) stackValidationFunc {
- return makeStackFunc(n, n+1)
+func minDupStack(n int) int {
+ return minStack(n, n+1)
+}
+func maxDupStack(n int) int {
+ return maxStack(n, n+1)
}
-func makeSwapStackFunc(n int) stackValidationFunc {
- return makeStackFunc(n, n)
+func maxStack(pop, push int) int {
+ return int(params.StackLimit) + pop - push
+}
+func minStack(pops, push int) int {
+ return pops
}
diff --git a/dashboard/assets.go b/dashboard/assets.go
index f3e7cf9815..c63ad198da 100644
--- a/dashboard/assets.go
+++ b/dashboard/assets.go
@@ -2,6 +2,7 @@
// sources:
// assets/index.html
// assets/bundle.js
+// assets/bundle.js.map
package dashboard
@@ -71,7 +72,7 @@ var _indexHtml = []byte(`
-
+