aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/chaincmd.go62
-rw-r--r--cmd/geth/main.go2
-rw-r--r--cmd/puppeth/puppeth.go7
-rw-r--r--cmd/utils/cmd.go94
-rw-r--r--core/asm/compiler.go2
-rw-r--r--core/evm.go19
-rw-r--r--core/headerchain.go2
-rw-r--r--core/state/statedb.go4
-rw-r--r--core/vm/doc.go17
-rw-r--r--core/vm/evm.go6
-rw-r--r--core/vm/instructions.go171
-rw-r--r--core/vm/instructions_test.go6
-rw-r--r--core/vm/interpreter.go6
-rw-r--r--core/vm/intpool.go16
-rw-r--r--core/vm/logger_test.go2
-rw-r--r--core/vm/runtime/runtime.go4
-rw-r--r--core/vm/vm_jit.go389
-rw-r--r--core/vm/vm_jit_fake.go19
-rw-r--r--crypto/ecies/ecies.go6
-rw-r--r--crypto/ecies/ecies_test.go20
-rw-r--r--ethdb/database.go6
-rw-r--r--p2p/rlpx.go4
-rw-r--r--rpc/http.go3
-rw-r--r--whisper/whisperv5/message.go2
-rw-r--r--whisper/whisperv6/message.go2
25 files changed, 307 insertions, 564 deletions
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index c9ab72b6d..d3086921b 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -96,6 +96,34 @@ Optional second and third arguments control the first and
last block to write. In this mode, the file will be appended
if already existing.`,
}
+ importPreimagesCommand = cli.Command{
+ Action: utils.MigrateFlags(importPreimages),
+ Name: "import-preimages",
+ Usage: "Import the preimage database from an RLP stream",
+ ArgsUsage: "<datafile>",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ utils.CacheFlag,
+ utils.LightModeFlag,
+ },
+ Category: "BLOCKCHAIN COMMANDS",
+ Description: `
+ The import-preimages command imports hash preimages from an RLP encoded stream.`,
+ }
+ exportPreimagesCommand = cli.Command{
+ Action: utils.MigrateFlags(exportPreimages),
+ Name: "export-preimages",
+ Usage: "Export the preimage database into an RLP stream",
+ ArgsUsage: "<dumpfile>",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ utils.CacheFlag,
+ utils.LightModeFlag,
+ },
+ Category: "BLOCKCHAIN COMMANDS",
+ Description: `
+The export-preimages command export hash preimages to an RLP encoded stream`,
+ }
copydbCommand = cli.Command{
Action: utils.MigrateFlags(copyDb),
Name: "copydb",
@@ -299,7 +327,39 @@ func exportChain(ctx *cli.Context) error {
if err != nil {
utils.Fatalf("Export error: %v\n", err)
}
- fmt.Printf("Export done in %v", time.Since(start))
+ fmt.Printf("Export done in %v\n", time.Since(start))
+ return nil
+}
+
+// importPreimages imports preimage data from the specified file.
+func importPreimages(ctx *cli.Context) error {
+ if len(ctx.Args()) < 1 {
+ utils.Fatalf("This command requires an argument.")
+ }
+ stack := makeFullNode(ctx)
+ diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase)
+
+ start := time.Now()
+ if err := utils.ImportPreimages(diskdb, ctx.Args().First()); err != nil {
+ utils.Fatalf("Export error: %v\n", err)
+ }
+ fmt.Printf("Export done in %v\n", time.Since(start))
+ return nil
+}
+
+// exportPreimages dumps the preimage data to specified json file in streaming way.
+func exportPreimages(ctx *cli.Context) error {
+ if len(ctx.Args()) < 1 {
+ utils.Fatalf("This command requires an argument.")
+ }
+ stack := makeFullNode(ctx)
+ diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase)
+
+ start := time.Now()
+ if err := utils.ExportPreimages(diskdb, ctx.Args().First()); err != nil {
+ utils.Fatalf("Export error: %v\n", err)
+ }
+ fmt.Printf("Export done in %v\n", time.Since(start))
return nil
}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index f5a3fa941..061384d1b 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -155,6 +155,8 @@ func init() {
initCommand,
importCommand,
exportCommand,
+ importPreimagesCommand,
+ exportPreimagesCommand,
copydbCommand,
removedbCommand,
dumpCommand,
diff --git a/cmd/puppeth/puppeth.go b/cmd/puppeth/puppeth.go
index 26382dac1..f9b8fe481 100644
--- a/cmd/puppeth/puppeth.go
+++ b/cmd/puppeth/puppeth.go
@@ -20,6 +20,7 @@ package main
import (
"math/rand"
"os"
+ "strings"
"time"
"github.com/ethereum/go-ethereum/log"
@@ -34,7 +35,7 @@ func main() {
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "network",
- Usage: "name of the network to administer",
+ Usage: "name of the network to administer (no spaces or hyphens, please)",
},
cli.IntFlag{
Name: "loglevel",
@@ -47,6 +48,10 @@ func main() {
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
rand.Seed(time.Now().UnixNano())
+ network := c.String("network")
+ if strings.Contains(network, " ") || strings.Contains(network, "-") {
+ log.Crit("No spaces or hyphens allowed in network name")
+ }
// Start the wizard and relinquish control
makeWizard(c.String("network")).run()
return nil
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 186d18d8f..c0af4c13e 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -27,8 +27,11 @@ import (
"strings"
"syscall"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
@@ -105,6 +108,8 @@ func ImportChain(chain *core.BlockChain, fn string) error {
}
log.Info("Importing blockchain", "file", fn)
+
+ // Open the file handle and potentially unwrap the gzip stream
fh, err := os.Open(fn)
if err != nil {
return err
@@ -180,8 +185,12 @@ func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block
return nil
}
+// ExportChain exports a blockchain into the specified file, truncating any data
+// already present in the file.
func ExportChain(blockchain *core.BlockChain, fn string) error {
log.Info("Exporting blockchain", "file", fn)
+
+ // Open the file handle and potentially wrap with a gzip stream
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
if err != nil {
return err
@@ -193,7 +202,7 @@ func ExportChain(blockchain *core.BlockChain, fn string) error {
writer = gzip.NewWriter(writer)
defer writer.(*gzip.Writer).Close()
}
-
+ // Iterate over the blocks and export them
if err := blockchain.Export(writer); err != nil {
return err
}
@@ -202,9 +211,12 @@ func ExportChain(blockchain *core.BlockChain, fn string) error {
return nil
}
+// ExportAppendChain exports a blockchain into the specified file, appending to
+// the file if data already exists in it.
func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error {
log.Info("Exporting blockchain", "file", fn)
- // TODO verify mode perms
+
+ // Open the file handle and potentially wrap with a gzip stream
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
if err != nil {
return err
@@ -216,10 +228,86 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
writer = gzip.NewWriter(writer)
defer writer.(*gzip.Writer).Close()
}
-
+ // Iterate over the blocks and export them
if err := blockchain.ExportN(writer, first, last); err != nil {
return err
}
log.Info("Exported blockchain to", "file", fn)
return nil
}
+
+// ImportPreimages imports a batch of exported hash preimages into the database.
+func ImportPreimages(db *ethdb.LDBDatabase, fn string) error {
+ log.Info("Importing preimages", "file", fn)
+
+ // Open the file handle and potentially unwrap the gzip stream
+ fh, err := os.Open(fn)
+ if err != nil {
+ return err
+ }
+ defer fh.Close()
+
+ var reader io.Reader = fh
+ if strings.HasSuffix(fn, ".gz") {
+ if reader, err = gzip.NewReader(reader); err != nil {
+ return err
+ }
+ }
+ stream := rlp.NewStream(reader, 0)
+
+ // Import the preimages in batches to prevent disk trashing
+ preimages := make(map[common.Hash][]byte)
+
+ for {
+ // Read the next entry and ensure it's not junk
+ var blob []byte
+
+ if err := stream.Decode(&blob); err != nil {
+ if err == io.EOF {
+ break
+ }
+ return err
+ }
+ // Accumulate the preimages and flush when enough ws gathered
+ preimages[crypto.Keccak256Hash(blob)] = common.CopyBytes(blob)
+ if len(preimages) > 1024 {
+ if err := core.WritePreimages(db, 0, preimages); err != nil {
+ return err
+ }
+ preimages = make(map[common.Hash][]byte)
+ }
+ }
+ // Flush the last batch preimage data
+ if len(preimages) > 0 {
+ return core.WritePreimages(db, 0, preimages)
+ }
+ return nil
+}
+
+// ExportPreimages exports all known hash preimages into the specified file,
+// truncating any data already present in the file.
+func ExportPreimages(db *ethdb.LDBDatabase, fn string) error {
+ log.Info("Exporting preimages", "file", fn)
+
+ // Open the file handle and potentially wrap with a gzip stream
+ fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+ if err != nil {
+ return err
+ }
+ defer fh.Close()
+
+ var writer io.Writer = fh
+ if strings.HasSuffix(fn, ".gz") {
+ writer = gzip.NewWriter(writer)
+ defer writer.(*gzip.Writer).Close()
+ }
+ // Iterate over the preimages and export them
+ it := db.NewIteratorWithPrefix([]byte("secure-key-"))
+ for it.Next() {
+ if err := rlp.Encode(writer, it.Value()); err != nil {
+ return err
+ }
+ }
+ log.Info("Exported preimages", "file", fn)
+ return nil
+}
diff --git a/core/asm/compiler.go b/core/asm/compiler.go
index 1b9025a54..18dc0877f 100644
--- a/core/asm/compiler.go
+++ b/core/asm/compiler.go
@@ -114,7 +114,7 @@ func (c *Compiler) Compile() (string, []error) {
}
// next returns the next token and increments the
-// posititon.
+// position.
func (c *Compiler) next() token {
token := c.tokens[c.pos]
c.pos++
diff --git a/core/evm.go b/core/evm.go
index 55db53927..596ea95fb 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -60,13 +60,26 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash {
+ var cache map[uint64]common.Hash
+
return func(n uint64) common.Hash {
+ // If there's no hash cache yet, make one
+ if cache == nil {
+ cache = map[uint64]common.Hash{
+ ref.Number.Uint64() - 1: ref.ParentHash,
+ }
+ }
+ // Try to fulfill the request from the cache
+ if hash, ok := cache[n]; ok {
+ return hash
+ }
+ // Not cached, iterate the blocks and cache the hashes
for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
- if header.Number.Uint64() == n {
- return header.Hash()
+ cache[header.Number.Uint64()-1] = header.ParentHash
+ if n == header.Number.Uint64()-1 {
+ return header.ParentHash
}
}
-
return common.Hash{}
}
}
diff --git a/core/headerchain.go b/core/headerchain.go
index 73cd5d2c4..2d1b0a2a1 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -23,6 +23,7 @@ import (
"math"
"math/big"
mrand "math/rand"
+ "sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -32,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/hashicorp/golang-lru"
- "sync/atomic"
)
const (
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 776693e24..5473ff8da 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -83,7 +83,7 @@ type StateDB struct {
lock sync.Mutex
}
-// Create a new state from a given trie
+// Create a new state from a given trie.
func New(root common.Hash, db Database) (*StateDB, error) {
tr, err := db.OpenTrie(root)
if err != nil {
@@ -110,7 +110,7 @@ func (self *StateDB) Error() error {
return self.dbErr
}
-// Reset clears out all emphemeral state objects from the state db, but keeps
+// Reset clears out all ephemeral state objects from the state db, but keeps
// the underlying state trie to avoid reloading data for the next operations.
func (self *StateDB) Reset(root common.Hash) error {
tr, err := self.db.OpenTrie(root)
diff --git a/core/vm/doc.go b/core/vm/doc.go
index 239be2cfe..5864d0cfa 100644
--- a/core/vm/doc.go
+++ b/core/vm/doc.go
@@ -17,19 +17,8 @@
/*
Package vm implements the Ethereum Virtual Machine.
-The vm package implements two EVMs, a byte code VM and a JIT VM. The BC
-(Byte Code) VM loops over a set of bytes and executes them according to the set
-of rules defined in the Ethereum yellow paper. When the BC VM is invoked it
-invokes the JIT VM in a separate goroutine and compiles the byte code in JIT
-instructions.
-
-The JIT VM, when invoked, loops around a set of pre-defined instructions until
-it either runs of gas, causes an internal error, returns or stops.
-
-The JIT optimiser attempts to pre-compile instructions in to chunks or segments
-such as multiple PUSH operations and static JUMPs. It does this by analysing the
-opcodes and attempts to match certain regions to known sets. Whenever the
-optimiser finds said segments it creates a new instruction and replaces the
-first occurrence in the sequence.
+The vm package implements one EVM, a byte code VM. The BC (Byte Code) VM loops
+over a set of bytes and executes them according to the set of rules defined
+in the Ethereum yellow paper.
*/
package vm
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 46e7baff4..96676c314 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -111,7 +111,7 @@ type EVM struct {
callGasTemp uint64
}
-// NewEVM retutrns a new EVM . The returned EVM is not thread safe and should
+// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
evm := &EVM{
@@ -221,7 +221,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
to = AccountRef(caller.Address())
)
// initialise a new contract and set the code that is to be used by the
- // E The contract is a scoped evmironment for this execution context
+ // EVM. The contract is a scoped environment for this execution context
// only.
contract := NewContract(caller, to, value, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
@@ -341,7 +341,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value)
// initialise a new contract and set the code that is to be used by the
- // E The contract is a scoped evmironment for this execution context
+ // EVM. The contract is a scoped environment for this execution context
// only.
contract := NewContract(caller, AccountRef(contractAddr), value, gas)
contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 66e804fb7..1e494a0eb 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -39,20 +39,18 @@ var (
)
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(math.U256(x.Add(x, y)))
-
- evm.interpreter.intPool.put(y)
+ x, y := stack.pop(), stack.peek()
+ math.U256(y.Add(x, y))
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(math.U256(x.Sub(x, y)))
-
- evm.interpreter.intPool.put(y)
+ x, y := stack.pop(), stack.peek()
+ math.U256(y.Sub(x, y))
+ evm.interpreter.intPool.put(x)
return nil, nil
}
@@ -66,44 +64,39 @@ func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
}
func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
+ x, y := stack.pop(), stack.peek()
if y.Sign() != 0 {
- stack.push(math.U256(x.Div(x, y)))
+ math.U256(y.Div(x, y))
} else {
- stack.push(new(big.Int))
+ y.SetUint64(0)
}
-
- evm.interpreter.intPool.put(y)
-
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := math.S256(stack.pop()), math.S256(stack.pop())
- if y.Sign() == 0 {
- stack.push(new(big.Int))
- return nil, nil
+ res := evm.interpreter.intPool.getZero()
+
+ if y.Sign() == 0 || x.Sign() == 0 {
+ stack.push(res)
} else {
- n := new(big.Int)
- if evm.interpreter.intPool.get().Mul(x, y).Sign() < 0 {
- n.SetInt64(-1)
+ if x.Sign() != y.Sign() {
+ res.Div(x.Abs(x), y.Abs(y))
+ res.Neg(res)
} else {
- n.SetInt64(1)
+ res.Div(x.Abs(x), y.Abs(y))
}
-
- res := x.Div(x.Abs(x), y.Abs(y))
- res.Mul(res, n)
-
stack.push(math.U256(res))
}
- evm.interpreter.intPool.put(y)
+ evm.interpreter.intPool.put(x, y)
return nil, nil
}
func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop()
if y.Sign() == 0 {
- stack.push(new(big.Int))
+ stack.push(x.SetUint64(0))
} else {
stack.push(math.U256(x.Mod(x, y)))
}
@@ -113,23 +106,20 @@ func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := math.S256(stack.pop()), math.S256(stack.pop())
+ res := evm.interpreter.intPool.getZero()
if y.Sign() == 0 {
- stack.push(new(big.Int))
+ stack.push(res)
} else {
- n := new(big.Int)
if x.Sign() < 0 {
- n.SetInt64(-1)
+ res.Mod(x.Abs(x), y.Abs(y))
+ res.Neg(res)
} else {
- n.SetInt64(1)
+ res.Mod(x.Abs(x), y.Abs(y))
}
-
- res := x.Mod(x.Abs(x), y.Abs(y))
- res.Mul(res, n)
-
stack.push(math.U256(res))
}
- evm.interpreter.intPool.put(y)
+ evm.interpreter.intPool.put(x, y)
return nil, nil
}
@@ -163,32 +153,30 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
}
func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x := stack.pop()
- stack.push(math.U256(x.Not(x)))
+ x := stack.peek()
+ math.U256(x.Not(x))
return nil, nil
}
func opLt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
+ x, y := stack.pop(), stack.peek()
if x.Cmp(y) < 0 {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
+ y.SetUint64(1)
} else {
- stack.push(new(big.Int))
+ y.SetUint64(0)
}
-
- evm.interpreter.intPool.put(x, y)
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
+ x, y := stack.pop(), stack.peek()
if x.Cmp(y) > 0 {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
+ y.SetUint64(1)
} else {
- stack.push(new(big.Int))
+ y.SetUint64(0)
}
-
- evm.interpreter.intPool.put(x, y)
+ evm.interpreter.intPool.put(x)
return nil, nil
}
@@ -270,18 +258,18 @@ func opAnd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
}
func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.Or(x, y))
+ x, y := stack.pop(), stack.peek()
+ y.Or(x, y)
- evm.interpreter.intPool.put(y)
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.Xor(x, y))
+ x, y := stack.pop(), stack.peek()
+ y.Xor(x, y)
- evm.interpreter.intPool.put(y)
+ evm.interpreter.intPool.put(x)
return nil, nil
}
@@ -300,13 +288,12 @@ func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y, z := stack.pop(), stack.pop(), stack.pop()
if z.Cmp(bigZero) > 0 {
- add := x.Add(x, y)
- add.Mod(add, z)
- stack.push(math.U256(add))
+ x.Add(x, y)
+ x.Mod(x, z)
+ stack.push(math.U256(x))
} else {
- stack.push(new(big.Int))
+ stack.push(x.SetUint64(0))
}
-
evm.interpreter.intPool.put(y, z)
return nil, nil
}
@@ -314,13 +301,12 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y, z := stack.pop(), stack.pop(), stack.pop()
if z.Cmp(bigZero) > 0 {
- mul := x.Mul(x, y)
- mul.Mod(mul, z)
- stack.push(math.U256(mul))
+ x.Mul(x, y)
+ x.Mod(x, z)
+ stack.push(math.U256(x))
} else {
- stack.push(new(big.Int))
+ stack.push(x.SetUint64(0))
}
-
evm.interpreter.intPool.put(y, z)
return nil, nil
}
@@ -393,8 +379,7 @@ func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
if evm.vmConfig.EnablePreimageRecording {
evm.StateDB.AddPreimage(common.BytesToHash(hash), data)
}
-
- stack.push(new(big.Int).SetBytes(hash))
+ stack.push(evm.interpreter.intPool.get().SetBytes(hash))
evm.interpreter.intPool.put(offset, size)
return nil, nil
@@ -406,10 +391,8 @@ func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
}
func opBalance(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- addr := common.BigToAddress(stack.pop())
- balance := evm.StateDB.GetBalance(addr)
-
- stack.push(new(big.Int).Set(balance))
+ slot := stack.peek()
+ slot.Set(evm.StateDB.GetBalance(common.BigToAddress(slot)))
return nil, nil
}
@@ -429,7 +412,7 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
}
func opCallDataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(new(big.Int).SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
+ stack.push(evm.interpreter.intPool.get().SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
return nil, nil
}
@@ -460,10 +443,11 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory,
memOffset = stack.pop()
dataOffset = stack.pop()
length = stack.pop()
+
+ end = evm.interpreter.intPool.get().Add(dataOffset, length)
)
- defer evm.interpreter.intPool.put(memOffset, dataOffset, length)
+ defer evm.interpreter.intPool.put(memOffset, dataOffset, length, end)
- end := new(big.Int).Add(dataOffset, length)
if end.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < end.Uint64() {
return nil, errReturnDataOutOfBounds
}
@@ -473,11 +457,8 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory,
}
func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- a := stack.pop()
-
- addr := common.BigToAddress(a)
- a.SetInt64(int64(evm.StateDB.GetCodeSize(addr)))
- stack.push(a)
+ slot := stack.peek()
+ slot.SetUint64(uint64(evm.StateDB.GetCodeSize(common.BigToAddress(slot))))
return nil, nil
}
@@ -485,6 +466,7 @@ func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta
func opCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
l := evm.interpreter.intPool.get().SetInt64(int64(len(contract.Code)))
stack.push(l)
+
return nil, nil
}
@@ -527,9 +509,8 @@ func opBlockhash(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
if num.Cmp(n) > 0 && num.Cmp(evm.BlockNumber) < 0 {
stack.push(evm.GetHash(num.Uint64()).Big())
} else {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
}
-
evm.interpreter.intPool.put(num, n)
return nil, nil
}
@@ -540,22 +521,22 @@ func opCoinbase(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
}
func opTimestamp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(new(big.Int).Set(evm.Time)))
+ stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.Time)))
return nil, nil
}
func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(new(big.Int).Set(evm.BlockNumber)))
+ stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.BlockNumber)))
return nil, nil
}
func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(new(big.Int).Set(evm.Difficulty)))
+ stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.Difficulty)))
return nil, nil
}
func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(new(big.Int).SetUint64(evm.GasLimit)))
+ stack.push(math.U256(evm.interpreter.intPool.get().SetUint64(evm.GasLimit)))
return nil, nil
}
@@ -566,7 +547,7 @@ func opPop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
offset := stack.pop()
- val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32))
+ val := evm.interpreter.intPool.get().SetBytes(memory.Get(offset.Int64(), 32))
stack.push(val)
evm.interpreter.intPool.put(offset)
@@ -670,9 +651,9 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
// rule) and treat as an error, if the ruleset is frontier we must
// ignore this error and pretend the operation was successful.
if evm.ChainConfig().IsHomestead(evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
} else {
stack.push(addr.Big())
}
@@ -701,9 +682,9 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
}
ret, returnGas, err := evm.Call(contract, toAddr, args, gas, value)
if err != nil {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
} else {
- stack.push(big.NewInt(1))
+ stack.push(evm.interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
@@ -730,9 +711,9 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
}
ret, returnGas, err := evm.CallCode(contract, toAddr, args, gas, value)
if err != nil {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
} else {
- stack.push(big.NewInt(1))
+ stack.push(evm.interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
@@ -755,9 +736,9 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
ret, returnGas, err := evm.DelegateCall(contract, toAddr, args, gas)
if err != nil {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
} else {
- stack.push(big.NewInt(1))
+ stack.push(evm.interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
@@ -780,9 +761,9 @@ func opStaticCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
ret, returnGas, err := evm.StaticCall(contract, toAddr, args, gas)
if err != nil {
- stack.push(new(big.Int))
+ stack.push(evm.interpreter.intPool.getZero())
} else {
- stack.push(big.NewInt(1))
+ stack.push(evm.interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index 134363bb7..0de558612 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -32,7 +32,7 @@ type twoOperandTest struct {
func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
+ env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@@ -68,7 +68,7 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64
func TestByteOp(t *testing.T) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
+ env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
stack = newstack()
)
tests := []struct {
@@ -198,7 +198,7 @@ func TestSLT(t *testing.T) {
func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
+ env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
stack = newstack()
)
// convert args
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 95490adfc..47d5e7f2f 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -28,10 +28,6 @@ import (
type Config struct {
// Debug enabled debugging Interpreter options
Debug bool
- // EnableJit enabled the JIT VM
- EnableJit bool
- // ForceJit forces the JIT VM
- ForceJit bool
// Tracer is the op code logger
Tracer Tracer
// NoRecursion disabled Interpreter call, callcode,
@@ -47,7 +43,7 @@ type Config struct {
// Interpreter is used to run Ethereum based contracts and will utilise the
// passed evmironment to query external sources for state information.
-// The Interpreter will run the byte code VM or JIT VM based on the passed
+// The Interpreter will run the byte code VM based on the passed
// configuration.
type Interpreter struct {
evm *EVM
diff --git a/core/vm/intpool.go b/core/vm/intpool.go
index 384f5df59..5dbda18ee 100644
--- a/core/vm/intpool.go
+++ b/core/vm/intpool.go
@@ -32,24 +32,36 @@ func newIntPool() *intPool {
return &intPool{pool: newstack()}
}
+// get retrieves a big int from the pool, allocating one if the pool is empty.
+// Note, the returned int's value is arbitrary and will not be zeroed!
func (p *intPool) get() *big.Int {
if p.pool.len() > 0 {
return p.pool.pop()
}
return new(big.Int)
}
+
+// getZero retrieves a big int from the pool, setting it to zero or allocating
+// a new one if the pool is empty.
+func (p *intPool) getZero() *big.Int {
+ if p.pool.len() > 0 {
+ return p.pool.pop().SetUint64(0)
+ }
+ return new(big.Int)
+}
+
+// put returns an allocated big int to the pool to be later reused by get calls.
+// Note, the values as saved as is; neither put nor get zeroes the ints out!
func (p *intPool) put(is ...*big.Int) {
if len(p.pool.data) > poolLimit {
return
}
-
for _, i := range is {
// verifyPool is a build flag. Pool verification makes sure the integrity
// of the integer pool by comparing values to a default value.
if verifyPool {
i.Set(checkVal)
}
-
p.pool.push(i)
}
}
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index 915f7177e..28830c445 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -48,7 +48,7 @@ type dummyStateDB struct {
func TestStoreCapture(t *testing.T) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
+ env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
logger = NewStructLogger(nil)
mem = NewMemory()
stack = newstack()
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index edbf54176..1e9ed7ae2 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -41,7 +41,6 @@ type Config struct {
GasLimit uint64
GasPrice *big.Int
Value *big.Int
- DisableJit bool // "disable" so it's enabled by default
Debug bool
EVMConfig vm.Config
@@ -92,8 +91,7 @@ func setDefaults(cfg *Config) {
// It returns the EVM's return value, the new state and an error if it failed.
//
// Executes sets up a in memory, temporarily, environment for the execution of
-// the given code. It enabled the JIT by default and make sure that it's restored
-// to it's original state afterwards.
+// the given code. It makes sure that it's restored to it's original state afterwards.
func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
if cfg == nil {
cfg = new(Config)
diff --git a/core/vm/vm_jit.go b/core/vm/vm_jit.go
deleted file mode 100644
index eb3acfb10..000000000
--- a/core/vm/vm_jit.go
+++ /dev/null
@@ -1,389 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// +build evmjit
-
-package vm
-
-/*
-
-void* evmjit_create();
-int evmjit_run(void* _jit, void* _data, void* _env);
-void evmjit_destroy(void* _jit);
-
-// Shared library evmjit (e.g. libevmjit.so) is expected to be installed in /usr/local/lib
-// More: https://github.com/ethereum/evmjit
-#cgo LDFLAGS: -levmjit
-*/
-import "C"
-
-/*
-import (
- "bytes"
- "errors"
- "fmt"
- "math/big"
- "unsafe"
-
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/params"
-)
-
-type JitVm struct {
- env EVM
- me ContextRef
- callerAddr []byte
- price *big.Int
- data RuntimeData
-}
-
-type i256 [32]byte
-
-type RuntimeData struct {
- gas int64
- gasPrice int64
- callData *byte
- callDataSize uint64
- address i256
- caller i256
- origin i256
- callValue i256
- coinBase i256
- difficulty i256
- gasLimit i256
- number uint64
- timestamp int64
- code *byte
- codeSize uint64
- codeHash i256
-}
-
-func hash2llvm(h []byte) i256 {
- var m i256
- copy(m[len(m)-len(h):], h) // right aligned copy
- return m
-}
-
-func llvm2hash(m *i256) []byte {
- return C.GoBytes(unsafe.Pointer(m), C.int(len(m)))
-}
-
-func llvm2hashRef(m *i256) []byte {
- return (*[1 << 30]byte)(unsafe.Pointer(m))[:len(m):len(m)]
-}
-
-func address2llvm(addr []byte) i256 {
- n := hash2llvm(addr)
- bswap(&n)
- return n
-}
-
-// bswap swap bytes of the 256-bit integer on LLVM side
-// TODO: Do not change memory on LLVM side, that can conflict with memory access optimizations
-func bswap(m *i256) *i256 {
- for i, l := 0, len(m); i < l/2; i++ {
- m[i], m[l-i-1] = m[l-i-1], m[i]
- }
- return m
-}
-
-func trim(m []byte) []byte {
- skip := 0
- for i := 0; i < len(m); i++ {
- if m[i] == 0 {
- skip++
- } else {
- break
- }
- }
- return m[skip:]
-}
-
-func getDataPtr(m []byte) *byte {
- var p *byte
- if len(m) > 0 {
- p = &m[0]
- }
- return p
-}
-
-func big2llvm(n *big.Int) i256 {
- m := hash2llvm(n.Bytes())
- bswap(&m)
- return m
-}
-
-func llvm2big(m *i256) *big.Int {
- n := big.NewInt(0)
- for i := 0; i < len(m); i++ {
- b := big.NewInt(int64(m[i]))
- b.Lsh(b, uint(i)*8)
- n.Add(n, b)
- }
- return n
-}
-
-// llvm2bytesRef creates a []byte slice that references byte buffer on LLVM side (as of that not controller by GC)
-// User must ensure that referenced memory is available to Go until the data is copied or not needed any more
-func llvm2bytesRef(data *byte, length uint64) []byte {
- if length == 0 {
- return nil
- }
- if data == nil {
- panic("Unexpected nil data pointer")
- }
- return (*[1 << 30]byte)(unsafe.Pointer(data))[:length:length]
-}
-
-func untested(condition bool, message string) {
- if condition {
- panic("Condition `" + message + "` tested. Remove assert.")
- }
-}
-
-func assert(condition bool, message string) {
- if !condition {
- panic("Assert `" + message + "` failed!")
- }
-}
-
-func NewJitVm(env EVM) *JitVm {
- return &JitVm{env: env}
-}
-
-func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
- // TODO: depth is increased but never checked by VM. VM should not know about it at all.
- self.env.SetDepth(self.env.Depth() + 1)
-
- // TODO: Move it to Env.Call() or sth
- if Precompiled[string(me.Address())] != nil {
- // if it's address of precompiled contract
- // fallback to standard VM
- stdVm := New(self.env)
- return stdVm.Run(me, caller, code, value, gas, price, callData)
- }
-
- if self.me != nil {
- panic("JitVm.Run() can be called only once per JitVm instance")
- }
-
- self.me = me
- self.callerAddr = caller.Address()
- self.price = price
-
- self.data.gas = gas.Int64()
- self.data.gasPrice = price.Int64()
- self.data.callData = getDataPtr(callData)
- self.data.callDataSize = uint64(len(callData))
- self.data.address = address2llvm(self.me.Address())
- self.data.caller = address2llvm(caller.Address())
- self.data.origin = address2llvm(self.env.Origin())
- self.data.callValue = big2llvm(value)
- self.data.coinBase = address2llvm(self.env.Coinbase())
- self.data.difficulty = big2llvm(self.env.Difficulty())
- self.data.gasLimit = big2llvm(self.env.GasLimit())
- self.data.number = self.env.BlockNumber().Uint64()
- self.data.timestamp = self.env.Time()
- self.data.code = getDataPtr(code)
- self.data.codeSize = uint64(len(code))
- self.data.codeHash = hash2llvm(crypto.Keccak256(code)) // TODO: Get already computed hash?
-
- jit := C.evmjit_create()
- retCode := C.evmjit_run(jit, unsafe.Pointer(&self.data), unsafe.Pointer(self))
-
- if retCode < 0 {
- err = errors.New("OOG from JIT")
- gas.SetInt64(0) // Set gas to 0, JIT does not bother
- } else {
- gas.SetInt64(self.data.gas)
- if retCode == 1 { // RETURN
- ret = C.GoBytes(unsafe.Pointer(self.data.callData), C.int(self.data.callDataSize))
- } else if retCode == 2 { // SUICIDE
- // TODO: Suicide support logic should be moved to Env to be shared by VM implementations
- state := self.Env().State()
- receiverAddr := llvm2hashRef(bswap(&self.data.address))
- receiver := state.GetOrNewStateObject(receiverAddr)
- balance := state.GetBalance(me.Address())
- receiver.AddBalance(balance)
- state.Delete(me.Address())
- }
- }
-
- C.evmjit_destroy(jit)
- return
-}
-
-func (self *JitVm) Printf(format string, v ...interface{}) VirtualMachine {
- return self
-}
-
-func (self *JitVm) Endl() VirtualMachine {
- return self
-}
-
-func (self *JitVm) Env() EVM {
- return self.env
-}
-
-//export env_sha3
-func env_sha3(dataPtr *byte, length uint64, resultPtr unsafe.Pointer) {
- data := llvm2bytesRef(dataPtr, length)
- hash := crypto.Keccak256(data)
- result := (*i256)(resultPtr)
- *result = hash2llvm(hash)
-}
-
-//export env_sstore
-func env_sstore(vmPtr unsafe.Pointer, indexPtr unsafe.Pointer, valuePtr unsafe.Pointer) {
- vm := (*JitVm)(vmPtr)
- index := llvm2hash(bswap((*i256)(indexPtr)))
- value := llvm2hash(bswap((*i256)(valuePtr)))
- value = trim(value)
- if len(value) == 0 {
- prevValue := vm.env.State().GetState(vm.me.Address(), index)
- if len(prevValue) != 0 {
- vm.Env().State().Refund(vm.callerAddr, GasSStoreRefund)
- }
- }
-
- vm.env.State().SetState(vm.me.Address(), index, value)
-}
-
-//export env_sload
-func env_sload(vmPtr unsafe.Pointer, indexPtr unsafe.Pointer, resultPtr unsafe.Pointer) {
- vm := (*JitVm)(vmPtr)
- index := llvm2hash(bswap((*i256)(indexPtr)))
- value := vm.env.State().GetState(vm.me.Address(), index)
- result := (*i256)(resultPtr)
- *result = hash2llvm(value)
- bswap(result)
-}
-
-//export env_balance
-func env_balance(_vm unsafe.Pointer, _addr unsafe.Pointer, _result unsafe.Pointer) {
- vm := (*JitVm)(_vm)
- addr := llvm2hash((*i256)(_addr))
- balance := vm.Env().State().GetBalance(addr)
- result := (*i256)(_result)
- *result = big2llvm(balance)
-}
-
-//export env_blockhash
-func env_blockhash(_vm unsafe.Pointer, _number unsafe.Pointer, _result unsafe.Pointer) {
- vm := (*JitVm)(_vm)
- number := llvm2big((*i256)(_number))
- result := (*i256)(_result)
-
- currNumber := vm.Env().BlockNumber()
- limit := big.NewInt(0).Sub(currNumber, big.NewInt(256))
- if number.Cmp(limit) >= 0 && number.Cmp(currNumber) < 0 {
- hash := vm.Env().GetHash(uint64(number.Int64()))
- *result = hash2llvm(hash)
- } else {
- *result = i256{}
- }
-}
-
-//export env_call
-func env_call(_vm unsafe.Pointer, _gas *int64, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr unsafe.Pointer, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool {
- vm := (*JitVm)(_vm)
-
- //fmt.Printf("env_call (depth %d)\n", vm.Env().Depth())
-
- defer func() {
- if r := recover(); r != nil {
- fmt.Printf("Recovered in env_call (depth %d, out %p %d): %s\n", vm.Env().Depth(), outDataPtr, outDataLen, r)
- }
- }()
-
- balance := vm.Env().State().GetBalance(vm.me.Address())
- value := llvm2big((*i256)(_value))
-
- if balance.Cmp(value) >= 0 {
- receiveAddr := llvm2hash((*i256)(_receiveAddr))
- inData := C.GoBytes(inDataPtr, C.int(inDataLen))
- outData := llvm2bytesRef(outDataPtr, outDataLen)
- codeAddr := llvm2hash((*i256)(_codeAddr))
- gas := big.NewInt(*_gas)
- var out []byte
- var err error
- if bytes.Equal(codeAddr, receiveAddr) {
- out, err = vm.env.Call(vm.me, codeAddr, inData, gas, vm.price, value)
- } else {
- out, err = vm.env.CallCode(vm.me, codeAddr, inData, gas, vm.price, value)
- }
- *_gas = gas.Int64()
- if err == nil {
- copy(outData, out)
- return true
- }
- }
-
- return false
-}
-
-//export env_create
-func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initDataPtr unsafe.Pointer, initDataLen uint64, _result unsafe.Pointer) {
- vm := (*JitVm)(_vm)
-
- value := llvm2big((*i256)(_value))
- initData := C.GoBytes(initDataPtr, C.int(initDataLen)) // TODO: Unnecessary if low balance
- result := (*i256)(_result)
- *result = i256{}
-
- gas := big.NewInt(*_gas)
- ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value)
- if suberr == nil {
- dataGas := big.NewInt(int64(len(ret))) // TODO: Not the best design. env.Create can do it, it has the reference to gas counter
- dataGas.Mul(dataGas, params.CreateDataGas)
- gas.Sub(gas, dataGas)
- *result = hash2llvm(ref.Address())
- }
- *_gas = gas.Int64()
-}
-
-//export env_log
-func env_log(_vm unsafe.Pointer, dataPtr unsafe.Pointer, dataLen uint64, _topic1 unsafe.Pointer, _topic2 unsafe.Pointer, _topic3 unsafe.Pointer, _topic4 unsafe.Pointer) {
- vm := (*JitVm)(_vm)
-
- data := C.GoBytes(dataPtr, C.int(dataLen))
-
- topics := make([][]byte, 0, 4)
- if _topic1 != nil {
- topics = append(topics, llvm2hash((*i256)(_topic1)))
- }
- if _topic2 != nil {
- topics = append(topics, llvm2hash((*i256)(_topic2)))
- }
- if _topic3 != nil {
- topics = append(topics, llvm2hash((*i256)(_topic3)))
- }
- if _topic4 != nil {
- topics = append(topics, llvm2hash((*i256)(_topic4)))
- }
-
- vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data, vm.env.BlockNumber().Uint64()))
-}
-
-//export env_extcode
-func env_extcode(_vm unsafe.Pointer, _addr unsafe.Pointer, o_size *uint64) *byte {
- vm := (*JitVm)(_vm)
- addr := llvm2hash((*i256)(_addr))
- code := vm.Env().State().GetCode(addr)
- *o_size = uint64(len(code))
- return getDataPtr(code)
-}*/
diff --git a/core/vm/vm_jit_fake.go b/core/vm/vm_jit_fake.go
deleted file mode 100644
index 44b60abf6..000000000
--- a/core/vm/vm_jit_fake.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// +build !evmjit
-
-package vm
diff --git a/crypto/ecies/ecies.go b/crypto/ecies/ecies.go
index 2ed91c895..147418148 100644
--- a/crypto/ecies/ecies.go
+++ b/crypto/ecies/ecies.go
@@ -230,7 +230,7 @@ func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte,
// symDecrypt carries out CTR decryption using the block cipher specified in
// the parameters
-func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) {
+func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) {
c, err := params.Cipher(key)
if err != nil {
return
@@ -292,7 +292,7 @@ func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err e
}
// Decrypt decrypts an ECIES ciphertext.
-func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) {
+func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
if len(c) == 0 {
return nil, ErrInvalidMessage
}
@@ -361,6 +361,6 @@ func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err
return
}
- m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd])
+ m, err = symDecrypt(params, Ke, c[mStart:mEnd])
return
}
diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go
index 9cd5c79f7..f33f204d5 100644
--- a/crypto/ecies/ecies_test.go
+++ b/crypto/ecies/ecies_test.go
@@ -270,7 +270,7 @@ func TestEncryptDecrypt(t *testing.T) {
t.FailNow()
}
- pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
+ pt, err := prv2.Decrypt(ct, nil, nil)
if err != nil {
fmt.Println(err.Error())
t.FailNow()
@@ -281,7 +281,7 @@ func TestEncryptDecrypt(t *testing.T) {
t.FailNow()
}
- _, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
+ _, err = prv1.Decrypt(ct, nil, nil)
if err == nil {
fmt.Println("ecies: encryption should not have succeeded")
t.FailNow()
@@ -301,7 +301,7 @@ func TestDecryptShared2(t *testing.T) {
}
// Check that decrypting with correct shared data works.
- pt, err := prv.Decrypt(rand.Reader, ct, nil, shared2)
+ pt, err := prv.Decrypt(ct, nil, shared2)
if err != nil {
t.Fatal(err)
}
@@ -310,10 +310,10 @@ func TestDecryptShared2(t *testing.T) {
}
// Decrypting without shared data or incorrect shared data fails.
- if _, err = prv.Decrypt(rand.Reader, ct, nil, nil); err == nil {
+ if _, err = prv.Decrypt(ct, nil, nil); err == nil {
t.Fatal("ecies: decrypting without shared data didn't fail")
}
- if _, err = prv.Decrypt(rand.Reader, ct, nil, []byte("garbage")); err == nil {
+ if _, err = prv.Decrypt(ct, nil, []byte("garbage")); err == nil {
t.Fatal("ecies: decrypting with incorrect shared data didn't fail")
}
}
@@ -381,7 +381,7 @@ func testParamSelection(t *testing.T, c testCase) {
t.FailNow()
}
- pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
+ pt, err := prv2.Decrypt(ct, nil, nil)
if err != nil {
fmt.Printf("%s (%s)\n", err.Error(), c.Name)
t.FailNow()
@@ -393,7 +393,7 @@ func testParamSelection(t *testing.T, c testCase) {
t.FailNow()
}
- _, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
+ _, err = prv1.Decrypt(ct, nil, nil)
if err == nil {
fmt.Printf("ecies: encryption should not have succeeded (%s)\n",
c.Name)
@@ -422,7 +422,7 @@ func TestBasicKeyValidation(t *testing.T) {
for _, b := range badBytes {
ct[0] = b
- _, err := prv.Decrypt(rand.Reader, ct, nil, nil)
+ _, err := prv.Decrypt(ct, nil, nil)
if err != ErrInvalidPublicKey {
fmt.Println("ecies: validated an invalid key")
t.FailNow()
@@ -441,14 +441,14 @@ func TestBox(t *testing.T) {
t.Fatal(err)
}
- pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
+ pt, err := prv2.Decrypt(ct, nil, nil)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(pt, message) {
t.Fatal("ecies: plaintext doesn't match message")
}
- if _, err = prv1.Decrypt(rand.Reader, ct, nil, nil); err == nil {
+ if _, err = prv1.Decrypt(ct, nil, nil); err == nil {
t.Fatal("ecies: encryption should not have succeeded")
}
}
diff --git a/ethdb/database.go b/ethdb/database.go
index 8c557e482..30ed37dc7 100644
--- a/ethdb/database.go
+++ b/ethdb/database.go
@@ -29,6 +29,7 @@ import (
"github.com/syndtr/goleveldb/leveldb/filter"
"github.com/syndtr/goleveldb/leveldb/iterator"
"github.com/syndtr/goleveldb/leveldb/opt"
+ "github.com/syndtr/goleveldb/leveldb/util"
)
var OpenFileLimit = 64
@@ -121,6 +122,11 @@ func (db *LDBDatabase) NewIterator() iterator.Iterator {
return db.db.NewIterator(nil, nil)
}
+// NewIteratorWithPrefix returns a iterator to iterate over subset of database content with a particular prefix.
+func (db *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator {
+ return db.db.NewIterator(util.BytesPrefix(prefix), nil)
+}
+
func (db *LDBDatabase) Close() {
// Stop the metrics collection to avoid internal database races
db.quitLock.Lock()
diff --git a/p2p/rlpx.go b/p2p/rlpx.go
index 1889edac9..a320e81e7 100644
--- a/p2p/rlpx.go
+++ b/p2p/rlpx.go
@@ -491,7 +491,7 @@ func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r
}
// Attempt decoding pre-EIP-8 "plain" format.
key := ecies.ImportECDSA(prv)
- if dec, err := key.Decrypt(rand.Reader, buf, nil, nil); err == nil {
+ if dec, err := key.Decrypt(buf, nil, nil); err == nil {
msg.decodePlain(dec)
return buf, nil
}
@@ -505,7 +505,7 @@ func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r
if _, err := io.ReadFull(r, buf[plainSize:]); err != nil {
return buf, err
}
- dec, err := key.Decrypt(rand.Reader, buf[2:], nil, prefix)
+ dec, err := key.Decrypt(buf[2:], nil, prefix)
if err != nil {
return buf, err
}
diff --git a/rpc/http.go b/rpc/http.go
index 9805d69b6..e8f51150f 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -169,7 +169,8 @@ func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// All checks passed, create a codec that reads direct from the request body
// untilEOF and writes the response to w and order the server to process a
// single request.
- codec := NewJSONCodec(&httpReadWriteNopCloser{r.Body, w})
+ body := io.LimitReader(r.Body, maxRequestContentLength)
+ codec := NewJSONCodec(&httpReadWriteNopCloser{body, w})
defer codec.Close()
w.Header().Set("content-type", contentType)
diff --git a/whisper/whisperv5/message.go b/whisper/whisperv5/message.go
index c27535cd1..34ce52e64 100644
--- a/whisper/whisperv5/message.go
+++ b/whisper/whisperv5/message.go
@@ -277,7 +277,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, nonce []byte) error {
// decryptAsymmetric decrypts an encrypted payload with a private key.
func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
- decrypted, err := ecies.ImportECDSA(key).Decrypt(crand.Reader, msg.Raw, nil, nil)
+ decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil)
if err == nil {
msg.Raw = decrypted
}
diff --git a/whisper/whisperv6/message.go b/whisper/whisperv6/message.go
index b8318cbe8..2d4e86244 100644
--- a/whisper/whisperv6/message.go
+++ b/whisper/whisperv6/message.go
@@ -289,7 +289,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte) error {
// decryptAsymmetric decrypts an encrypted payload with a private key.
func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
- decrypted, err := ecies.ImportECDSA(key).Decrypt(crand.Reader, msg.Raw, nil, nil)
+ decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil)
if err == nil {
msg.Raw = decrypted
}