mirror of
https://github.com/status-im/status-go.git
synced 2025-02-23 20:28:27 +00:00
vendor: 1.5.6-stable (non-broken LES)
This commit is contained in:
parent
d959c87ae1
commit
4284b7743e
70
vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go
generated
vendored
70
vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go
generated
vendored
@ -91,8 +91,30 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
||||
// first we need to create a slice of the type
|
||||
var refSlice reflect.Value
|
||||
switch elem.T {
|
||||
case IntTy, UintTy, BoolTy: // int, uint, bool can all be of type big int.
|
||||
refSlice = reflect.ValueOf([]*big.Int(nil))
|
||||
case IntTy, UintTy, BoolTy:
|
||||
// create a new reference slice matching the element type
|
||||
switch t.Type.Kind {
|
||||
case reflect.Bool:
|
||||
refSlice = reflect.ValueOf([]bool(nil))
|
||||
case reflect.Uint8:
|
||||
refSlice = reflect.ValueOf([]uint8(nil))
|
||||
case reflect.Uint16:
|
||||
refSlice = reflect.ValueOf([]uint16(nil))
|
||||
case reflect.Uint32:
|
||||
refSlice = reflect.ValueOf([]uint32(nil))
|
||||
case reflect.Uint64:
|
||||
refSlice = reflect.ValueOf([]uint64(nil))
|
||||
case reflect.Int8:
|
||||
refSlice = reflect.ValueOf([]int8(nil))
|
||||
case reflect.Int16:
|
||||
refSlice = reflect.ValueOf([]int16(nil))
|
||||
case reflect.Int32:
|
||||
refSlice = reflect.ValueOf([]int32(nil))
|
||||
case reflect.Int64:
|
||||
refSlice = reflect.ValueOf([]int64(nil))
|
||||
default:
|
||||
refSlice = reflect.ValueOf([]*big.Int(nil))
|
||||
}
|
||||
case AddressTy: // address must be of slice Address
|
||||
refSlice = reflect.ValueOf([]common.Address(nil))
|
||||
case HashTy: // hash must be of slice hash
|
||||
@ -147,7 +169,27 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
||||
// set inter to the correct type (cast)
|
||||
switch elem.T {
|
||||
case IntTy, UintTy:
|
||||
inter = common.BytesToBig(returnOutput)
|
||||
bigNum := common.BytesToBig(returnOutput)
|
||||
switch t.Type.Kind {
|
||||
case reflect.Uint8:
|
||||
inter = uint8(bigNum.Uint64())
|
||||
case reflect.Uint16:
|
||||
inter = uint16(bigNum.Uint64())
|
||||
case reflect.Uint32:
|
||||
inter = uint32(bigNum.Uint64())
|
||||
case reflect.Uint64:
|
||||
inter = bigNum.Uint64()
|
||||
case reflect.Int8:
|
||||
inter = int8(bigNum.Int64())
|
||||
case reflect.Int16:
|
||||
inter = int16(bigNum.Int64())
|
||||
case reflect.Int32:
|
||||
inter = int32(bigNum.Int64())
|
||||
case reflect.Int64:
|
||||
inter = bigNum.Int64()
|
||||
default:
|
||||
inter = common.BytesToBig(returnOutput)
|
||||
}
|
||||
case BoolTy:
|
||||
inter = common.BytesToBig(returnOutput).Uint64() > 0
|
||||
case AddressTy:
|
||||
@ -169,7 +211,7 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
||||
// argument in T.
|
||||
func toGoType(i int, t Argument, output []byte) (interface{}, error) {
|
||||
// we need to treat slices differently
|
||||
if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy {
|
||||
if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy && t.Type.T != FunctionTy {
|
||||
return toGoSlice(i, t, output)
|
||||
}
|
||||
|
||||
@ -233,7 +275,7 @@ func toGoType(i int, t Argument, output []byte) (interface{}, error) {
|
||||
return common.BytesToAddress(returnOutput), nil
|
||||
case HashTy:
|
||||
return common.BytesToHash(returnOutput), nil
|
||||
case BytesTy, FixedBytesTy:
|
||||
case BytesTy, FixedBytesTy, FunctionTy:
|
||||
return returnOutput, nil
|
||||
case StringTy:
|
||||
return string(returnOutput), nil
|
||||
@ -345,12 +387,13 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
|
||||
|
||||
func (abi *ABI) UnmarshalJSON(data []byte) error {
|
||||
var fields []struct {
|
||||
Type string
|
||||
Name string
|
||||
Constant bool
|
||||
Indexed bool
|
||||
Inputs []Argument
|
||||
Outputs []Argument
|
||||
Type string
|
||||
Name string
|
||||
Constant bool
|
||||
Indexed bool
|
||||
Anonymous bool
|
||||
Inputs []Argument
|
||||
Outputs []Argument
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &fields); err != nil {
|
||||
@ -375,8 +418,9 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
case "event":
|
||||
abi.Events[field.Name] = Event{
|
||||
Name: field.Name,
|
||||
Inputs: field.Inputs,
|
||||
Name: field.Name,
|
||||
Anonymous: field.Anonymous,
|
||||
Inputs: field.Inputs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
6
vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go
generated
vendored
6
vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go
generated
vendored
@ -31,8 +31,9 @@ type Argument struct {
|
||||
|
||||
func (a *Argument) UnmarshalJSON(data []byte) error {
|
||||
var extarg struct {
|
||||
Name string
|
||||
Type string
|
||||
Name string
|
||||
Type string
|
||||
Indexed bool
|
||||
}
|
||||
err := json.Unmarshal(data, &extarg)
|
||||
if err != nil {
|
||||
@ -44,6 +45,7 @@ func (a *Argument) UnmarshalJSON(data []byte) error {
|
||||
return err
|
||||
}
|
||||
a.Name = extarg.Name
|
||||
a.Indexed = extarg.Indexed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/auth.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/auth.go
generated
vendored
@ -52,7 +52,7 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
|
||||
if address != keyAddr {
|
||||
return nil, errors.New("not authorized to sign this account")
|
||||
}
|
||||
signature, err := crypto.SignEthereum(signer.Hash(tx).Bytes(), key)
|
||||
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go
generated
vendored
@ -229,7 +229,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
||||
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain)
|
||||
// Create a new environment which holds all relevant information
|
||||
// about the transaction and calling mechanisms.
|
||||
vmenv := vm.NewEnvironment(evmContext, statedb, chainConfig, vm.Config{})
|
||||
vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{})
|
||||
gaspool := new(core.GasPool).AddGas(common.MaxBig)
|
||||
ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
|
||||
return ret, gasUsed, err
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go
generated
vendored
@ -170,7 +170,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
|
||||
if value == nil {
|
||||
value = new(big.Int)
|
||||
}
|
||||
nonce := uint64(0)
|
||||
var nonce uint64
|
||||
if opts.Nonce == nil {
|
||||
nonce, err = c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
|
||||
if err != nil {
|
||||
|
20
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go
generated
vendored
20
vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go
generated
vendored
@ -147,21 +147,21 @@ func bindTypeGo(kind abi.Type) string {
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(stringKind, "address"):
|
||||
parts := regexp.MustCompile("address(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 2 {
|
||||
return stringKind
|
||||
}
|
||||
return fmt.Sprintf("%scommon.Address", parts[1])
|
||||
|
||||
case strings.HasPrefix(stringKind, "bytes"):
|
||||
parts := regexp.MustCompile("bytes([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`bytes([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 3 {
|
||||
return stringKind
|
||||
}
|
||||
return fmt.Sprintf("%s[%s]byte", parts[2], parts[1])
|
||||
|
||||
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
|
||||
parts := regexp.MustCompile("(u)?int([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 4 {
|
||||
return stringKind
|
||||
}
|
||||
@ -172,7 +172,7 @@ func bindTypeGo(kind abi.Type) string {
|
||||
return fmt.Sprintf("%s*big.Int", parts[3])
|
||||
|
||||
case strings.HasPrefix(stringKind, "bool") || strings.HasPrefix(stringKind, "string"):
|
||||
parts := regexp.MustCompile("([a-z]+)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`([a-z]+)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 3 {
|
||||
return stringKind
|
||||
}
|
||||
@ -191,7 +191,7 @@ func bindTypeJava(kind abi.Type) string {
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(stringKind, "address"):
|
||||
parts := regexp.MustCompile("address(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 2 {
|
||||
return stringKind
|
||||
}
|
||||
@ -201,7 +201,7 @@ func bindTypeJava(kind abi.Type) string {
|
||||
return fmt.Sprintf("Addresses")
|
||||
|
||||
case strings.HasPrefix(stringKind, "bytes"):
|
||||
parts := regexp.MustCompile("bytes([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`bytes([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 3 {
|
||||
return stringKind
|
||||
}
|
||||
@ -211,7 +211,7 @@ func bindTypeJava(kind abi.Type) string {
|
||||
return "byte[]"
|
||||
|
||||
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
|
||||
parts := regexp.MustCompile("(u)?int([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 4 {
|
||||
return stringKind
|
||||
}
|
||||
@ -230,7 +230,7 @@ func bindTypeJava(kind abi.Type) string {
|
||||
return fmt.Sprintf("BigInts")
|
||||
|
||||
case strings.HasPrefix(stringKind, "bool"):
|
||||
parts := regexp.MustCompile("bool(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`bool(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 2 {
|
||||
return stringKind
|
||||
}
|
||||
@ -240,7 +240,7 @@ func bindTypeJava(kind abi.Type) string {
|
||||
return fmt.Sprintf("bool[]")
|
||||
|
||||
case strings.HasPrefix(stringKind, "string"):
|
||||
parts := regexp.MustCompile("string(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
|
||||
parts := regexp.MustCompile(`string(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
|
||||
if len(parts) != 2 {
|
||||
return stringKind
|
||||
}
|
||||
@ -278,7 +278,7 @@ func namedTypeJava(javaKind string, solKind abi.Type) string {
|
||||
case "bool[]":
|
||||
return "Bools"
|
||||
case "BigInt":
|
||||
parts := regexp.MustCompile("(u)?int([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(solKind.String())
|
||||
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
|
||||
if len(parts) != 4 {
|
||||
return javaKind
|
||||
}
|
||||
|
8
vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go
generated
vendored
8
vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go
generated
vendored
@ -25,10 +25,12 @@ import (
|
||||
)
|
||||
|
||||
// Event is an event potentially triggered by the EVM's LOG mechanism. The Event
|
||||
// holds type information (inputs) about the yielded output
|
||||
// holds type information (inputs) about the yielded output. Anonymous events
|
||||
// don't get the signature canonical representation as the first LOG topic.
|
||||
type Event struct {
|
||||
Name string
|
||||
Inputs []Argument
|
||||
Name string
|
||||
Anonymous bool
|
||||
Inputs []Argument
|
||||
}
|
||||
|
||||
// Id returns the canonical representation of the event's signature used by the
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/packing.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/accounts/abi/packing.go
generated
vendored
@ -54,7 +54,7 @@ func packElement(t Type, reflectValue reflect.Value) []byte {
|
||||
reflectValue = mustArrayToByteSlice(reflectValue)
|
||||
}
|
||||
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len())
|
||||
case FixedBytesTy:
|
||||
case FixedBytesTy, FunctionTy:
|
||||
if reflectValue.Kind() == reflect.Array {
|
||||
reflectValue = mustArrayToByteSlice(reflectValue)
|
||||
}
|
||||
|
37
vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go
generated
vendored
37
vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go
generated
vendored
@ -33,7 +33,8 @@ const (
|
||||
FixedBytesTy
|
||||
BytesTy
|
||||
HashTy
|
||||
RealTy
|
||||
FixedpointTy
|
||||
FunctionTy
|
||||
)
|
||||
|
||||
// Type is the reflection of the supported argument type
|
||||
@ -57,16 +58,16 @@ var (
|
||||
// Types can be in the format of:
|
||||
//
|
||||
// Input = Type [ "[" [ Number ] "]" ] Name .
|
||||
// Type = [ "u" ] "int" [ Number ] .
|
||||
// Type = [ "u" ] "int" [ Number ] [ x ] [ Number ].
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// string int uint real
|
||||
// string int uint fixed
|
||||
// string32 int8 uint8 uint[]
|
||||
// address int256 uint256 real[2]
|
||||
fullTypeRegex = regexp.MustCompile("([a-zA-Z0-9]+)(\\[([0-9]*)?\\])?")
|
||||
// address int256 uint256 fixed128x128[2]
|
||||
fullTypeRegex = regexp.MustCompile(`([a-zA-Z0-9]+)(\[([0-9]*)\])?`)
|
||||
// typeRegex parses the abi sub types
|
||||
typeRegex = regexp.MustCompile("([a-zA-Z]+)([0-9]*)?")
|
||||
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
|
||||
)
|
||||
|
||||
// NewType creates a new reflection type of abi type given in t.
|
||||
@ -90,14 +91,19 @@ func NewType(t string) (typ Type, err error) {
|
||||
}
|
||||
typ.Elem = &sliceType
|
||||
typ.stringKind = sliceType.stringKind + t[len(res[1]):]
|
||||
return typ, nil
|
||||
// Altough we know that this is an array, we cannot return
|
||||
// as we don't know the type of the element, however, if it
|
||||
// is still an array, then don't determine the type.
|
||||
if typ.Elem.IsArray || typ.Elem.IsSlice {
|
||||
return typ, nil
|
||||
}
|
||||
}
|
||||
|
||||
// parse the type and size of the abi-type.
|
||||
parsedType := typeRegex.FindAllStringSubmatch(res[1], -1)[0]
|
||||
// varSize is the size of the variable
|
||||
var varSize int
|
||||
if len(parsedType[2]) > 0 {
|
||||
if len(parsedType[3]) > 0 {
|
||||
var err error
|
||||
varSize, err = strconv.Atoi(parsedType[2])
|
||||
if err != nil {
|
||||
@ -111,7 +117,12 @@ func NewType(t string) (typ Type, err error) {
|
||||
varSize = 256
|
||||
t += "256"
|
||||
}
|
||||
typ.stringKind = t
|
||||
|
||||
// only set stringKind if not array or slice, as for those,
|
||||
// the correct string type has been set
|
||||
if !(typ.IsArray || typ.IsSlice) {
|
||||
typ.stringKind = t
|
||||
}
|
||||
|
||||
switch varType {
|
||||
case "int":
|
||||
@ -148,6 +159,12 @@ func NewType(t string) (typ Type, err error) {
|
||||
typ.T = FixedBytesTy
|
||||
typ.SliceSize = varSize
|
||||
}
|
||||
case "function":
|
||||
sliceType, _ := NewType("uint8")
|
||||
typ.Elem = &sliceType
|
||||
typ.IsArray = true
|
||||
typ.T = FunctionTy
|
||||
typ.SliceSize = 24
|
||||
default:
|
||||
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
|
||||
}
|
||||
@ -168,7 +185,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy {
|
||||
if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy && t.T != FunctionTy {
|
||||
var packed []byte
|
||||
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
|
32
vendor/github.com/ethereum/go-ethereum/accounts/account_manager.go
generated
vendored
32
vendor/github.com/ethereum/go-ethereum/accounts/account_manager.go
generated
vendored
@ -114,6 +114,7 @@ func (am *Manager) Accounts() []Account {
|
||||
return am.cache.accounts()
|
||||
}
|
||||
|
||||
// AccountDecryptedKey returns decrypted key for account (provided that password is correct).
|
||||
func (am *Manager) AccountDecryptedKey(a Account, auth string) (Account, *Key, error) {
|
||||
return am.getDecryptedKey(a, auth)
|
||||
}
|
||||
@ -141,13 +142,12 @@ func (am *Manager) DeleteAccount(a Account, passphrase string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sign calculates a ECDSA signature for the given hash.
|
||||
// Note, Ethereum signatures have a particular format as described in the
|
||||
// yellow paper. Use the SignEthereum function to calculate a signature
|
||||
// in Ethereum format.
|
||||
// Sign calculates a ECDSA signature for the given hash. The produced signature
|
||||
// is in the [R || S || V] format where V is 0 or 1.
|
||||
func (am *Manager) Sign(addr common.Address, hash []byte) ([]byte, error) {
|
||||
am.mu.RLock()
|
||||
defer am.mu.RUnlock()
|
||||
|
||||
unlockedKey, found := am.unlocked[addr]
|
||||
if !found {
|
||||
return nil, ErrLocked
|
||||
@ -155,28 +155,16 @@ func (am *Manager) Sign(addr common.Address, hash []byte) ([]byte, error) {
|
||||
return crypto.Sign(hash, unlockedKey.PrivateKey)
|
||||
}
|
||||
|
||||
// SignEthereum calculates a ECDSA signature for the given hash.
|
||||
// The signature has the format as described in the Ethereum yellow paper.
|
||||
func (am *Manager) SignEthereum(addr common.Address, hash []byte) ([]byte, error) {
|
||||
am.mu.RLock()
|
||||
defer am.mu.RUnlock()
|
||||
unlockedKey, found := am.unlocked[addr]
|
||||
if !found {
|
||||
return nil, ErrLocked
|
||||
}
|
||||
return crypto.SignEthereum(hash, unlockedKey.PrivateKey)
|
||||
}
|
||||
|
||||
// SignWithPassphrase signs hash if the private key matching the given
|
||||
// address can be decrypted with the given passphrase.
|
||||
func (am *Manager) SignWithPassphrase(addr common.Address, passphrase string, hash []byte) (signature []byte, err error) {
|
||||
_, key, err := am.getDecryptedKey(Account{Address: addr}, passphrase)
|
||||
// SignWithPassphrase signs hash if the private key matching the given address
|
||||
// can be decrypted with the given passphrase. The produced signature is in the
|
||||
// [R || S || V] format where V is 0 or 1.
|
||||
func (am *Manager) SignWithPassphrase(a Account, passphrase string, hash []byte) (signature []byte, err error) {
|
||||
_, key, err := am.getDecryptedKey(a, passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer zeroKey(key.PrivateKey)
|
||||
return crypto.SignEthereum(hash, key.PrivateKey)
|
||||
return crypto.Sign(hash, key.PrivateKey)
|
||||
}
|
||||
|
||||
// Unlock unlocks the given account indefinitely.
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/accounts/presale.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/accounts/presale.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
@ -53,6 +54,9 @@ func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error
|
||||
return nil, err
|
||||
}
|
||||
encSeedBytes, err := hex.DecodeString(preSaleKeyStruct.EncSeed)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid hex in encSeed")
|
||||
}
|
||||
iv := encSeedBytes[:16]
|
||||
cipherText := encSeedBytes[16:]
|
||||
/*
|
||||
|
161
vendor/github.com/ethereum/go-ethereum/cmd/bzzup/main.go
generated
vendored
161
vendor/github.com/ethereum/go-ethereum/cmd/bzzup/main.go
generated
vendored
@ -1,161 +0,0 @@
|
||||
// Copyright 2016 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Command bzzup uploads files to the swarm HTTP API.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
bzzapiFlag = flag.String("bzzapi", "http://127.0.0.1:8500", "Swarm HTTP endpoint")
|
||||
recursiveFlag = flag.Bool("recursive", false, "Upload directories recursively")
|
||||
manifestFlag = flag.Bool("manifest", true, "Skip automatic manifest upload")
|
||||
)
|
||||
log.SetOutput(os.Stderr)
|
||||
log.SetFlags(0)
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
log.Fatal("need filename as the first and only argument")
|
||||
}
|
||||
|
||||
var (
|
||||
file = flag.Arg(0)
|
||||
client = &client{api: *bzzapiFlag}
|
||||
mroot manifest
|
||||
)
|
||||
fi, err := os.Stat(file)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
if !*recursiveFlag {
|
||||
log.Fatal("argument is a directory and recursive upload is disabled")
|
||||
}
|
||||
mroot, err = client.uploadDirectory(file)
|
||||
} else {
|
||||
mroot, err = client.uploadFile(file, fi)
|
||||
if *manifestFlag {
|
||||
// Wrap the raw file entry in a proper manifest so both hashes get printed.
|
||||
mroot = manifest{Entries: []manifest{mroot}}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalln("upload failed:", err)
|
||||
}
|
||||
if *manifestFlag {
|
||||
hash, err := client.uploadManifest(mroot)
|
||||
if err != nil {
|
||||
log.Fatalln("manifest upload failed:", err)
|
||||
}
|
||||
mroot.Hash = hash
|
||||
}
|
||||
|
||||
// Print the manifest. This is the only output to stdout.
|
||||
mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
|
||||
fmt.Println(string(mrootJSON))
|
||||
}
|
||||
|
||||
// client wraps interaction with the swarm HTTP gateway.
|
||||
type client struct {
|
||||
api string
|
||||
}
|
||||
|
||||
// manifest is the JSON representation of a swarm manifest.
|
||||
type manifest struct {
|
||||
Hash string `json:"hash,omitempty"`
|
||||
ContentType string `json:"contentType,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Entries []manifest `json:"entries,omitempty"`
|
||||
}
|
||||
|
||||
func (c *client) uploadFile(file string, fi os.FileInfo) (manifest, error) {
|
||||
hash, err := c.uploadFileContent(file, fi)
|
||||
m := manifest{
|
||||
Hash: hash,
|
||||
ContentType: mime.TypeByExtension(filepath.Ext(fi.Name())),
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (c *client) uploadDirectory(dir string) (manifest, error) {
|
||||
dirm := manifest{}
|
||||
prefix := filepath.ToSlash(filepath.Clean(dir)) + "/"
|
||||
err := filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || fi.IsDir() {
|
||||
return err
|
||||
}
|
||||
if !strings.HasPrefix(path, dir) {
|
||||
return fmt.Errorf("path %s outside directory %s", path, dir)
|
||||
}
|
||||
entry, err := c.uploadFile(path, fi)
|
||||
entry.Path = strings.TrimPrefix(filepath.ToSlash(filepath.Clean(path)), prefix)
|
||||
dirm.Entries = append(dirm.Entries, entry)
|
||||
return err
|
||||
})
|
||||
return dirm, err
|
||||
}
|
||||
|
||||
func (c *client) uploadFileContent(file string, fi os.FileInfo) (string, error) {
|
||||
fd, err := os.Open(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
log.Printf("uploading file %s (%d bytes)", file, fi.Size())
|
||||
return c.postRaw("application/octet-stream", fi.Size(), fd)
|
||||
}
|
||||
|
||||
func (c *client) uploadManifest(m manifest) (string, error) {
|
||||
jsm, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Println("uploading manifest")
|
||||
return c.postRaw("application/json", int64(len(jsm)), ioutil.NopCloser(bytes.NewReader(jsm)))
|
||||
}
|
||||
|
||||
func (c *client) postRaw(mimetype string, size int64, body io.ReadCloser) (string, error) {
|
||||
req, err := http.NewRequest("POST", c.api+"/bzzr:/", body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("content-type", mimetype)
|
||||
req.ContentLength = size
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 400 {
|
||||
return "", fmt.Errorf("bad status: %s", resp.Status)
|
||||
}
|
||||
content, err := ioutil.ReadAll(resp.Body)
|
||||
return string(content), err
|
||||
}
|
21
vendor/github.com/ethereum/go-ethereum/cmd/disasm/main.go
generated
vendored
21
vendor/github.com/ethereum/go-ethereum/cmd/disasm/main.go
generated
vendored
@ -18,11 +18,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
)
|
||||
|
||||
@ -32,20 +33,28 @@ func main() {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
code = common.Hex2Bytes(string(code[:len(code)-1]))
|
||||
code, err = hex.DecodeString(strings.TrimSpace(string(code[:])))
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%x\n", code)
|
||||
|
||||
for pc := uint64(0); pc < uint64(len(code)); pc++ {
|
||||
op := vm.OpCode(code[pc])
|
||||
fmt.Printf("%-5d %v", pc, op)
|
||||
|
||||
switch op {
|
||||
case vm.PUSH1, vm.PUSH2, vm.PUSH3, vm.PUSH4, vm.PUSH5, vm.PUSH6, vm.PUSH7, vm.PUSH8, vm.PUSH9, vm.PUSH10, vm.PUSH11, vm.PUSH12, vm.PUSH13, vm.PUSH14, vm.PUSH15, vm.PUSH16, vm.PUSH17, vm.PUSH18, vm.PUSH19, vm.PUSH20, vm.PUSH21, vm.PUSH22, vm.PUSH23, vm.PUSH24, vm.PUSH25, vm.PUSH26, vm.PUSH27, vm.PUSH28, vm.PUSH29, vm.PUSH30, vm.PUSH31, vm.PUSH32:
|
||||
a := uint64(op) - uint64(vm.PUSH1) + 1
|
||||
fmt.Printf(" => %x", code[pc+1:pc+1+a])
|
||||
|
||||
u := pc + 1 + a
|
||||
if uint64(len(code)) <= pc || uint64(len(code)) < u {
|
||||
fmt.Printf("Error: incomplete push instruction at %v\n", pc)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%-5d %v => %x\n", pc, op, code[pc+1:u])
|
||||
pc += a
|
||||
default:
|
||||
fmt.Printf("%-5d %v\n", pc, op)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
21
vendor/github.com/ethereum/go-ethereum/cmd/evm/main.go
generated
vendored
21
vendor/github.com/ethereum/go-ethereum/cmd/evm/main.go
generated
vendored
@ -44,14 +44,6 @@ var (
|
||||
Name: "debug",
|
||||
Usage: "output full trace logs",
|
||||
}
|
||||
ForceJitFlag = cli.BoolFlag{
|
||||
Name: "forcejit",
|
||||
Usage: "forces jit compilation",
|
||||
}
|
||||
DisableJitFlag = cli.BoolFlag{
|
||||
Name: "nojit",
|
||||
Usage: "disabled jit compilation",
|
||||
}
|
||||
CodeFlag = cli.StringFlag{
|
||||
Name: "code",
|
||||
Usage: "EVM code",
|
||||
@ -95,6 +87,10 @@ var (
|
||||
Name: "create",
|
||||
Usage: "indicates the action should be create rather than call",
|
||||
}
|
||||
DisableGasMeteringFlag = cli.BoolFlag{
|
||||
Name: "nogasmetering",
|
||||
Usage: "disable gas metering",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -102,8 +98,6 @@ func init() {
|
||||
CreateFlag,
|
||||
DebugFlag,
|
||||
VerbosityFlag,
|
||||
ForceJitFlag,
|
||||
DisableJitFlag,
|
||||
SysStatFlag,
|
||||
CodeFlag,
|
||||
CodeFileFlag,
|
||||
@ -112,6 +106,7 @@ func init() {
|
||||
ValueFlag,
|
||||
DumpFlag,
|
||||
InputFlag,
|
||||
DisableGasMeteringFlag,
|
||||
}
|
||||
app.Action = run
|
||||
}
|
||||
@ -165,7 +160,8 @@ func run(ctx *cli.Context) error {
|
||||
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
|
||||
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||
EVMConfig: vm.Config{
|
||||
Tracer: logger,
|
||||
Tracer: logger,
|
||||
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
@ -179,7 +175,8 @@ func run(ctx *cli.Context) error {
|
||||
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
|
||||
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||
EVMConfig: vm.Config{
|
||||
Tracer: logger,
|
||||
Tracer: logger,
|
||||
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/cmd/geth/accountcmd.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/cmd/geth/accountcmd.go
generated
vendored
@ -214,7 +214,7 @@ func unlockAccount(ctx *cli.Context, accman *accounts.Manager, address string, i
|
||||
return accounts.Account{}, ""
|
||||
}
|
||||
|
||||
// getPassPhrase retrieves the password associated with an account, either fetched
|
||||
// getPassPhrase retrieves the passwor associated with an account, either fetched
|
||||
// from a list of preloaded passphrases, or requested interactively from the user.
|
||||
func getPassPhrase(prompt string, confirmation bool, i int, passwords []string) string {
|
||||
// If a list of passwords was supplied, retrieve from them
|
||||
|
24
vendor/github.com/ethereum/go-ethereum/cmd/geth/library.c
generated
vendored
24
vendor/github.com/ethereum/go-ethereum/cmd/geth/library.c
generated
vendored
@ -1,24 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Simple wrapper to translate the API exposed methods and types to inthernal
|
||||
// Go versions of the same types.
|
||||
|
||||
#include "_cgo_export.h"
|
||||
|
||||
int run(const char* args) {
|
||||
return doRun((char*)args);
|
||||
}
|
46
vendor/github.com/ethereum/go-ethereum/cmd/geth/library.go
generated
vendored
46
vendor/github.com/ethereum/go-ethereum/cmd/geth/library.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Contains a simple library definition to allow creating a Geth instance from
|
||||
// straight C code.
|
||||
|
||||
package main
|
||||
|
||||
// #ifdef __cplusplus
|
||||
// extern "C" {
|
||||
// #endif
|
||||
//
|
||||
// extern int run(const char*);
|
||||
//
|
||||
// #ifdef __cplusplus
|
||||
// }
|
||||
// #endif
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//export doRun
|
||||
func doRun(args *C.char) C.int {
|
||||
// This is equivalent to geth.main, just modified to handle the function arg passing
|
||||
if err := app.Run(strings.Split("geth "+C.GoString(args), " ")); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
56
vendor/github.com/ethereum/go-ethereum/cmd/geth/library_android.go
generated
vendored
56
vendor/github.com/ethereum/go-ethereum/cmd/geth/library_android.go
generated
vendored
@ -1,56 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Contains specialized code for running Geth on Android.
|
||||
|
||||
package main
|
||||
|
||||
// #include <android/log.h>
|
||||
// #cgo LDFLAGS: -llog
|
||||
import "C"
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Redirect the standard output and error to logcat
|
||||
oldStdout, oldStderr := os.Stdout, os.Stderr
|
||||
|
||||
outRead, outWrite, _ := os.Pipe()
|
||||
errRead, errWrite, _ := os.Pipe()
|
||||
|
||||
os.Stdout = outWrite
|
||||
os.Stderr = errWrite
|
||||
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(outRead)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
C.__android_log_write(C.ANDROID_LOG_INFO, C.CString("Stdout"), C.CString(line))
|
||||
oldStdout.WriteString(line + "\n")
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(errRead)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
C.__android_log_write(C.ANDROID_LOG_INFO, C.CString("Stderr"), C.CString(line))
|
||||
oldStderr.WriteString(line + "\n")
|
||||
}
|
||||
}()
|
||||
}
|
1
vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go
generated
vendored
1
vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go
generated
vendored
@ -168,7 +168,6 @@ func init() {
|
||||
}
|
||||
|
||||
app.After = func(ctx *cli.Context) error {
|
||||
logger.Flush()
|
||||
debug.Exit()
|
||||
console.Stdin.Close() // Resets terminal mode.
|
||||
return nil
|
||||
|
3
vendor/github.com/ethereum/go-ethereum/cmd/geth/monitorcmd.go
generated
vendored
3
vendor/github.com/ethereum/go-ethereum/cmd/geth/monitorcmd.go
generated
vendored
@ -236,8 +236,9 @@ func expandMetrics(metrics map[string]interface{}, path string) []string {
|
||||
|
||||
// fetchMetric iterates over the metrics map and retrieves a specific one.
|
||||
func fetchMetric(metrics map[string]interface{}, metric string) float64 {
|
||||
parts, found := strings.Split(metric, "/"), true
|
||||
parts := strings.Split(metric, "/")
|
||||
for _, part := range parts[:len(parts)-1] {
|
||||
var found bool
|
||||
metrics, found = metrics[part].(map[string]interface{})
|
||||
if !found {
|
||||
return 0
|
||||
|
@ -19,22 +19,21 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("Usage: bzzhash <file name>")
|
||||
os.Exit(0)
|
||||
func hash(ctx *cli.Context) {
|
||||
args := ctx.Args()
|
||||
if len(args) < 1 {
|
||||
log.Fatal("Usage: swarm hash <file name>")
|
||||
}
|
||||
f, err := os.Open(os.Args[1])
|
||||
f, err := os.Open(args[0])
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file " + os.Args[1])
|
||||
fmt.Println("Error opening file " + args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -42,7 +41,7 @@ func main() {
|
||||
chunker := storage.NewTreeChunker(storage.NewChunkerParams())
|
||||
key, err := chunker.Split(f, stat.Size(), nil, nil, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
log.Fatalf("%v\n", err)
|
||||
} else {
|
||||
fmt.Printf("%v\n", key)
|
||||
}
|
@ -43,11 +43,21 @@ import (
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
const clientIdentifier = "bzzd"
|
||||
const (
|
||||
clientIdentifier = "swarm"
|
||||
versionString = "0.2"
|
||||
)
|
||||
|
||||
var (
|
||||
gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
|
||||
app = utils.NewApp(gitCommit, "Ethereum Swarm server daemon")
|
||||
gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
|
||||
app = utils.NewApp(gitCommit, "Ethereum Swarm")
|
||||
testbetBootNodes = []string{
|
||||
"enode://ec8ae764f7cb0417bdfb009b9d0f18ab3818a3a4e8e7c67dd5f18971a93510a2e6f43cd0b69a27e439a9629457ea804104f37c85e41eed057d3faabbf7744cdf@13.74.157.139:30429",
|
||||
"enode://c2e1fceb3bf3be19dff71eec6cccf19f2dbf7567ee017d130240c670be8594bc9163353ca55dd8df7a4f161dd94b36d0615c17418b5a3cdcbb4e9d99dfa4de37@13.74.157.139:30430",
|
||||
"enode://fe29b82319b734ce1ec68b84657d57145fee237387e63273989d354486731e59f78858e452ef800a020559da22dcca759536e6aa5517c53930d29ce0b1029286@13.74.157.139:30431",
|
||||
"enode://1d7187e7bde45cf0bee489ce9852dd6d1a0d9aa67a33a6b8e6db8a4fbc6fcfa6f0f1a5419343671521b863b187d1c73bad3603bae66421d157ffef357669ddb8@13.74.157.139:30432",
|
||||
"enode://0e4cba800f7b1ee73673afa6a4acead4018f0149d2e3216be3f133318fd165b324cd71b81fbe1e80deac8dbf56e57a49db7be67f8b9bc81bd2b7ee496434fb5d@13.74.157.139:30433",
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
@ -65,30 +75,49 @@ var (
|
||||
}
|
||||
SwarmNetworkIdFlag = cli.IntFlag{
|
||||
Name: "bzznetworkid",
|
||||
Usage: "Network identifier (integer, default 322=swarm testnet)",
|
||||
Usage: "Network identifier (integer, default 3=swarm testnet)",
|
||||
Value: network.NetworkId,
|
||||
}
|
||||
SwarmConfigPathFlag = cli.StringFlag{
|
||||
Name: "bzzconfig",
|
||||
Usage: "Swarm config file path (datadir/bzz)",
|
||||
}
|
||||
SwarmSwapEnabled = cli.BoolFlag{
|
||||
SwarmSwapEnabledFlag = cli.BoolFlag{
|
||||
Name: "swap",
|
||||
Usage: "Swarm SWAP enabled (default false)",
|
||||
}
|
||||
SwarmSyncEnabled = cli.BoolTFlag{
|
||||
SwarmSyncEnabledFlag = cli.BoolTFlag{
|
||||
Name: "sync",
|
||||
Usage: "Swarm Syncing enabled (default true)",
|
||||
}
|
||||
EthAPI = cli.StringFlag{
|
||||
EthAPIFlag = cli.StringFlag{
|
||||
Name: "ethapi",
|
||||
Usage: "URL of the Ethereum API provider",
|
||||
Value: node.DefaultIPCEndpoint("geth"),
|
||||
}
|
||||
SwarmApiFlag = cli.StringFlag{
|
||||
Name: "bzzapi",
|
||||
Usage: "Swarm HTTP endpoint",
|
||||
Value: "http://127.0.0.1:8500",
|
||||
}
|
||||
SwarmRecursiveUploadFlag = cli.BoolFlag{
|
||||
Name: "recursive",
|
||||
Usage: "Upload directories recursively",
|
||||
}
|
||||
SwarmWantManifestFlag = cli.BoolTFlag{
|
||||
Name: "manifest",
|
||||
Usage: "Automatic manifest upload",
|
||||
}
|
||||
SwarmUploadDefaultPath = cli.StringFlag{
|
||||
Name: "defaultpath",
|
||||
Usage: "path to file served for empty url path (none)",
|
||||
}
|
||||
CorsStringFlag = cli.StringFlag{
|
||||
Name: "corsdomain",
|
||||
Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')",
|
||||
}
|
||||
)
|
||||
|
||||
var defaultBootnodes = []string{}
|
||||
|
||||
func init() {
|
||||
// Override flag defaults so bzzd can run alongside geth.
|
||||
utils.ListenPortFlag.Value = 30399
|
||||
@ -96,8 +125,39 @@ func init() {
|
||||
utils.IPCApiFlag.Value = "admin, bzz, chequebook, debug, rpc, web3"
|
||||
|
||||
// Set up the cli app.
|
||||
app.Commands = nil
|
||||
app.Action = bzzd
|
||||
app.HideVersion = true // we have a command to print the version
|
||||
app.Copyright = "Copyright 2013-2016 The go-ethereum Authors"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Action: version,
|
||||
Name: "version",
|
||||
Usage: "Print version numbers",
|
||||
ArgsUsage: " ",
|
||||
Description: `
|
||||
The output of this command is supposed to be machine-readable.
|
||||
`,
|
||||
},
|
||||
{
|
||||
Action: upload,
|
||||
Name: "up",
|
||||
Usage: "upload a file or directory to swarm using the HTTP API",
|
||||
ArgsUsage: " <file>",
|
||||
Description: `
|
||||
"upload a file or directory to swarm using the HTTP API and prints the root hash",
|
||||
`,
|
||||
},
|
||||
{
|
||||
Action: hash,
|
||||
Name: "hash",
|
||||
Usage: "print the swarm hash of a file or directory",
|
||||
ArgsUsage: " <file>",
|
||||
Description: `
|
||||
Prints the swarm hash of file or directory.
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
utils.IdentityFlag,
|
||||
utils.DataDirFlag,
|
||||
@ -115,14 +175,20 @@ func init() {
|
||||
utils.IPCApiFlag,
|
||||
utils.IPCPathFlag,
|
||||
// bzzd-specific flags
|
||||
EthAPI,
|
||||
CorsStringFlag,
|
||||
EthAPIFlag,
|
||||
SwarmConfigPathFlag,
|
||||
SwarmSwapEnabled,
|
||||
SwarmSyncEnabled,
|
||||
SwarmSwapEnabledFlag,
|
||||
SwarmSyncEnabledFlag,
|
||||
SwarmPortFlag,
|
||||
SwarmAccountFlag,
|
||||
SwarmNetworkIdFlag,
|
||||
ChequebookAddrFlag,
|
||||
// upload flags
|
||||
SwarmApiFlag,
|
||||
SwarmRecursiveUploadFlag,
|
||||
SwarmWantManifestFlag,
|
||||
SwarmUploadDefaultPath,
|
||||
}
|
||||
app.Flags = append(app.Flags, debug.Flags...)
|
||||
app.Before = func(ctx *cli.Context) error {
|
||||
@ -142,17 +208,33 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func version(ctx *cli.Context) error {
|
||||
fmt.Println(strings.Title(clientIdentifier))
|
||||
fmt.Println("Version:", versionString)
|
||||
if gitCommit != "" {
|
||||
fmt.Println("Git Commit:", gitCommit)
|
||||
}
|
||||
fmt.Println("Network Id:", ctx.GlobalInt(utils.NetworkIdFlag.Name))
|
||||
fmt.Println("Go Version:", runtime.Version())
|
||||
fmt.Println("OS:", runtime.GOOS)
|
||||
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
|
||||
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
|
||||
return nil
|
||||
}
|
||||
|
||||
func bzzd(ctx *cli.Context) error {
|
||||
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
|
||||
registerBzzService(ctx, stack)
|
||||
utils.StartNode(stack)
|
||||
|
||||
networkId := ctx.GlobalUint64(SwarmNetworkIdFlag.Name)
|
||||
// Add bootnodes as initial peers.
|
||||
if ctx.GlobalIsSet(utils.BootnodesFlag.Name) {
|
||||
bootnodes := strings.Split(ctx.GlobalString(utils.BootnodesFlag.Name), ",")
|
||||
injectBootnodes(stack.Server(), bootnodes)
|
||||
} else {
|
||||
injectBootnodes(stack.Server(), defaultBootnodes)
|
||||
if networkId == 3 {
|
||||
injectBootnodes(stack.Server(), testbetBootNodes)
|
||||
}
|
||||
}
|
||||
|
||||
stack.Wait()
|
||||
@ -175,22 +257,21 @@ func registerBzzService(ctx *cli.Context, stack *node.Node) {
|
||||
if len(bzzport) > 0 {
|
||||
bzzconfig.Port = bzzport
|
||||
}
|
||||
swapEnabled := ctx.GlobalBool(SwarmSwapEnabled.Name)
|
||||
syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabled.Name)
|
||||
swapEnabled := ctx.GlobalBool(SwarmSwapEnabledFlag.Name)
|
||||
syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name)
|
||||
|
||||
ethapi := ctx.GlobalString(EthAPI.Name)
|
||||
ethapi := ctx.GlobalString(EthAPIFlag.Name)
|
||||
cors := ctx.GlobalString(CorsStringFlag.Name)
|
||||
|
||||
boot := func(ctx *node.ServiceContext) (node.Service, error) {
|
||||
var client *ethclient.Client
|
||||
if ethapi == "" {
|
||||
err = fmt.Errorf("use ethapi flag to connect to a an eth client and talk to the blockchain")
|
||||
} else {
|
||||
if len(ethapi) > 0 {
|
||||
client, err = ethclient.Dial(ethapi)
|
||||
if err != nil {
|
||||
utils.Fatalf("Can't connect: %v", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
utils.Fatalf("Can't connect: %v", err)
|
||||
}
|
||||
return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled)
|
||||
return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled, cors)
|
||||
}
|
||||
if err := stack.Register(boot); err != nil {
|
||||
utils.Fatalf("Failed to register the Swarm service: %v", err)
|
231
vendor/github.com/ethereum/go-ethereum/cmd/swarm/upload.go
generated
vendored
Normal file
231
vendor/github.com/ethereum/go-ethereum/cmd/swarm/upload.go
generated
vendored
Normal file
@ -0,0 +1,231 @@
|
||||
// Copyright 2016 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Command bzzup uploads files to the swarm HTTP API.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
func upload(ctx *cli.Context) {
|
||||
args := ctx.Args()
|
||||
var (
|
||||
bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
|
||||
recursive = ctx.GlobalBool(SwarmRecursiveUploadFlag.Name)
|
||||
wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
|
||||
defaultPath = ctx.GlobalString(SwarmUploadDefaultPath.Name)
|
||||
)
|
||||
if len(args) != 1 {
|
||||
log.Fatal("need filename as the first and only argument")
|
||||
}
|
||||
|
||||
var (
|
||||
file = args[0]
|
||||
client = &client{api: bzzapi}
|
||||
)
|
||||
fi, err := os.Stat(expandPath(file))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
if !recursive {
|
||||
log.Fatal("argument is a directory and recursive upload is disabled")
|
||||
}
|
||||
if !wantManifest {
|
||||
log.Fatal("manifest is required for directory uploads")
|
||||
}
|
||||
mhash, err := client.uploadDirectory(file, defaultPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(mhash)
|
||||
return
|
||||
}
|
||||
entry, err := client.uploadFile(file, fi)
|
||||
if err != nil {
|
||||
log.Fatalln("upload failed:", err)
|
||||
}
|
||||
mroot := manifest{[]manifestEntry{entry}}
|
||||
if !wantManifest {
|
||||
// Print the manifest. This is the only output to stdout.
|
||||
mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
|
||||
fmt.Println(string(mrootJSON))
|
||||
return
|
||||
}
|
||||
hash, err := client.uploadManifest(mroot)
|
||||
if err != nil {
|
||||
log.Fatalln("manifest upload failed:", err)
|
||||
}
|
||||
fmt.Println(hash)
|
||||
}
|
||||
|
||||
// Expands a file path
|
||||
// 1. replace tilde with users home dir
|
||||
// 2. expands embedded environment variables
|
||||
// 3. cleans the path, e.g. /a/b/../c -> /a/c
|
||||
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
|
||||
func expandPath(p string) string {
|
||||
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
|
||||
if home := homeDir(); home != "" {
|
||||
p = home + p[1:]
|
||||
}
|
||||
}
|
||||
return path.Clean(os.ExpandEnv(p))
|
||||
}
|
||||
|
||||
func homeDir() string {
|
||||
if home := os.Getenv("HOME"); home != "" {
|
||||
return home
|
||||
}
|
||||
if usr, err := user.Current(); err == nil {
|
||||
return usr.HomeDir
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// client wraps interaction with the swarm HTTP gateway.
|
||||
type client struct {
|
||||
api string
|
||||
}
|
||||
|
||||
// manifest is the JSON representation of a swarm manifest.
|
||||
type manifestEntry struct {
|
||||
Hash string `json:"hash,omitempty"`
|
||||
ContentType string `json:"contentType,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// manifest is the JSON representation of a swarm manifest.
|
||||
type manifest struct {
|
||||
Entries []manifestEntry `json:"entries,omitempty"`
|
||||
}
|
||||
|
||||
func (c *client) uploadDirectory(dir string, defaultPath string) (string, error) {
|
||||
mhash, err := c.postRaw("application/json", 2, ioutil.NopCloser(bytes.NewReader([]byte("{}"))))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to upload empty manifest")
|
||||
}
|
||||
if len(defaultPath) > 0 {
|
||||
fi, err := os.Stat(defaultPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mhash, err = c.uploadToManifest(mhash, "", defaultPath, fi)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
prefix := filepath.ToSlash(filepath.Clean(dir)) + "/"
|
||||
err = filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || fi.IsDir() {
|
||||
return err
|
||||
}
|
||||
if !strings.HasPrefix(path, dir) {
|
||||
return fmt.Errorf("path %s outside directory %s", path, dir)
|
||||
}
|
||||
uripath := strings.TrimPrefix(filepath.ToSlash(filepath.Clean(path)), prefix)
|
||||
mhash, err = c.uploadToManifest(mhash, uripath, path, fi)
|
||||
return err
|
||||
})
|
||||
return mhash, err
|
||||
}
|
||||
|
||||
func (c *client) uploadFile(file string, fi os.FileInfo) (manifestEntry, error) {
|
||||
hash, err := c.uploadFileContent(file, fi)
|
||||
m := manifestEntry{
|
||||
Hash: hash,
|
||||
ContentType: mime.TypeByExtension(filepath.Ext(fi.Name())),
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (c *client) uploadFileContent(file string, fi os.FileInfo) (string, error) {
|
||||
fd, err := os.Open(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
log.Printf("uploading file %s (%d bytes)", file, fi.Size())
|
||||
return c.postRaw("application/octet-stream", fi.Size(), fd)
|
||||
}
|
||||
|
||||
func (c *client) uploadManifest(m manifest) (string, error) {
|
||||
jsm, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Println("uploading manifest")
|
||||
return c.postRaw("application/json", int64(len(jsm)), ioutil.NopCloser(bytes.NewReader(jsm)))
|
||||
}
|
||||
|
||||
func (c *client) uploadToManifest(mhash string, path string, fpath string, fi os.FileInfo) (string, error) {
|
||||
fd, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
log.Printf("uploading file %s (%d bytes) and adding path %v", fpath, fi.Size(), path)
|
||||
req, err := http.NewRequest("PUT", c.api+"/bzz:/"+mhash+"/"+path, fd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("content-type", mime.TypeByExtension(filepath.Ext(fi.Name())))
|
||||
req.ContentLength = fi.Size()
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 400 {
|
||||
return "", fmt.Errorf("bad status: %s", resp.Status)
|
||||
}
|
||||
content, err := ioutil.ReadAll(resp.Body)
|
||||
return string(content), err
|
||||
}
|
||||
|
||||
func (c *client) postRaw(mimetype string, size int64, body io.ReadCloser) (string, error) {
|
||||
req, err := http.NewRequest("POST", c.api+"/bzzr:/", body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("content-type", mimetype)
|
||||
req.ContentLength = size
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 400 {
|
||||
return "", fmt.Errorf("bad status: %s", resp.Status)
|
||||
}
|
||||
content, err := ioutil.ReadAll(resp.Body)
|
||||
return string(content), err
|
||||
}
|
34
vendor/github.com/ethereum/go-ethereum/cmd/utils/cmd.go
generated
vendored
34
vendor/github.com/ethereum/go-ethereum/cmd/utils/cmd.go
generated
vendored
@ -18,12 +18,14 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
@ -65,7 +67,6 @@ func Fatalf(format string, args ...interface{}) {
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "Fatal: "+format+"\n", args...)
|
||||
logger.Flush()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -93,7 +94,7 @@ func StartNode(stack *node.Node) {
|
||||
|
||||
func FormatTransactionData(data string) []byte {
|
||||
d := common.StringToByteFunc(data, func(s string) (ret []byte) {
|
||||
slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
|
||||
slice := regexp.MustCompile(`\n|\s`).Split(s, 1000000000)
|
||||
for _, dataItem := range slice {
|
||||
d := common.FormatData(dataItem)
|
||||
ret = append(ret, d...)
|
||||
@ -133,7 +134,15 @@ func ImportChain(chain *core.BlockChain, fn string) error {
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
stream := rlp.NewStream(fh, 0)
|
||||
|
||||
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)
|
||||
|
||||
// Run actual the import.
|
||||
blocks := make(types.Blocks, importBatchSize)
|
||||
@ -195,10 +204,18 @@ func ExportChain(blockchain *core.BlockChain, fn string) error {
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
if err := blockchain.Export(fh); err != nil {
|
||||
|
||||
var writer io.Writer = fh
|
||||
if strings.HasSuffix(fn, ".gz") {
|
||||
writer = gzip.NewWriter(writer)
|
||||
defer writer.(*gzip.Writer).Close()
|
||||
}
|
||||
|
||||
if err := blockchain.Export(writer); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infoln("Exported blockchain to ", fn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -210,7 +227,14 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
if err := blockchain.ExportN(fh, first, last); err != nil {
|
||||
|
||||
var writer io.Writer = fh
|
||||
if strings.HasSuffix(fn, ".gz") {
|
||||
writer = gzip.NewWriter(writer)
|
||||
defer writer.(*gzip.Writer).Close()
|
||||
}
|
||||
|
||||
if err := blockchain.ExportN(writer, first, last); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infoln("Exported blockchain to ", fn)
|
||||
|
7
vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go
generated
vendored
7
vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go
generated
vendored
@ -54,15 +54,10 @@ type DirectoryFlag struct {
|
||||
}
|
||||
|
||||
func (self DirectoryFlag) String() string {
|
||||
var fmtString string
|
||||
fmtString = "%s %v\t%v"
|
||||
|
||||
fmtString := "%s %v\t%v"
|
||||
if len(self.Value.Value) > 0 {
|
||||
fmtString = "%s \"%v\"\t%v"
|
||||
} else {
|
||||
fmtString = "%s %v\t%v"
|
||||
}
|
||||
|
||||
return withEnvHint(self.EnvVar, fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage))
|
||||
}
|
||||
|
||||
|
47
vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go
generated
vendored
47
vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go
generated
vendored
@ -39,7 +39,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/ethstats"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/internal/debug"
|
||||
"github.com/ethereum/go-ethereum/les"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
@ -338,10 +337,10 @@ var (
|
||||
Usage: "Network listening port",
|
||||
Value: 30303,
|
||||
}
|
||||
BootnodesFlag = cli.StringFlag{
|
||||
BootnodesFlag = cli.StringSliceFlag{
|
||||
Name: "bootnodes",
|
||||
Usage: "Comma separated enode URLs for P2P discovery bootstrap",
|
||||
Value: "",
|
||||
Value: nil,
|
||||
}
|
||||
NodeKeyFileFlag = cli.StringFlag{
|
||||
Name: "nodekey",
|
||||
@ -419,13 +418,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// DebugSetup sets up the debugging parameters such that logs can be retrieved when a
|
||||
// node is started via importing go-ethereum packages, as opposed to starting via CLI
|
||||
func DebugSetup(ctx *cli.Context) error {
|
||||
err := debug.Setup(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// MakeDataDir retrieves the currently requested data directory, terminating
|
||||
// if none (or the empty string) is specified. If the node is starting a testnet,
|
||||
// the a subdirectory of the specified datadir will be used.
|
||||
@ -493,17 +485,15 @@ func makeNodeUserIdent(ctx *cli.Context) string {
|
||||
// MakeBootstrapNodes creates a list of bootstrap nodes from the command line
|
||||
// flags, reverting to pre-configured ones if none have been specified.
|
||||
func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
|
||||
// Return pre-configured nodes if none were manually requested
|
||||
if !ctx.GlobalIsSet(BootnodesFlag.Name) {
|
||||
if ctx.GlobalBool(TestNetFlag.Name) {
|
||||
return params.TestnetBootnodes
|
||||
}
|
||||
return params.MainnetBootnodes
|
||||
urls := params.MainnetBootnodes
|
||||
if ctx.GlobalIsSet(BootnodesFlag.Name) {
|
||||
urls = ctx.GlobalStringSlice(BootnodesFlag.Name)
|
||||
} else if ctx.GlobalBool(TestNetFlag.Name) {
|
||||
urls = params.TestnetBootnodes
|
||||
}
|
||||
// Otherwise parse and use the CLI bootstrap nodes
|
||||
bootnodes := []*discover.Node{}
|
||||
|
||||
for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") {
|
||||
bootnodes := make([]*discover.Node, 0, len(urls))
|
||||
for _, url := range urls {
|
||||
node, err := discover.ParseNode(url)
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
|
||||
@ -517,14 +507,13 @@ func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
|
||||
// MakeBootstrapNodesV5 creates a list of bootstrap nodes from the command line
|
||||
// flags, reverting to pre-configured ones if none have been specified.
|
||||
func MakeBootstrapNodesV5(ctx *cli.Context) []*discv5.Node {
|
||||
// Return pre-configured nodes if none were manually requested
|
||||
if !ctx.GlobalIsSet(BootnodesFlag.Name) {
|
||||
return params.DiscoveryV5Bootnodes
|
||||
urls := params.DiscoveryV5Bootnodes
|
||||
if ctx.GlobalIsSet(BootnodesFlag.Name) {
|
||||
urls = ctx.GlobalStringSlice(BootnodesFlag.Name)
|
||||
}
|
||||
// Otherwise parse and use the CLI bootstrap nodes
|
||||
bootnodes := []*discv5.Node{}
|
||||
|
||||
for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") {
|
||||
bootnodes := make([]*discv5.Node, 0, len(urls))
|
||||
for _, url := range urls {
|
||||
node, err := discv5.ParseNode(url)
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
|
||||
@ -932,11 +921,19 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
|
||||
chainDb = MakeChainDatabase(ctx, stack)
|
||||
|
||||
if ctx.GlobalBool(OlympicFlag.Name) {
|
||||
_, err := core.WriteOlympicGenesisBlock(chainDb)
|
||||
if err != nil {
|
||||
glog.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(TestNetFlag.Name) {
|
||||
_, err := core.WriteTestNetGenesisBlock(chainDb)
|
||||
if err != nil {
|
||||
glog.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
chainConfig := MakeChainConfigFromDb(ctx, chainDb)
|
||||
|
||||
pow := pow.PoW(core.FakePow{})
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/common/bytes.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/common/bytes.go
generated
vendored
@ -143,7 +143,7 @@ func Hex2BytesFixed(str string, flen int) []byte {
|
||||
return h
|
||||
} else {
|
||||
if len(h) > flen {
|
||||
return h[len(h)-flen : len(h)]
|
||||
return h[len(h)-flen:]
|
||||
} else {
|
||||
hh := make([]byte, flen)
|
||||
copy(hh[flen-len(h):flen], h[:])
|
||||
|
32
vendor/github.com/ethereum/go-ethereum/common/compiler/solidity.go
generated
vendored
32
vendor/github.com/ethereum/go-ethereum/common/compiler/solidity.go
generated
vendored
@ -22,9 +22,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
@ -34,7 +32,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
versionRegexp = regexp.MustCompile("[0-9]+\\.[0-9]+\\.[0-9]+")
|
||||
versionRegexp = regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+`)
|
||||
solcParams = []string{
|
||||
"--combined-json", "bin,abi,userdoc,devdoc",
|
||||
"--add-std", // include standard lib contracts
|
||||
@ -96,27 +94,16 @@ func CompileSolidityString(solc, source string) (map[string]*Contract, error) {
|
||||
if solc == "" {
|
||||
solc = "solc"
|
||||
}
|
||||
// Write source to a temporary file. Compiling stdin used to be supported
|
||||
// but seems to produce an exception with solc 0.3.5.
|
||||
infile, err := ioutil.TempFile("", "geth-compile-solidity")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.Remove(infile.Name())
|
||||
if _, err := io.WriteString(infile, source); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := infile.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return CompileSolidity(solc, infile.Name())
|
||||
args := append(solcParams, "--")
|
||||
cmd := exec.Command(solc, append(args, "-")...)
|
||||
cmd.Stdin = strings.NewReader(source)
|
||||
return runsolc(cmd, source)
|
||||
}
|
||||
|
||||
// CompileSolidity compiles all given Solidity source files.
|
||||
func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, error) {
|
||||
if len(sourcefiles) == 0 {
|
||||
return nil, errors.New("solc: no source ")
|
||||
return nil, errors.New("solc: no source files")
|
||||
}
|
||||
source, err := slurpFiles(sourcefiles)
|
||||
if err != nil {
|
||||
@ -125,10 +112,13 @@ func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract,
|
||||
if solc == "" {
|
||||
solc = "solc"
|
||||
}
|
||||
|
||||
var stderr, stdout bytes.Buffer
|
||||
args := append(solcParams, "--")
|
||||
cmd := exec.Command(solc, append(args, sourcefiles...)...)
|
||||
return runsolc(cmd, source)
|
||||
}
|
||||
|
||||
func runsolc(cmd *exec.Cmd, source string) (map[string]*Contract, error) {
|
||||
var stderr, stdout bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
cmd.Stdout = &stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/common/format.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/common/format.go
generated
vendored
@ -27,7 +27,7 @@ import (
|
||||
// the unnecessary precision off from the formatted textual representation.
|
||||
type PrettyDuration time.Duration
|
||||
|
||||
var prettyDurationRe = regexp.MustCompile("\\.[0-9]+")
|
||||
var prettyDurationRe = regexp.MustCompile(`\.[0-9]+`)
|
||||
|
||||
// String implements the Stringer interface, allowing pretty printing of duration
|
||||
// values rounded to three decimals.
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/compression/rle/read_write.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/compression/rle/read_write.go
generated
vendored
@ -76,9 +76,9 @@ func compressChunk(dat []byte) (ret []byte, n int) {
|
||||
}
|
||||
return []byte{token, byte(j + 2)}, j
|
||||
case len(dat) >= 32:
|
||||
if dat[0] == empty[0] && bytes.Compare(dat[:32], empty) == 0 {
|
||||
if dat[0] == empty[0] && bytes.Equal(dat[:32], empty) {
|
||||
return []byte{token, emptyShaToken}, 32
|
||||
} else if dat[0] == emptyList[0] && bytes.Compare(dat[:32], emptyList) == 0 {
|
||||
} else if dat[0] == emptyList[0] && bytes.Equal(dat[:32], emptyList) {
|
||||
return []byte{token, emptyListShaToken}, 32
|
||||
}
|
||||
fallthrough
|
||||
|
25
vendor/github.com/ethereum/go-ethereum/console/bridge.go
generated
vendored
25
vendor/github.com/ethereum/go-ethereum/console/bridge.go
generated
vendored
@ -46,7 +46,7 @@ func newBridge(client *rpc.Client, prompter UserPrompter, printer io.Writer) *br
|
||||
}
|
||||
|
||||
// NewAccount is a wrapper around the personal.newAccount RPC method that uses a
|
||||
// non-echoing password prompt to aquire the passphrase and executes the original
|
||||
// non-echoing password prompt to acquire the passphrase and executes the original
|
||||
// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call.
|
||||
func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
|
||||
var (
|
||||
@ -75,7 +75,7 @@ func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
|
||||
default:
|
||||
throwJSException("expected 0 or 1 string argument")
|
||||
}
|
||||
// Password aquired, execute the call and return
|
||||
// Password acquired, execute the call and return
|
||||
ret, err := call.Otto.Call("jeth.newAccount", nil, password)
|
||||
if err != nil {
|
||||
throwJSException(err.Error())
|
||||
@ -84,7 +84,7 @@ func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
|
||||
}
|
||||
|
||||
// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
|
||||
// uses a non-echoing password prompt to aquire the passphrase and executes the
|
||||
// uses a non-echoing password prompt to acquire the passphrase and executes the
|
||||
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
|
||||
// the RPC call.
|
||||
func (b *bridge) UnlockAccount(call otto.FunctionCall) (response otto.Value) {
|
||||
@ -127,7 +127,7 @@ func (b *bridge) UnlockAccount(call otto.FunctionCall) (response otto.Value) {
|
||||
}
|
||||
|
||||
// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password
|
||||
// prompt to aquire the passphrase and executes the original RPC method (saved in
|
||||
// prompt to acquire the passphrase and executes the original RPC method (saved in
|
||||
// jeth.sign) with it to actually execute the RPC call.
|
||||
func (b *bridge) Sign(call otto.FunctionCall) (response otto.Value) {
|
||||
var (
|
||||
@ -270,18 +270,15 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) {
|
||||
} else {
|
||||
resultVal, err := JSON.Call("parse", string(result))
|
||||
if err != nil {
|
||||
resp = newErrorResponse(call, -32603, err.Error(), &req.Id).Object()
|
||||
setError(resp, -32603, err.Error())
|
||||
} else {
|
||||
resp.Set("result", resultVal)
|
||||
}
|
||||
}
|
||||
case rpc.Error:
|
||||
resp.Set("error", map[string]interface{}{
|
||||
"code": err.ErrorCode(),
|
||||
"message": err.Error(),
|
||||
})
|
||||
setError(resp, err.ErrorCode(), err.Error())
|
||||
default:
|
||||
resp = newErrorResponse(call, -32603, err.Error(), &req.Id).Object()
|
||||
setError(resp, -32603, err.Error())
|
||||
}
|
||||
resps.Call("push", resp)
|
||||
}
|
||||
@ -300,12 +297,8 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) {
|
||||
return response
|
||||
}
|
||||
|
||||
func newErrorResponse(call otto.FunctionCall, code int, msg string, id interface{}) otto.Value {
|
||||
// Bundle the error into a JSON RPC call response
|
||||
m := map[string]interface{}{"version": "2.0", "id": id, "error": map[string]interface{}{"code": code, msg: msg}}
|
||||
res, _ := json.Marshal(m)
|
||||
val, _ := call.Otto.Run("(" + string(res) + ")")
|
||||
return val
|
||||
func setError(resp *otto.Object, code int, msg string) {
|
||||
resp.Set("error", map[string]interface{}{"code": code, "message": msg})
|
||||
}
|
||||
|
||||
// throwJSException panics on an otto.Value. The Otto VM will recover from the
|
||||
|
15
vendor/github.com/ethereum/go-ethereum/console/console.go
generated
vendored
15
vendor/github.com/ethereum/go-ethereum/console/console.go
generated
vendored
@ -36,9 +36,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
passwordRegexp = regexp.MustCompile("personal.[nus]")
|
||||
onlyWhitespace = regexp.MustCompile("^\\s*$")
|
||||
exit = regexp.MustCompile("^\\s*exit\\s*;*\\s*$")
|
||||
passwordRegexp = regexp.MustCompile(`personal.[nus]`)
|
||||
onlyWhitespace = regexp.MustCompile(`^\s*$`)
|
||||
exit = regexp.MustCompile(`^\s*exit\s*;*\s*$`)
|
||||
)
|
||||
|
||||
// HistoryFile is the file within the data directory to store input scrollback.
|
||||
@ -226,8 +226,8 @@ func (c *Console) AutoCompleteInput(line string, pos int) (string, []string, str
|
||||
}
|
||||
// Chunck data to relevant part for autocompletion
|
||||
// E.g. in case of nested lines eth.getBalance(eth.coinb<tab><tab>
|
||||
start := 0
|
||||
for start = pos - 1; start > 0; start-- {
|
||||
start := pos - 1
|
||||
for ; start > 0; start-- {
|
||||
// Skip all methods and namespaces (i.e. including te dot)
|
||||
if line[start] == '.' || (line[start] >= 'a' && line[start] <= 'z') || (line[start] >= 'A' && line[start] <= 'Z') {
|
||||
continue
|
||||
@ -275,10 +275,7 @@ func (c *Console) Evaluate(statement string) error {
|
||||
fmt.Fprintf(c.printer, "[native] error: %v\n", r)
|
||||
}
|
||||
}()
|
||||
if err := c.jsre.Evaluate(statement, c.printer); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return c.jsre.Evaluate(statement, c.printer)
|
||||
}
|
||||
|
||||
// Interactive starts an interactive user session, where input is propted from
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/console/prompter.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/console/prompter.go
generated
vendored
@ -44,7 +44,7 @@ type UserPrompter interface {
|
||||
PromptConfirm(prompt string) (bool, error)
|
||||
|
||||
// SetHistory sets the the input scrollback history that the prompter will allow
|
||||
// the user to scoll back to.
|
||||
// the user to scroll back to.
|
||||
SetHistory(history []string)
|
||||
|
||||
// AppendHistory appends an entry to the scrollback history. It should be called
|
||||
@ -147,7 +147,7 @@ func (p *terminalPrompter) PromptConfirm(prompt string) (bool, error) {
|
||||
}
|
||||
|
||||
// SetHistory sets the the input scrollback history that the prompter will allow
|
||||
// the user to scoll back to.
|
||||
// the user to scroll back to.
|
||||
func (p *terminalPrompter) SetHistory(history []string) {
|
||||
p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n")))
|
||||
}
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/contracts/chequebook/cheque.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/contracts/chequebook/cheque.go
generated
vendored
@ -252,7 +252,7 @@ func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *
|
||||
return nil, fmt.Errorf("amount must be greater than zero (%v)", amount)
|
||||
}
|
||||
if self.balance.Cmp(amount) < 0 {
|
||||
err = fmt.Errorf("insufficent funds to issue cheque for amount: %v. balance: %v", amount, self.balance)
|
||||
err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, self.balance)
|
||||
} else {
|
||||
var sig []byte
|
||||
sent, found := self.sent[beneficiary]
|
||||
@ -277,7 +277,7 @@ func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *
|
||||
}
|
||||
|
||||
// auto deposit if threshold is set and balance is less then threshold
|
||||
// note this is called even if issueing cheque fails
|
||||
// note this is called even if issuing cheque fails
|
||||
// so we reattempt depositing
|
||||
if self.threshold != nil {
|
||||
if self.balance.Cmp(self.threshold) < 0 {
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/contracts/release/contract.sol
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/contracts/release/contract.sol
generated
vendored
@ -78,7 +78,7 @@ contract ReleaseOracle {
|
||||
}
|
||||
|
||||
// signers is an accessor method to retrieve all te signers (public accessor
|
||||
// generates an indexed one, not a retreive-all version).
|
||||
// generates an indexed one, not a retrieve-all version).
|
||||
function signers() constant returns(address[]) {
|
||||
return voters;
|
||||
}
|
||||
@ -178,7 +178,7 @@ contract ReleaseOracle {
|
||||
voters[i] = voters[voters.length - 1];
|
||||
voters.length--;
|
||||
|
||||
delete verProp; // Nuke any version proposal (no suprise releases!)
|
||||
delete verProp; // Nuke any version proposal (no surprise releases!)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
51
vendor/github.com/ethereum/go-ethereum/core/blockchain.go
generated
vendored
51
vendor/github.com/ethereum/go-ethereum/core/blockchain.go
generated
vendored
@ -46,9 +46,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
chainlogger = logger.NewLogger("CHAIN")
|
||||
jsonlogger = logger.NewJsonLogger()
|
||||
|
||||
blockInsertTimer = metrics.NewTimer("chain/inserts")
|
||||
|
||||
ErrNoGenesis = errors.New("Genesis not found in chain")
|
||||
@ -150,7 +147,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P
|
||||
return nil, err
|
||||
}
|
||||
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
|
||||
for hash, _ := range BadHashes {
|
||||
for hash := range BadHashes {
|
||||
if header := bc.GetHeaderByHash(hash); header != nil {
|
||||
// get the canonical block corresponding to the offending header's number
|
||||
headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64())
|
||||
@ -402,10 +399,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) {
|
||||
|
||||
// Export writes the active chain to the given writer.
|
||||
func (self *BlockChain) Export(w io.Writer) error {
|
||||
if err := self.ExportN(w, uint64(0), self.currentBlock.NumberU64()); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return self.ExportN(w, uint64(0), self.currentBlock.NumberU64())
|
||||
}
|
||||
|
||||
// ExportN writes a subset of the active chain to the given writer.
|
||||
@ -601,7 +595,11 @@ func (self *BlockChain) procFutureBlocks() {
|
||||
}
|
||||
if len(blocks) > 0 {
|
||||
types.BlockBy(types.Number).Sort(blocks)
|
||||
self.InsertChain(blocks)
|
||||
|
||||
// Insert one by one as chain insertion needs contiguous ancestry between blocks
|
||||
for i := range blocks {
|
||||
self.InsertChain(blocks[i : i+1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,6 +673,18 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty
|
||||
// transaction and receipt data.
|
||||
// XXX should this be moved to the test?
|
||||
func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
|
||||
// Do a sanity check that the provided chain is actually ordered and linked
|
||||
for i := 1; i < len(blockChain); i++ {
|
||||
if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() {
|
||||
// Chain broke ancestry, log a messge (programming error) and skip insertion
|
||||
failure := fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, blockChain[i-1].NumberU64(),
|
||||
blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4])
|
||||
|
||||
glog.V(logger.Error).Info(failure.Error())
|
||||
return 0, failure
|
||||
}
|
||||
}
|
||||
// Pre-checks passed, start the block body and receipt imports
|
||||
self.wg.Add(1)
|
||||
defer self.wg.Done()
|
||||
|
||||
@ -843,6 +853,18 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
|
||||
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
|
||||
// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
|
||||
func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||
// Do a sanity check that the provided chain is actually ordered and linked
|
||||
for i := 1; i < len(chain); i++ {
|
||||
if chain[i].NumberU64() != chain[i-1].NumberU64()+1 || chain[i].ParentHash() != chain[i-1].Hash() {
|
||||
// Chain broke ancestry, log a messge (programming error) and skip insertion
|
||||
failure := fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])",
|
||||
i-1, chain[i-1].NumberU64(), chain[i-1].Hash().Bytes()[:4], i, chain[i].NumberU64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash().Bytes()[:4])
|
||||
|
||||
glog.V(logger.Error).Info(failure.Error())
|
||||
return 0, failure
|
||||
}
|
||||
}
|
||||
// Pre-checks passed, start the full block imports
|
||||
self.wg.Add(1)
|
||||
defer self.wg.Done()
|
||||
|
||||
@ -855,7 +877,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||
var (
|
||||
stats = insertStats{startTime: time.Now()}
|
||||
events = make([]interface{}, 0, len(chain))
|
||||
coalescedLogs vm.Logs
|
||||
coalescedLogs []*types.Log
|
||||
nonceChecked = make([]bool, len(chain))
|
||||
)
|
||||
|
||||
@ -916,10 +938,8 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||
}
|
||||
|
||||
self.reportBlock(block, nil, err)
|
||||
|
||||
return i, err
|
||||
}
|
||||
|
||||
// Create a new statedb using the parent block and report an
|
||||
// error if it fails.
|
||||
switch {
|
||||
@ -1034,11 +1054,10 @@ func (st *insertStats) report(chain []*types.Block, index int) {
|
||||
start, end := chain[st.lastIndex], chain[index]
|
||||
txcount := countTransactions(chain[st.lastIndex : index+1])
|
||||
|
||||
extra := ""
|
||||
var hashes, extra string
|
||||
if st.queued > 0 || st.ignored > 0 {
|
||||
extra = fmt.Sprintf(" (%d queued %d ignored)", st.queued, st.ignored)
|
||||
}
|
||||
hashes := ""
|
||||
if st.processed > 1 {
|
||||
hashes = fmt.Sprintf("%x… / %x…", start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
|
||||
} else {
|
||||
@ -1068,7 +1087,7 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||
oldStart = oldBlock
|
||||
newStart = newBlock
|
||||
deletedTxs types.Transactions
|
||||
deletedLogs vm.Logs
|
||||
deletedLogs []*types.Log
|
||||
// collectLogs collects the logs that were generated during the
|
||||
// processing of the block that corresponds with the given hash.
|
||||
// These logs are later announced as deleted.
|
||||
@ -1184,7 +1203,7 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||
|
||||
// postChainEvents iterates over the events generated by a chain insertion and
|
||||
// posts them into the event mux.
|
||||
func (self *BlockChain) postChainEvents(events []interface{}, logs vm.Logs) {
|
||||
func (self *BlockChain) postChainEvents(events []interface{}, logs []*types.Log) {
|
||||
// post event logs for further processing
|
||||
self.eventMux.Post(logs)
|
||||
for _, event := range events {
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/core/chain_makers.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/core/chain_makers.go
generated
vendored
@ -108,7 +108,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
|
||||
b.SetCoinbase(common.Address{})
|
||||
}
|
||||
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
|
||||
receipt, _, _, err := ApplyTransaction(b.config, nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
|
||||
receipt, _, err := ApplyTransaction(b.config, nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/core/dao.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/core/dao.go
generated
vendored
@ -45,11 +45,11 @@ func ValidateDAOHeaderExtraData(config *params.ChainConfig, header *types.Header
|
||||
}
|
||||
// Depending whether we support or oppose the fork, validate the extra-data contents
|
||||
if config.DAOForkSupport {
|
||||
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) != 0 {
|
||||
if !bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
|
||||
return ValidationError("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
|
||||
}
|
||||
} else {
|
||||
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) == 0 {
|
||||
if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
|
||||
return ValidationError("DAO no-fork bad block extra-data: 0x%x", header.Extra)
|
||||
}
|
||||
}
|
||||
|
6
vendor/github.com/ethereum/go-ethereum/core/database_util.go
generated
vendored
6
vendor/github.com/ethereum/go-ethereum/core/database_util.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
@ -63,6 +64,8 @@ var (
|
||||
oldBlockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
|
||||
|
||||
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
|
||||
|
||||
mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
|
||||
)
|
||||
|
||||
// encodeBlockNumber encodes a block number as big endian uint64
|
||||
@ -564,6 +567,9 @@ func mipmapKey(num, level uint64) []byte {
|
||||
// WriteMapmapBloom writes each address included in the receipts' logs to the
|
||||
// MIP bloom bin.
|
||||
func WriteMipmapBloom(db ethdb.Database, number uint64, receipts types.Receipts) error {
|
||||
mipmapBloomMu.Lock()
|
||||
defer mipmapBloomMu.Unlock()
|
||||
|
||||
batch := db.NewBatch()
|
||||
for _, level := range MIPMapLevels {
|
||||
key := mipmapKey(number, level)
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/core/default_genesis.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/core/default_genesis.go
generated
vendored
File diff suppressed because one or more lines are too long
11
vendor/github.com/ethereum/go-ethereum/core/events.go
generated
vendored
11
vendor/github.com/ethereum/go-ethereum/core/events.go
generated
vendored
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
)
|
||||
|
||||
// TxPreEvent is posted when a transaction enters the transaction pool.
|
||||
@ -32,7 +31,7 @@ type TxPostEvent struct{ Tx *types.Transaction }
|
||||
|
||||
// PendingLogsEvent is posted pre mining and notifies of pending logs.
|
||||
type PendingLogsEvent struct {
|
||||
Logs vm.Logs
|
||||
Logs []*types.Log
|
||||
}
|
||||
|
||||
// PendingStateEvent is posted pre mining and notifies of pending state changes.
|
||||
@ -45,18 +44,18 @@ type NewMinedBlockEvent struct{ Block *types.Block }
|
||||
type RemovedTransactionEvent struct{ Txs types.Transactions }
|
||||
|
||||
// RemovedLogEvent is posted when a reorg happens
|
||||
type RemovedLogsEvent struct{ Logs vm.Logs }
|
||||
type RemovedLogsEvent struct{ Logs []*types.Log }
|
||||
|
||||
// ChainSplit is posted when a new head is detected
|
||||
type ChainSplitEvent struct {
|
||||
Block *types.Block
|
||||
Logs vm.Logs
|
||||
Logs []*types.Log
|
||||
}
|
||||
|
||||
type ChainEvent struct {
|
||||
Block *types.Block
|
||||
Hash common.Hash
|
||||
Logs vm.Logs
|
||||
Logs []*types.Log
|
||||
}
|
||||
|
||||
type ChainSideEvent struct {
|
||||
@ -65,7 +64,7 @@ type ChainSideEvent struct {
|
||||
|
||||
type PendingBlockEvent struct {
|
||||
Block *types.Block
|
||||
Logs vm.Logs
|
||||
Logs []*types.Log
|
||||
}
|
||||
|
||||
type ChainUncleEvent struct {
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/core/genesis.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/core/genesis.go
generated
vendored
@ -172,7 +172,7 @@ func WriteDefaultGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
|
||||
return WriteGenesisBlock(chainDb, strings.NewReader(DefaultGenesisBlock()))
|
||||
}
|
||||
|
||||
// WriteTestNetGenesisBlock assembles the Morden test network genesis block and
|
||||
// WriteTestNetGenesisBlock assembles the test network genesis block and
|
||||
// writes it - along with all associated state - into a chain database.
|
||||
func WriteTestNetGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
|
||||
return WriteGenesisBlock(chainDb, strings.NewReader(DefaultTestnetGenesisBlock()))
|
||||
@ -198,6 +198,8 @@ func DefaultGenesisBlock() string {
|
||||
return string(blob)
|
||||
}
|
||||
|
||||
// DefaultTestnetGenesisBlock assembles a JSON string representing the default Ethereum
|
||||
// test network genesis block.
|
||||
func DefaultTestnetGenesisBlock() string {
|
||||
reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultTestnetGenesisBlock)))
|
||||
blob, err := ioutil.ReadAll(reader)
|
||||
|
11
vendor/github.com/ethereum/go-ethereum/core/headerchain.go
generated
vendored
11
vendor/github.com/ethereum/go-ethereum/core/headerchain.go
generated
vendored
@ -224,6 +224,17 @@ type WhCallback func(*types.Header) error
|
||||
// of the header retrieval mechanisms already need to verfy nonces, as well as
|
||||
// because nonces can be verified sparsely, not needing to check each.
|
||||
func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, checkFreq int, writeHeader WhCallback) (int, error) {
|
||||
// Do a sanity check that the provided chain is actually ordered and linked
|
||||
for i := 1; i < len(chain); i++ {
|
||||
if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() {
|
||||
// Chain broke ancestry, log a messge (programming error) and skip insertion
|
||||
failure := fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])",
|
||||
i-1, chain[i-1].Number.Uint64(), chain[i-1].Hash().Bytes()[:4], i, chain[i].Number.Uint64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash.Bytes()[:4])
|
||||
|
||||
glog.V(logger.Error).Info(failure.Error())
|
||||
return 0, failure
|
||||
}
|
||||
}
|
||||
// Collect some import statistics to report on
|
||||
stats := struct{ processed, ignored int }{}
|
||||
start := time.Now()
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/core/state/iterator.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/core/state/iterator.go
generated
vendored
@ -123,7 +123,7 @@ func (it *NodeIterator) step() error {
|
||||
if !it.dataIt.Next() {
|
||||
it.dataIt = nil
|
||||
}
|
||||
if bytes.Compare(account.CodeHash, emptyCodeHash) != 0 {
|
||||
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
|
||||
it.codeHash = common.BytesToHash(account.CodeHash)
|
||||
it.code, err = it.state.db.Get(account.CodeHash)
|
||||
if err != nil {
|
||||
|
29
vendor/github.com/ethereum/go-ethereum/core/state/statedb.go
generated
vendored
29
vendor/github.com/ethereum/go-ethereum/core/state/statedb.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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"
|
||||
@ -71,7 +72,7 @@ type StateDB struct {
|
||||
|
||||
thash, bhash common.Hash
|
||||
txIndex int
|
||||
logs map[common.Hash]vm.Logs
|
||||
logs map[common.Hash][]*types.Log
|
||||
logSize uint
|
||||
|
||||
// Journal of state modifications. This is the backbone of
|
||||
@ -97,7 +98,7 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
||||
stateObjects: make(map[common.Address]*StateObject),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||
refund: new(big.Int),
|
||||
logs: make(map[common.Hash]vm.Logs),
|
||||
logs: make(map[common.Hash][]*types.Log),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -118,7 +119,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
||||
stateObjects: make(map[common.Address]*StateObject),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||
refund: new(big.Int),
|
||||
logs: make(map[common.Hash]vm.Logs),
|
||||
logs: make(map[common.Hash][]*types.Log),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -138,7 +139,7 @@ func (self *StateDB) Reset(root common.Hash) error {
|
||||
self.thash = common.Hash{}
|
||||
self.bhash = common.Hash{}
|
||||
self.txIndex = 0
|
||||
self.logs = make(map[common.Hash]vm.Logs)
|
||||
self.logs = make(map[common.Hash][]*types.Log)
|
||||
self.logSize = 0
|
||||
self.clearJournalAndRefund()
|
||||
|
||||
@ -175,7 +176,7 @@ func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
|
||||
self.txIndex = ti
|
||||
}
|
||||
|
||||
func (self *StateDB) AddLog(log *vm.Log) {
|
||||
func (self *StateDB) AddLog(log *types.Log) {
|
||||
self.journal = append(self.journal, addLogChange{txhash: self.thash})
|
||||
|
||||
log.TxHash = self.thash
|
||||
@ -186,12 +187,12 @@ func (self *StateDB) AddLog(log *vm.Log) {
|
||||
self.logSize++
|
||||
}
|
||||
|
||||
func (self *StateDB) GetLogs(hash common.Hash) vm.Logs {
|
||||
func (self *StateDB) GetLogs(hash common.Hash) []*types.Log {
|
||||
return self.logs[hash]
|
||||
}
|
||||
|
||||
func (self *StateDB) Logs() vm.Logs {
|
||||
var logs vm.Logs
|
||||
func (self *StateDB) Logs() []*types.Log {
|
||||
var logs []*types.Log
|
||||
for _, lgs := range self.logs {
|
||||
logs = append(logs, lgs...)
|
||||
}
|
||||
@ -209,7 +210,7 @@ func (self *StateDB) Exist(addr common.Address) bool {
|
||||
return self.GetStateObject(addr) != nil
|
||||
}
|
||||
|
||||
// Empty returns whether the state object is either non-existant
|
||||
// Empty returns whether the state object is either non-existent
|
||||
// or empty according to the EIP161 specification (balance = nonce = code = 0)
|
||||
func (self *StateDB) Empty(addr common.Address) bool {
|
||||
so := self.GetStateObject(addr)
|
||||
@ -474,16 +475,16 @@ func (self *StateDB) Copy() *StateDB {
|
||||
stateObjects: make(map[common.Address]*StateObject, len(self.stateObjectsDirty)),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
|
||||
refund: new(big.Int).Set(self.refund),
|
||||
logs: make(map[common.Hash]vm.Logs, len(self.logs)),
|
||||
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
|
||||
logSize: self.logSize,
|
||||
}
|
||||
// Copy the dirty states and logs
|
||||
for addr, _ := range self.stateObjectsDirty {
|
||||
for addr := range self.stateObjectsDirty {
|
||||
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
|
||||
state.stateObjectsDirty[addr] = struct{}{}
|
||||
}
|
||||
for hash, logs := range self.logs {
|
||||
state.logs[hash] = make(vm.Logs, len(logs))
|
||||
state.logs[hash] = make([]*types.Log, len(logs))
|
||||
copy(state.logs[hash], logs)
|
||||
}
|
||||
return state
|
||||
@ -529,7 +530,7 @@ func (self *StateDB) GetRefund() *big.Int {
|
||||
// It is called in between transactions to get the root hash that
|
||||
// goes into transaction receipts.
|
||||
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
for addr, _ := range s.stateObjectsDirty {
|
||||
for addr := range s.stateObjectsDirty {
|
||||
stateObject := s.stateObjects[addr]
|
||||
if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) {
|
||||
s.deleteStateObject(stateObject)
|
||||
@ -552,7 +553,7 @@ func (s *StateDB) DeleteSuicides() {
|
||||
// Reset refund so that any used-gas calculations can use this method.
|
||||
s.clearJournalAndRefund()
|
||||
|
||||
for addr, _ := range s.stateObjectsDirty {
|
||||
for addr := range s.stateObjectsDirty {
|
||||
stateObject := s.stateObjects[addr]
|
||||
|
||||
// If the object has been removed by a suicide
|
||||
|
7
vendor/github.com/ethereum/go-ethereum/core/state/sync.go
generated
vendored
7
vendor/github.com/ethereum/go-ethereum/core/state/sync.go
generated
vendored
@ -21,7 +21,6 @@ import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
@ -32,7 +31,7 @@ import (
|
||||
type StateSync trie.TrieSync
|
||||
|
||||
// NewStateSync create a new state trie download scheduler.
|
||||
func NewStateSync(root common.Hash, database ethdb.Database) *StateSync {
|
||||
func NewStateSync(root common.Hash, database trie.DatabaseReader) *StateSync {
|
||||
var syncer *trie.TrieSync
|
||||
|
||||
callback := func(leaf []byte, parent common.Hash) error {
|
||||
@ -62,8 +61,8 @@ func (s *StateSync) Missing(max int) []common.Hash {
|
||||
// Process injects a batch of retrieved trie nodes data, returning if something
|
||||
// was committed to the database and also the index of an entry if processing of
|
||||
// it failed.
|
||||
func (s *StateSync) Process(list []trie.SyncResult) (bool, int, error) {
|
||||
return (*trie.TrieSync)(s).Process(list)
|
||||
func (s *StateSync) Process(list []trie.SyncResult, dbw trie.DatabaseWriter) (bool, int, error) {
|
||||
return (*trie.TrieSync)(s).Process(list, dbw)
|
||||
}
|
||||
|
||||
// Pending returns the number of state entries currently pending for download.
|
||||
|
25
vendor/github.com/ethereum/go-ethereum/core/state_processor.go
generated
vendored
25
vendor/github.com/ethereum/go-ethereum/core/state_processor.go
generated
vendored
@ -57,13 +57,13 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain) *StateProcess
|
||||
// Process returns the receipts and logs accumulated during the process and
|
||||
// returns the amount of gas that was used in the process. If any of the
|
||||
// transactions failed to execute due to insufficient gas it will return an error.
|
||||
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
||||
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
|
||||
var (
|
||||
receipts types.Receipts
|
||||
totalUsedGas = big.NewInt(0)
|
||||
err error
|
||||
header = block.Header()
|
||||
allLogs vm.Logs
|
||||
allLogs []*types.Log
|
||||
gp = new(GasPool).AddGas(block.GasLimit())
|
||||
)
|
||||
// Mutate the the block and state according to any hard-fork specs
|
||||
@ -74,12 +74,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
for i, tx := range block.Transactions() {
|
||||
//fmt.Println("tx:", i)
|
||||
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
||||
receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
|
||||
receipt, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
receipts = append(receipts, receipt)
|
||||
allLogs = append(allLogs, logs...)
|
||||
allLogs = append(allLogs, receipt.Logs...)
|
||||
}
|
||||
AccumulateRewards(statedb, header, block.Uncles())
|
||||
|
||||
@ -87,24 +87,23 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
}
|
||||
|
||||
// ApplyTransaction attempts to apply a transaction to the given state database
|
||||
// and uses the input parameters for its environment.
|
||||
//
|
||||
// ApplyTransactions returns the generated receipts and vm logs during the
|
||||
// execution of the state transition phase.
|
||||
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
|
||||
// and uses the input parameters for its environment. It returns the receipt
|
||||
// for the transaction, gas used and an error if the transaction failed,
|
||||
// indicating the block was invalid.
|
||||
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, *big.Int, error) {
|
||||
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
// Create a new context to be used in the EVM environment
|
||||
context := NewEVMContext(msg, header, bc)
|
||||
// Create a new environment which holds all relevant information
|
||||
// about the transaction and calling mechanisms.
|
||||
vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{})
|
||||
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
|
||||
// Apply the transaction to the current state (included in the env)
|
||||
_, gas, err := ApplyMessage(vmenv, msg, gp)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Update the state with pending changes
|
||||
@ -125,7 +124,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, s
|
||||
|
||||
glog.V(logger.Debug).Infoln(receipt)
|
||||
|
||||
return receipt, receipt.Logs, gas, err
|
||||
return receipt, gas, err
|
||||
}
|
||||
|
||||
// AccumulateRewards credits the coinbase of the given block with the
|
||||
|
10
vendor/github.com/ethereum/go-ethereum/core/state_transition.go
generated
vendored
10
vendor/github.com/ethereum/go-ethereum/core/state_transition.go
generated
vendored
@ -57,7 +57,7 @@ type StateTransition struct {
|
||||
data []byte
|
||||
state vm.StateDB
|
||||
|
||||
env *vm.Environment
|
||||
env *vm.EVM
|
||||
}
|
||||
|
||||
// Message represents a message sent to a contract.
|
||||
@ -106,7 +106,7 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
|
||||
}
|
||||
|
||||
// NewStateTransition initialises and returns a new state transition object.
|
||||
func NewStateTransition(env *vm.Environment, msg Message, gp *GasPool) *StateTransition {
|
||||
func NewStateTransition(env *vm.EVM, msg Message, gp *GasPool) *StateTransition {
|
||||
return &StateTransition{
|
||||
gp: gp,
|
||||
env: env,
|
||||
@ -127,7 +127,7 @@ func NewStateTransition(env *vm.Environment, msg Message, gp *GasPool) *StateTra
|
||||
// the gas used (which includes gas refunds) and an error if it failed. An error always
|
||||
// indicates a core error meaning that the message would always fail for that particular
|
||||
// state and would never be accepted within a block.
|
||||
func ApplyMessage(env *vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
|
||||
func ApplyMessage(env *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
|
||||
st := NewStateTransition(env, msg, gp)
|
||||
|
||||
ret, _, gasUsed, err := st.TransitionDb()
|
||||
@ -159,7 +159,7 @@ func (self *StateTransition) to() vm.Account {
|
||||
|
||||
func (self *StateTransition) useGas(amount *big.Int) error {
|
||||
if self.gas.Cmp(amount) < 0 {
|
||||
return vm.OutOfGasError
|
||||
return vm.ErrOutOfGas
|
||||
}
|
||||
self.gas.Sub(self.gas, amount)
|
||||
|
||||
@ -233,7 +233,7 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
|
||||
)
|
||||
if contractCreation {
|
||||
ret, _, vmerr = vmenv.Create(sender, self.data, self.gas, self.value)
|
||||
if homestead && err == vm.CodeStoreOutOfGasError {
|
||||
if homestead && err == vm.ErrCodeStoreOutOfGas {
|
||||
self.gas = Big0
|
||||
}
|
||||
} else {
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/core/tx_list.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/core/tx_list.go
generated
vendored
@ -110,7 +110,7 @@ func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transac
|
||||
// If transactions were removed, the heap and cache are ruined
|
||||
if len(removed) > 0 {
|
||||
*m.index = make([]uint64, 0, len(m.items))
|
||||
for nonce, _ := range m.items {
|
||||
for nonce := range m.items {
|
||||
*m.index = append(*m.index, nonce)
|
||||
}
|
||||
heap.Init(m.index)
|
||||
@ -216,7 +216,7 @@ func (m *txSortedMap) Flatten() types.Transactions {
|
||||
// txList is a "list" of transactions belonging to an account, sorted by account
|
||||
// nonce. The same type can be used both for storing contiguous transactions for
|
||||
// the executable/pending queue; and for storing gapped transactions for the non-
|
||||
// executable/future queue, with minor behavoiral changes.
|
||||
// executable/future queue, with minor behavioral changes.
|
||||
type txList struct {
|
||||
strict bool // Whether nonces are strictly continuous or not
|
||||
txs *txSortedMap // Heap indexed sorted hash map of the transactions
|
||||
|
91
vendor/github.com/ethereum/go-ethereum/core/tx_pool.go
generated
vendored
91
vendor/github.com/ethereum/go-ethereum/core/tx_pool.go
generated
vendored
@ -37,15 +37,14 @@ import (
|
||||
|
||||
var (
|
||||
// Transaction Pool Errors
|
||||
ErrInvalidSender = errors.New("Invalid sender")
|
||||
ErrNonce = errors.New("Nonce too low")
|
||||
ErrCheap = errors.New("Gas price too low for acceptance")
|
||||
ErrBalance = errors.New("Insufficient balance")
|
||||
ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
|
||||
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
|
||||
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
|
||||
ErrGasLimit = errors.New("Exceeds block gas limit")
|
||||
ErrNegativeValue = errors.New("Negative value")
|
||||
ErrInvalidSender = errors.New("Invalid sender")
|
||||
ErrNonce = errors.New("Nonce too low")
|
||||
ErrCheap = errors.New("Gas price too low for acceptance")
|
||||
ErrBalance = errors.New("Insufficient balance")
|
||||
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
|
||||
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
|
||||
ErrGasLimit = errors.New("Exceeds block gas limit")
|
||||
ErrNegativeValue = errors.New("Negative value")
|
||||
)
|
||||
|
||||
var (
|
||||
@ -124,6 +123,8 @@ func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, currentState
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
|
||||
pool.resetState()
|
||||
|
||||
pool.wg.Add(2)
|
||||
go pool.eventLoop()
|
||||
go pool.expirationLoop()
|
||||
@ -176,7 +177,7 @@ func (pool *TxPool) resetState() {
|
||||
// any transactions that have been included in the block or
|
||||
// have been invalidated because of another transaction (e.g.
|
||||
// higher gas price)
|
||||
pool.demoteUnexecutables()
|
||||
pool.demoteUnexecutables(currentState)
|
||||
|
||||
// Update all accounts to the latest known pending nonce
|
||||
for addr, list := range pool.pending {
|
||||
@ -185,7 +186,7 @@ func (pool *TxPool) resetState() {
|
||||
}
|
||||
// Check the queue and move transactions over to the pending if possible
|
||||
// or remove those that have become invalid
|
||||
pool.promoteExecutables()
|
||||
pool.promoteExecutables(currentState)
|
||||
}
|
||||
|
||||
func (pool *TxPool) Stop() {
|
||||
@ -237,21 +238,26 @@ func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common
|
||||
// Pending retrieves all currently processable transactions, groupped by origin
|
||||
// account and sorted by nonce. The returned transaction set is a copy and can be
|
||||
// freely modified by calling code.
|
||||
func (pool *TxPool) Pending() map[common.Address]types.Transactions {
|
||||
func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) {
|
||||
pool.mu.Lock()
|
||||
defer pool.mu.Unlock()
|
||||
|
||||
state, err := pool.currentState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check queue first
|
||||
pool.promoteExecutables()
|
||||
pool.promoteExecutables(state)
|
||||
|
||||
// invalidate any txs
|
||||
pool.demoteUnexecutables()
|
||||
pool.demoteUnexecutables(state)
|
||||
|
||||
pending := make(map[common.Address]types.Transactions)
|
||||
for addr, list := range pool.pending {
|
||||
pending[addr] = list.Flatten()
|
||||
}
|
||||
return pending
|
||||
return pending, nil
|
||||
}
|
||||
|
||||
// SetLocal marks a transaction as local, skipping gas price
|
||||
@ -280,13 +286,6 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
||||
if err != nil {
|
||||
return ErrInvalidSender
|
||||
}
|
||||
|
||||
// Make sure the account exist. Non existent accounts
|
||||
// haven't got funds and well therefor never pass.
|
||||
if !currentState.Exist(from) {
|
||||
return ErrNonExistentAccount
|
||||
}
|
||||
|
||||
// Last but not least check for nonce errors
|
||||
if currentState.GetNonce(from) > tx.Nonce() {
|
||||
return ErrNonce
|
||||
@ -322,7 +321,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
||||
// add validates a transaction and inserts it into the non-executable queue for
|
||||
// later pending promotion and execution.
|
||||
func (pool *TxPool) add(tx *types.Transaction) error {
|
||||
// If the transaction is alreayd known, discard it
|
||||
// If the transaction is already known, discard it
|
||||
hash := tx.Hash()
|
||||
if pool.all[hash] != nil {
|
||||
return fmt.Errorf("Known transaction: %x", hash[:4])
|
||||
@ -372,10 +371,6 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) {
|
||||
//
|
||||
// Note, this method assumes the pool lock is held!
|
||||
func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) {
|
||||
// Init delayed since tx pool could have been started before any state sync
|
||||
if pool.pendingState == nil {
|
||||
pool.resetState()
|
||||
}
|
||||
// Try to insert the transaction into the pending queue
|
||||
if pool.pending[addr] == nil {
|
||||
pool.pending[addr] = newTxList(true)
|
||||
@ -410,13 +405,19 @@ func (pool *TxPool) Add(tx *types.Transaction) error {
|
||||
if err := pool.add(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
pool.promoteExecutables()
|
||||
|
||||
state, err := pool.currentState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool.promoteExecutables(state)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddBatch attempts to queue a batch of transactions.
|
||||
func (pool *TxPool) AddBatch(txs []*types.Transaction) {
|
||||
func (pool *TxPool) AddBatch(txs []*types.Transaction) error {
|
||||
pool.mu.Lock()
|
||||
defer pool.mu.Unlock()
|
||||
|
||||
@ -425,7 +426,15 @@ func (pool *TxPool) AddBatch(txs []*types.Transaction) {
|
||||
glog.V(logger.Debug).Infoln("tx error:", err)
|
||||
}
|
||||
}
|
||||
pool.promoteExecutables()
|
||||
|
||||
state, err := pool.currentState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool.promoteExecutables(state)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get returns a transaction if it is contained in the pool
|
||||
@ -499,17 +508,7 @@ func (pool *TxPool) removeTx(hash common.Hash) {
|
||||
// promoteExecutables moves transactions that have become processable from the
|
||||
// future queue to the set of pending transactions. During this process, all
|
||||
// invalidated transactions (low nonce, low balance) are deleted.
|
||||
func (pool *TxPool) promoteExecutables() {
|
||||
// Init delayed since tx pool could have been started before any state sync
|
||||
if pool.pendingState == nil {
|
||||
pool.resetState()
|
||||
}
|
||||
// Retrieve the current state to allow nonce and balance checking
|
||||
state, err := pool.currentState()
|
||||
if err != nil {
|
||||
glog.Errorf("Could not get current state: %v", err)
|
||||
return
|
||||
}
|
||||
func (pool *TxPool) promoteExecutables(state *state.StateDB) {
|
||||
// Iterate over all accounts and promote any executable transactions
|
||||
queued := uint64(0)
|
||||
for addr, list := range pool.queue {
|
||||
@ -610,7 +609,7 @@ func (pool *TxPool) promoteExecutables() {
|
||||
if queued > maxQueuedInTotal {
|
||||
// Sort all accounts with queued transactions by heartbeat
|
||||
addresses := make(addresssByHeartbeat, 0, len(pool.queue))
|
||||
for addr, _ := range pool.queue {
|
||||
for addr := range pool.queue {
|
||||
addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]})
|
||||
}
|
||||
sort.Sort(addresses)
|
||||
@ -645,13 +644,7 @@ func (pool *TxPool) promoteExecutables() {
|
||||
// demoteUnexecutables removes invalid and processed transactions from the pools
|
||||
// executable/pending queue and any subsequent transactions that become unexecutable
|
||||
// are moved back into the future queue.
|
||||
func (pool *TxPool) demoteUnexecutables() {
|
||||
// Retrieve the current state to allow nonce and balance checking
|
||||
state, err := pool.currentState()
|
||||
if err != nil {
|
||||
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
|
||||
return
|
||||
}
|
||||
func (pool *TxPool) demoteUnexecutables(state *state.StateDB) {
|
||||
// Iterate over all accounts and demote any non-executable transactions
|
||||
for addr, list := range pool.pending {
|
||||
nonce := state.GetNonce(addr)
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/core/types.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/core/types.go
generated
vendored
@ -58,5 +58,5 @@ type HeaderValidator interface {
|
||||
// of gas used in the process and return an error if any of the internal rules
|
||||
// failed.
|
||||
type Processor interface {
|
||||
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error)
|
||||
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error)
|
||||
}
|
||||
|
11
vendor/github.com/ethereum/go-ethereum/core/types/bloom9.go
generated
vendored
11
vendor/github.com/ethereum/go-ethereum/core/types/bloom9.go
generated
vendored
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
@ -95,17 +94,11 @@ func CreateBloom(receipts Receipts) Bloom {
|
||||
return BytesToBloom(bin.Bytes())
|
||||
}
|
||||
|
||||
func LogsBloom(logs vm.Logs) *big.Int {
|
||||
func LogsBloom(logs []*Log) *big.Int {
|
||||
bin := new(big.Int)
|
||||
for _, log := range logs {
|
||||
data := make([]common.Hash, len(log.Topics))
|
||||
bin.Or(bin, bloom9(log.Address.Bytes()))
|
||||
|
||||
for i, topic := range log.Topics {
|
||||
data[i] = topic
|
||||
}
|
||||
|
||||
for _, b := range data {
|
||||
for _, b := range log.Topics {
|
||||
bin.Or(bin, bloom9(b[:]))
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package vm
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -79,10 +79,6 @@ type jsonLog struct {
|
||||
Removed bool `json:"removed"`
|
||||
}
|
||||
|
||||
func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *Log {
|
||||
return &Log{Address: address, Topics: topics, Data: data, BlockNumber: number}
|
||||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (l *Log) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
|
||||
@ -150,8 +146,6 @@ func (l *Log) UnmarshalJSON(input []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Logs []*Log
|
||||
|
||||
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
|
||||
// a log including non-consensus fields.
|
||||
type LogForStorage Log
|
21
vendor/github.com/ethereum/go-ethereum/core/types/receipt.go
generated
vendored
21
vendor/github.com/ethereum/go-ethereum/core/types/receipt.go
generated
vendored
@ -25,7 +25,6 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
@ -40,7 +39,7 @@ type Receipt struct {
|
||||
PostState []byte
|
||||
CumulativeGasUsed *big.Int
|
||||
Bloom Bloom
|
||||
Logs vm.Logs
|
||||
Logs []*Log
|
||||
|
||||
// Implementation fields (don't reorder!)
|
||||
TxHash common.Hash
|
||||
@ -52,7 +51,7 @@ type jsonReceipt struct {
|
||||
PostState *common.Hash `json:"root"`
|
||||
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Logs *vm.Logs `json:"logs"`
|
||||
Logs []*Log `json:"logs"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
ContractAddress *common.Address `json:"contractAddress"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
@ -76,7 +75,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||
PostState []byte
|
||||
CumulativeGasUsed *big.Int
|
||||
Bloom Bloom
|
||||
Logs vm.Logs
|
||||
Logs []*Log
|
||||
}
|
||||
if err := s.Decode(&receipt); err != nil {
|
||||
return err
|
||||
@ -93,7 +92,7 @@ func (r *Receipt) MarshalJSON() ([]byte, error) {
|
||||
PostState: &root,
|
||||
CumulativeGasUsed: (*hexutil.Big)(r.CumulativeGasUsed),
|
||||
Bloom: &r.Bloom,
|
||||
Logs: &r.Logs,
|
||||
Logs: r.Logs,
|
||||
TxHash: &r.TxHash,
|
||||
ContractAddress: &r.ContractAddress,
|
||||
GasUsed: (*hexutil.Big)(r.GasUsed),
|
||||
@ -120,7 +119,7 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
|
||||
PostState: (*dec.PostState)[:],
|
||||
CumulativeGasUsed: (*big.Int)(dec.CumulativeGasUsed),
|
||||
Bloom: *dec.Bloom,
|
||||
Logs: *dec.Logs,
|
||||
Logs: dec.Logs,
|
||||
TxHash: *dec.TxHash,
|
||||
GasUsed: (*big.Int)(dec.GasUsed),
|
||||
}
|
||||
@ -142,9 +141,9 @@ type ReceiptForStorage Receipt
|
||||
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
|
||||
// into an RLP stream.
|
||||
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
||||
logs := make([]*vm.LogForStorage, len(r.Logs))
|
||||
logs := make([]*LogForStorage, len(r.Logs))
|
||||
for i, log := range r.Logs {
|
||||
logs[i] = (*vm.LogForStorage)(log)
|
||||
logs[i] = (*LogForStorage)(log)
|
||||
}
|
||||
return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed})
|
||||
}
|
||||
@ -158,7 +157,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||
Bloom Bloom
|
||||
TxHash common.Hash
|
||||
ContractAddress common.Address
|
||||
Logs []*vm.LogForStorage
|
||||
Logs []*LogForStorage
|
||||
GasUsed *big.Int
|
||||
}
|
||||
if err := s.Decode(&receipt); err != nil {
|
||||
@ -166,9 +165,9 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||
}
|
||||
// Assign the consensus fields
|
||||
r.PostState, r.CumulativeGasUsed, r.Bloom = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom
|
||||
r.Logs = make(vm.Logs, len(receipt.Logs))
|
||||
r.Logs = make([]*Log, len(receipt.Logs))
|
||||
for i, log := range receipt.Logs {
|
||||
r.Logs[i] = (*vm.Log)(log)
|
||||
r.Logs[i] = (*Log)(log)
|
||||
}
|
||||
// Assign the implementation fields
|
||||
r.TxHash, r.ContractAddress, r.GasUsed = receipt.TxHash, receipt.ContractAddress, receipt.GasUsed
|
||||
|
58
vendor/github.com/ethereum/go-ethereum/core/types/transaction.go
generated
vendored
58
vendor/github.com/ethereum/go-ethereum/core/types/transaction.go
generated
vendored
@ -18,7 +18,6 @@ package types
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -199,9 +198,9 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
|
||||
var V byte
|
||||
if isProtectedV((*big.Int)(dec.V)) {
|
||||
V = normaliseV(NewEIP155Signer(deriveChainId((*big.Int)(dec.V))), (*big.Int)(dec.V))
|
||||
V = byte((new(big.Int).Sub((*big.Int)(dec.V), deriveChainId((*big.Int)(dec.V))).Uint64()) - 35)
|
||||
} else {
|
||||
V = byte(((*big.Int)(dec.V)).Uint64())
|
||||
V = byte(((*big.Int)(dec.V)).Uint64() - 27)
|
||||
}
|
||||
if !crypto.ValidateSignatureValues(V, (*big.Int)(dec.R), (*big.Int)(dec.S), false) {
|
||||
return ErrInvalidSig
|
||||
@ -272,51 +271,6 @@ func (tx *Transaction) Size() common.StorageSize {
|
||||
return common.StorageSize(c)
|
||||
}
|
||||
|
||||
/*
|
||||
// From returns the address derived from the signature (V, R, S) using secp256k1
|
||||
// elliptic curve and an error if it failed deriving or upon an incorrect
|
||||
// signature.
|
||||
//
|
||||
// From Uses the homestead consensus rules to determine whether the signature is
|
||||
// valid.
|
||||
//
|
||||
// From caches the address, allowing it to be used regardless of
|
||||
// Frontier / Homestead. however, the first time called it runs
|
||||
// signature validations, so we need two versions. This makes it
|
||||
// easier to ensure backwards compatibility of things like package rpc
|
||||
// where eth_getblockbynumber uses tx.From() and needs to work for
|
||||
// both txs before and after the first homestead block. Signatures
|
||||
// valid in homestead are a subset of valid ones in Frontier)
|
||||
func (tx *Transaction) From() (common.Address, error) {
|
||||
if tx.signer == nil {
|
||||
return common.Address{}, errNoSigner
|
||||
}
|
||||
|
||||
if from := tx.from.Load(); from != nil {
|
||||
return from.(common.Address), nil
|
||||
}
|
||||
|
||||
pubkey, err := tx.signer.PublicKey(tx)
|
||||
if err != nil {
|
||||
return common.Address{}, err
|
||||
}
|
||||
var addr common.Address
|
||||
copy(addr[:], crypto.Keccak256(pubkey[1:])[12:])
|
||||
tx.from.Store(addr)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// SignatureValues returns the ECDSA signature values contained in the transaction.
|
||||
func (tx *Transaction) SignatureValues() (v byte, r *big.Int, s *big.Int, err error) {
|
||||
if tx.signer == nil {
|
||||
return 0, nil, nil,errNoSigner
|
||||
}
|
||||
|
||||
return normaliseV(tx.signer, tx.data.V), new(big.Int).Set(tx.data.R),new(big.Int).Set(tx.data.S), nil
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// AsMessage returns the transaction as a core.Message.
|
||||
//
|
||||
// AsMessage requires a signer to derive the sender.
|
||||
@ -338,14 +292,6 @@ func (tx *Transaction) AsMessage(s Signer) (Message, error) {
|
||||
return msg, err
|
||||
}
|
||||
|
||||
// SignECDSA signs the transaction using the given signer and private key
|
||||
//
|
||||
// XXX This only makes for a nice API: NewTx(...).SignECDSA(signer, prv). Should
|
||||
// we keep this?
|
||||
func (tx *Transaction) SignECDSA(signer Signer, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
return signer.SignECDSA(tx, prv)
|
||||
}
|
||||
|
||||
// WithSignature returns a new transaction with the given signature.
|
||||
// This signature needs to be formatted as described in the yellow paper (v+27).
|
||||
func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) {
|
||||
|
90
vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go
generated
vendored
90
vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go
generated
vendored
@ -50,10 +50,10 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||
return signer
|
||||
}
|
||||
|
||||
// SignECDSA signs the transaction using the given signer and private key
|
||||
func SignECDSA(s Signer, tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
// SignTx signs the transaction using the given signer and private key
|
||||
func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
h := s.Hash(tx)
|
||||
sig, err := crypto.SignEthereum(h[:], prv)
|
||||
sig, err := crypto.Sign(h[:], prv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -91,19 +91,13 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) {
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// SignatureValues returns the ECDSA signature values contained in the transaction.
|
||||
func SignatureValues(signer Signer, tx *Transaction) (v byte, r *big.Int, s *big.Int) {
|
||||
return normaliseV(signer, tx.data.V), new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
|
||||
}
|
||||
|
||||
type Signer interface {
|
||||
// Hash returns the rlp encoded hash for signatures
|
||||
Hash(tx *Transaction) common.Hash
|
||||
// PubilcKey returns the public key derived from the signature
|
||||
PublicKey(tx *Transaction) ([]byte, error)
|
||||
// SignECDSA signs the transaction with the given and returns a copy of the tx
|
||||
SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error)
|
||||
// WithSignature returns a copy of the transaction with the given signature
|
||||
// WithSignature returns a copy of the transaction with the given signature.
|
||||
// The signature must be encoded in [R || S || V] format where V is 0 or 1.
|
||||
WithSignature(tx *Transaction, sig []byte) (*Transaction, error)
|
||||
// Checks for equality on the signers
|
||||
Equal(Signer) bool
|
||||
@ -129,10 +123,6 @@ func (s EIP155Signer) Equal(s2 Signer) bool {
|
||||
return ok && eip155.chainId.Cmp(s.chainId) == 0
|
||||
}
|
||||
|
||||
func (s EIP155Signer) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
return SignECDSA(s, tx, prv)
|
||||
}
|
||||
|
||||
func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
// if the transaction is not protected fall back to homestead signer
|
||||
if !tx.Protected() {
|
||||
@ -143,17 +133,16 @@ func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
return nil, ErrInvalidChainId
|
||||
}
|
||||
|
||||
V := normaliseV(s, tx.data.V)
|
||||
V := byte(new(big.Int).Sub(tx.data.V, s.chainIdMul).Uint64() - 35)
|
||||
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) {
|
||||
return nil, ErrInvalidSig
|
||||
}
|
||||
|
||||
// encode the signature in uncompressed format
|
||||
R, S := tx.data.R.Bytes(), tx.data.S.Bytes()
|
||||
sig := make([]byte, 65)
|
||||
copy(sig[32-len(R):32], R)
|
||||
copy(sig[64-len(S):64], S)
|
||||
sig[64] = V - 27
|
||||
sig[64] = V
|
||||
|
||||
// recover the public key from the signature
|
||||
hash := s.Hash(tx)
|
||||
@ -167,8 +156,8 @@ func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
return pub, nil
|
||||
}
|
||||
|
||||
// WithSignature returns a new transaction with the given signature.
|
||||
// This signature needs to be formatted as described in the yellow paper (v+27).
|
||||
// WithSignature returns a new transaction with the given signature. This signature
|
||||
// needs to be in the [R || S || V] format where V is 0 or 1.
|
||||
func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
|
||||
if len(sig) != 65 {
|
||||
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
|
||||
@ -179,7 +168,7 @@ func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction,
|
||||
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
|
||||
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
|
||||
if s.chainId.BitLen() > 0 {
|
||||
cpy.data.V = big.NewInt(int64(sig[64] - 27 + 35))
|
||||
cpy.data.V = big.NewInt(int64(sig[64] + 35))
|
||||
cpy.data.V.Add(cpy.data.V, s.chainIdMul)
|
||||
}
|
||||
return cpy, nil
|
||||
@ -199,15 +188,6 @@ func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
|
||||
})
|
||||
}
|
||||
|
||||
func (s EIP155Signer) SigECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
h := s.Hash(tx)
|
||||
sig, err := crypto.SignEthereum(h[:], prv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.WithSignature(tx, sig)
|
||||
}
|
||||
|
||||
// HomesteadTransaction implements TransactionInterface using the
|
||||
// homestead rules.
|
||||
type HomesteadSigner struct{ FrontierSigner }
|
||||
@ -217,8 +197,8 @@ func (s HomesteadSigner) Equal(s2 Signer) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// WithSignature returns a new transaction with the given snature.
|
||||
// This snature needs to be formatted as described in the yellow paper (v+27).
|
||||
// WithSignature returns a new transaction with the given signature. This signature
|
||||
// needs to be in the [R || S || V] format where V is 0 or 1.
|
||||
func (hs HomesteadSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
|
||||
if len(sig) != 65 {
|
||||
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
|
||||
@ -226,24 +206,15 @@ func (hs HomesteadSigner) WithSignature(tx *Transaction, sig []byte) (*Transacti
|
||||
cpy := &Transaction{data: tx.data}
|
||||
cpy.data.R = new(big.Int).SetBytes(sig[:32])
|
||||
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
|
||||
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
|
||||
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64] + 27})
|
||||
return cpy, nil
|
||||
}
|
||||
|
||||
func (hs HomesteadSigner) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
h := hs.Hash(tx)
|
||||
sig, err := crypto.SignEthereum(h[:], prv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hs.WithSignature(tx, sig)
|
||||
}
|
||||
|
||||
func (hs HomesteadSigner) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
if tx.data.V.BitLen() > 8 {
|
||||
return nil, ErrInvalidSig
|
||||
}
|
||||
V := byte(tx.data.V.Uint64())
|
||||
V := byte(tx.data.V.Uint64() - 27)
|
||||
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) {
|
||||
return nil, ErrInvalidSig
|
||||
}
|
||||
@ -252,7 +223,7 @@ func (hs HomesteadSigner) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
sig := make([]byte, 65)
|
||||
copy(sig[32-len(r):32], r)
|
||||
copy(sig[64-len(s):64], s)
|
||||
sig[64] = V - 27
|
||||
sig[64] = V
|
||||
|
||||
// recover the public key from the snature
|
||||
hash := hs.Hash(tx)
|
||||
@ -273,8 +244,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// WithSignature returns a new transaction with the given snature.
|
||||
// This snature needs to be formatted as described in the yellow paper (v+27).
|
||||
// WithSignature returns a new transaction with the given signature. This signature
|
||||
// needs to be in the [R || S || V] format where V is 0 or 1.
|
||||
func (fs FrontierSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
|
||||
if len(sig) != 65 {
|
||||
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
|
||||
@ -282,19 +253,10 @@ func (fs FrontierSigner) WithSignature(tx *Transaction, sig []byte) (*Transactio
|
||||
cpy := &Transaction{data: tx.data}
|
||||
cpy.data.R = new(big.Int).SetBytes(sig[:32])
|
||||
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
|
||||
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
|
||||
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64] + 27})
|
||||
return cpy, nil
|
||||
}
|
||||
|
||||
func (fs FrontierSigner) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
|
||||
h := fs.Hash(tx)
|
||||
sig, err := crypto.SignEthereum(h[:], prv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fs.WithSignature(tx, sig)
|
||||
}
|
||||
|
||||
// Hash returns the hash to be sned by the sender.
|
||||
// It does not uniquely identify the transaction.
|
||||
func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
|
||||
@ -313,7 +275,7 @@ func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
return nil, ErrInvalidSig
|
||||
}
|
||||
|
||||
V := byte(tx.data.V.Uint64())
|
||||
V := byte(tx.data.V.Uint64() - 27)
|
||||
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, false) {
|
||||
return nil, ErrInvalidSig
|
||||
}
|
||||
@ -322,7 +284,7 @@ func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
sig := make([]byte, 65)
|
||||
copy(sig[32-len(r):32], r)
|
||||
copy(sig[64-len(s):64], s)
|
||||
sig[64] = V - 27
|
||||
sig[64] = V
|
||||
|
||||
// recover the public key from the snature
|
||||
hash := fs.Hash(tx)
|
||||
@ -336,18 +298,6 @@ func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
|
||||
return pub, nil
|
||||
}
|
||||
|
||||
// normaliseV returns the Ethereum version of the V parameter
|
||||
func normaliseV(s Signer, v *big.Int) byte {
|
||||
if s, ok := s.(EIP155Signer); ok {
|
||||
stdV := v.BitLen() <= 8 && (v.Uint64() == 27 || v.Uint64() == 28)
|
||||
if s.chainId.BitLen() > 0 && !stdV {
|
||||
nv := byte((new(big.Int).Sub(v, s.chainIdMul).Uint64()) - 35 + 27)
|
||||
return nv
|
||||
}
|
||||
}
|
||||
return byte(v.Uint64())
|
||||
}
|
||||
|
||||
// deriveChainId derives the chain id from the given v parameter
|
||||
func deriveChainId(v *big.Int) *big.Int {
|
||||
if v.BitLen() <= 64 {
|
||||
|
124
vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go
generated
vendored
124
vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go
generated
vendored
@ -26,84 +26,59 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// PrecompiledAccount represents a native ethereum contract
|
||||
type PrecompiledAccount struct {
|
||||
Gas func(l int) *big.Int
|
||||
fn func(in []byte) []byte
|
||||
}
|
||||
|
||||
// Call calls the native function
|
||||
func (self PrecompiledAccount) Call(in []byte) []byte {
|
||||
return self.fn(in)
|
||||
// Precompiled contract is the basic interface for native Go contracts. The implementation
|
||||
// requires a deterministic gas count based on the input size of the Run method of the
|
||||
// contract.
|
||||
type PrecompiledContract interface {
|
||||
RequiredGas(inputSize int) *big.Int // RequiredPrice calculates the contract gas use
|
||||
Run(input []byte) []byte // Run runs the precompiled contract
|
||||
}
|
||||
|
||||
// Precompiled contains the default set of ethereum contracts
|
||||
var Precompiled = PrecompiledContracts()
|
||||
var PrecompiledContracts = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
||||
common.BytesToAddress([]byte{2}): &sha256{},
|
||||
common.BytesToAddress([]byte{3}): &ripemd160{},
|
||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||
}
|
||||
|
||||
// PrecompiledContracts returns the default set of precompiled ethereum
|
||||
// contracts defined by the ethereum yellow paper.
|
||||
func PrecompiledContracts() map[string]*PrecompiledAccount {
|
||||
return map[string]*PrecompiledAccount{
|
||||
// ECRECOVER
|
||||
string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int {
|
||||
return params.EcrecoverGas
|
||||
}, ecrecoverFunc},
|
||||
// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
|
||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
|
||||
gas := p.RequiredGas(len(input))
|
||||
if contract.UseGas(gas) {
|
||||
ret = p.Run(input)
|
||||
|
||||
// SHA256
|
||||
string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int {
|
||||
n := big.NewInt(int64(l+31) / 32)
|
||||
n.Mul(n, params.Sha256WordGas)
|
||||
return n.Add(n, params.Sha256Gas)
|
||||
}, sha256Func},
|
||||
|
||||
// RIPEMD160
|
||||
string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int {
|
||||
n := big.NewInt(int64(l+31) / 32)
|
||||
n.Mul(n, params.Ripemd160WordGas)
|
||||
return n.Add(n, params.Ripemd160Gas)
|
||||
}, ripemd160Func},
|
||||
|
||||
string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int {
|
||||
n := big.NewInt(int64(l+31) / 32)
|
||||
n.Mul(n, params.IdentityWordGas)
|
||||
|
||||
return n.Add(n, params.IdentityGas)
|
||||
}, memCpy},
|
||||
return ret, nil
|
||||
} else {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
}
|
||||
|
||||
func sha256Func(in []byte) []byte {
|
||||
return crypto.Sha256(in)
|
||||
// ECRECOVER implemented as a native contract
|
||||
type ecrecover struct{}
|
||||
|
||||
func (c *ecrecover) RequiredGas(inputSize int) *big.Int {
|
||||
return params.EcrecoverGas
|
||||
}
|
||||
|
||||
func ripemd160Func(in []byte) []byte {
|
||||
return common.LeftPadBytes(crypto.Ripemd160(in), 32)
|
||||
}
|
||||
func (c *ecrecover) Run(in []byte) []byte {
|
||||
const ecRecoverInputLength = 128
|
||||
|
||||
const ecRecoverInputLength = 128
|
||||
|
||||
func ecrecoverFunc(in []byte) []byte {
|
||||
in = common.RightPadBytes(in, 128)
|
||||
in = common.RightPadBytes(in, ecRecoverInputLength)
|
||||
// "in" is (hash, v, r, s), each 32 bytes
|
||||
// but for ecrecover we want (r, s, v)
|
||||
|
||||
r := common.BytesToBig(in[64:96])
|
||||
s := common.BytesToBig(in[96:128])
|
||||
// Treat V as a 256bit integer
|
||||
vbig := common.Bytes2Big(in[32:64])
|
||||
v := byte(vbig.Uint64())
|
||||
v := in[63] - 27
|
||||
|
||||
// tighter sig s values in homestead only apply to tx sigs
|
||||
if !crypto.ValidateSignatureValues(v, r, s, false) {
|
||||
if common.Bytes2Big(in[32:63]).BitLen() > 0 || !crypto.ValidateSignatureValues(v, r, s, false) {
|
||||
glog.V(logger.Detail).Infof("ECRECOVER error: v, r or s value invalid")
|
||||
return nil
|
||||
}
|
||||
|
||||
// v needs to be at the end and normalized for libsecp256k1
|
||||
vbignormal := new(big.Int).Sub(vbig, big.NewInt(27))
|
||||
vnormal := byte(vbignormal.Uint64())
|
||||
rsv := append(in[64:128], vnormal)
|
||||
pubKey, err := crypto.Ecrecover(in[:32], rsv)
|
||||
// v needs to be at the end for libsecp256k1
|
||||
pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v))
|
||||
// make sure the public key is a valid one
|
||||
if err != nil {
|
||||
glog.V(logger.Detail).Infoln("ECRECOVER error: ", err)
|
||||
@ -114,6 +89,39 @@ func ecrecoverFunc(in []byte) []byte {
|
||||
return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32)
|
||||
}
|
||||
|
||||
func memCpy(in []byte) []byte {
|
||||
// SHA256 implemented as a native contract
|
||||
type sha256 struct{}
|
||||
|
||||
func (c *sha256) RequiredGas(inputSize int) *big.Int {
|
||||
n := big.NewInt(int64(inputSize+31) / 32)
|
||||
n.Mul(n, params.Sha256WordGas)
|
||||
return n.Add(n, params.Sha256Gas)
|
||||
}
|
||||
func (c *sha256) Run(in []byte) []byte {
|
||||
return crypto.Sha256(in)
|
||||
}
|
||||
|
||||
// RIPMED160 implemented as a native contract
|
||||
type ripemd160 struct{}
|
||||
|
||||
func (c *ripemd160) RequiredGas(inputSize int) *big.Int {
|
||||
n := big.NewInt(int64(inputSize+31) / 32)
|
||||
n.Mul(n, params.Ripemd160WordGas)
|
||||
return n.Add(n, params.Ripemd160Gas)
|
||||
}
|
||||
func (c *ripemd160) Run(in []byte) []byte {
|
||||
return common.LeftPadBytes(crypto.Ripemd160(in), 32)
|
||||
}
|
||||
|
||||
// data copy implemented as a native contract
|
||||
type dataCopy struct{}
|
||||
|
||||
func (c *dataCopy) RequiredGas(inputSize int) *big.Int {
|
||||
n := big.NewInt(int64(inputSize+31) / 32)
|
||||
n.Mul(n, params.IdentityWordGas)
|
||||
|
||||
return n.Add(n, params.IdentityGas)
|
||||
}
|
||||
func (c *dataCopy) Run(in []byte) []byte {
|
||||
return in
|
||||
}
|
||||
|
177
vendor/github.com/ethereum/go-ethereum/core/vm/environment.go
generated
vendored
177
vendor/github.com/ethereum/go-ethereum/core/vm/environment.go
generated
vendored
@ -19,6 +19,7 @@ package vm
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
@ -33,7 +34,7 @@ type (
|
||||
GetHashFunc func(uint64) common.Hash
|
||||
)
|
||||
|
||||
// Context provides the EVM with auxilary information. Once provided it shouldn't be modified.
|
||||
// Context provides the EVM with auxiliary information. Once provided it shouldn't be modified.
|
||||
type Context struct {
|
||||
// CanTransfer returns whether the account contains
|
||||
// sufficient ether to transfer the value
|
||||
@ -55,41 +56,54 @@ type Context struct {
|
||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||
}
|
||||
|
||||
// Environment provides information about external sources for the EVM
|
||||
// EVM provides information about external sources for the EVM
|
||||
//
|
||||
// The Environment should never be reused and is not thread safe.
|
||||
type Environment struct {
|
||||
// The EVM should never be reused and is not thread safe.
|
||||
type EVM struct {
|
||||
// Context provides auxiliary blockchain related information
|
||||
Context
|
||||
// StateDB gives access to the underlying state
|
||||
StateDB StateDB
|
||||
// Depth is the current call stack
|
||||
Depth int
|
||||
depth int
|
||||
|
||||
// evm is the ethereum virtual machine
|
||||
evm Vm
|
||||
// chainConfig contains information about the current chain
|
||||
chainConfig *params.ChainConfig
|
||||
vmConfig Config
|
||||
// virtual machine configuration options used to initialise the
|
||||
// evm.
|
||||
vmConfig Config
|
||||
// global (to this context) ethereum virtual machine
|
||||
// used throughout the execution of the tx.
|
||||
interpreter *Interpreter
|
||||
// abort is used to abort the EVM calling operations
|
||||
// NOTE: must be set atomically
|
||||
abort int32
|
||||
}
|
||||
|
||||
// NewEnvironment retutrns a new EVM environment.
|
||||
func NewEnvironment(context Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *Environment {
|
||||
env := &Environment{
|
||||
Context: context,
|
||||
// NewEVM retutrns a new EVM evmironment.
|
||||
func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
|
||||
evm := &EVM{
|
||||
Context: ctx,
|
||||
StateDB: statedb,
|
||||
vmConfig: vmConfig,
|
||||
chainConfig: chainConfig,
|
||||
}
|
||||
env.evm = New(env, vmConfig)
|
||||
return env
|
||||
|
||||
evm.interpreter = NewInterpreter(evm, vmConfig)
|
||||
return evm
|
||||
}
|
||||
|
||||
// Call executes the contract associated with the addr with the given input as paramaters. It also handles any
|
||||
// Cancel cancels any running EVM operation. This may be called concurrently and it's safe to be
|
||||
// called multiple times.
|
||||
func (evm *EVM) Cancel() {
|
||||
atomic.StoreInt32(&evm.abort, 1)
|
||||
}
|
||||
|
||||
// Call executes the contract associated with the addr with the given input as parameters. It also handles any
|
||||
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
|
||||
// case of an execution error or failed value transfer.
|
||||
func (env *Environment) Call(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) {
|
||||
if env.vmConfig.NoRecursion && env.Depth > 0 {
|
||||
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) (ret []byte, err error) {
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, nil
|
||||
@ -97,59 +111,59 @@ func (env *Environment) Call(caller ContractRef, addr common.Address, input []by
|
||||
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if env.Depth > int(params.CallCreateDepth.Int64()) {
|
||||
if evm.depth > int(params.CallCreateDepth.Int64()) {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, DepthError
|
||||
return nil, ErrDepth
|
||||
}
|
||||
if !env.Context.CanTransfer(env.StateDB, caller.Address(), value) {
|
||||
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, ErrInsufficientBalance
|
||||
}
|
||||
|
||||
var (
|
||||
to Account
|
||||
snapshotPreTransfer = env.StateDB.Snapshot()
|
||||
to Account
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
)
|
||||
if !env.StateDB.Exist(addr) {
|
||||
if Precompiled[addr.Str()] == nil && env.ChainConfig().IsEIP158(env.BlockNumber) && value.BitLen() == 0 {
|
||||
if !evm.StateDB.Exist(addr) {
|
||||
if PrecompiledContracts[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.BitLen() == 0 {
|
||||
caller.ReturnGas(gas)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
to = env.StateDB.CreateAccount(addr)
|
||||
to = evm.StateDB.CreateAccount(addr)
|
||||
} else {
|
||||
to = env.StateDB.GetAccount(addr)
|
||||
to = evm.StateDB.GetAccount(addr)
|
||||
}
|
||||
env.Transfer(env.StateDB, caller.Address(), to.Address(), value)
|
||||
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||
|
||||
// initialise a new contract and set the code that is to be used by the
|
||||
// E The contract is a scoped environment for this execution context
|
||||
// E The contract is a scoped evmironment for this execution context
|
||||
// only.
|
||||
contract := NewContract(caller, to, value, gas)
|
||||
contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
defer contract.Finalise()
|
||||
|
||||
ret, err := env.EVM().Run(contract, input)
|
||||
ret, err = evm.interpreter.Run(contract, input)
|
||||
// When an error was returned by the EVM or when setting the creation code
|
||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||
// when we're in homestead this also counts for code storage gas errors.
|
||||
if err != nil {
|
||||
contract.UseGas(contract.Gas)
|
||||
|
||||
env.StateDB.RevertToSnapshot(snapshotPreTransfer)
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// CallCode executes the contract associated with the addr with the given input as paramaters. It also handles any
|
||||
// CallCode executes the contract associated with the addr with the given input as parameters. It also handles any
|
||||
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
|
||||
// case of an execution error or failed value transfer.
|
||||
//
|
||||
// CallCode differs from Call in the sense that it executes the given address' code with the caller as context.
|
||||
func (env *Environment) CallCode(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) {
|
||||
if env.vmConfig.NoRecursion && env.Depth > 0 {
|
||||
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) (ret []byte, err error) {
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, nil
|
||||
@ -157,45 +171,45 @@ func (env *Environment) CallCode(caller ContractRef, addr common.Address, input
|
||||
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if env.Depth > int(params.CallCreateDepth.Int64()) {
|
||||
if evm.depth > int(params.CallCreateDepth.Int64()) {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, DepthError
|
||||
return nil, ErrDepth
|
||||
}
|
||||
if !env.CanTransfer(env.StateDB, caller.Address(), value) {
|
||||
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, fmt.Errorf("insufficient funds to transfer value. Req %v, has %v", value, env.StateDB.GetBalance(caller.Address()))
|
||||
return nil, fmt.Errorf("insufficient funds to transfer value. Req %v, has %v", value, evm.StateDB.GetBalance(caller.Address()))
|
||||
}
|
||||
|
||||
var (
|
||||
snapshotPreTransfer = env.StateDB.Snapshot()
|
||||
to = env.StateDB.GetAccount(caller.Address())
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
to = evm.StateDB.GetAccount(caller.Address())
|
||||
)
|
||||
// initialise a new contract and set the code that is to be used by the
|
||||
// E The contract is a scoped environment for this execution context
|
||||
// E The contract is a scoped evmironment for this execution context
|
||||
// only.
|
||||
contract := NewContract(caller, to, value, gas)
|
||||
contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
defer contract.Finalise()
|
||||
|
||||
ret, err := env.EVM().Run(contract, input)
|
||||
ret, err = evm.interpreter.Run(contract, input)
|
||||
if err != nil {
|
||||
contract.UseGas(contract.Gas)
|
||||
|
||||
env.StateDB.RevertToSnapshot(snapshotPreTransfer)
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
}
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// DelegateCall executes the contract associated with the addr with the given input as paramaters.
|
||||
// DelegateCall executes the contract associated with the addr with the given input as parameters.
|
||||
// It reverses the state in case of an execution error.
|
||||
//
|
||||
// DelegateCall differs from CallCode in the sense that it executes the given address' code with the caller as context
|
||||
// and the caller is set to the caller of the caller.
|
||||
func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas *big.Int) ([]byte, error) {
|
||||
if env.vmConfig.NoRecursion && env.Depth > 0 {
|
||||
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas *big.Int) (ret []byte, err error) {
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, nil
|
||||
@ -203,34 +217,34 @@ func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, in
|
||||
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if env.Depth > int(params.CallCreateDepth.Int64()) {
|
||||
if evm.depth > int(params.CallCreateDepth.Int64()) {
|
||||
caller.ReturnGas(gas)
|
||||
return nil, DepthError
|
||||
return nil, ErrDepth
|
||||
}
|
||||
|
||||
var (
|
||||
snapshot = env.StateDB.Snapshot()
|
||||
to = env.StateDB.GetAccount(caller.Address())
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
to = evm.StateDB.GetAccount(caller.Address())
|
||||
)
|
||||
|
||||
// Iinitialise a new contract and make initialise the delegate values
|
||||
contract := NewContract(caller, to, caller.Value(), gas).AsDelegate()
|
||||
contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
defer contract.Finalise()
|
||||
|
||||
ret, err := env.EVM().Run(contract, input)
|
||||
ret, err = evm.interpreter.Run(contract, input)
|
||||
if err != nil {
|
||||
contract.UseGas(contract.Gas)
|
||||
|
||||
env.StateDB.RevertToSnapshot(snapshot)
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
}
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Create creates a new contract using code as deployment code.
|
||||
func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.Int) ([]byte, common.Address, error) {
|
||||
if env.vmConfig.NoRecursion && env.Depth > 0 {
|
||||
func (evm *EVM) Create(caller ContractRef, code []byte, gas, value *big.Int) (ret []byte, contractAddr common.Address, err error) {
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, common.Address{}, nil
|
||||
@ -238,39 +252,38 @@ func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.
|
||||
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if env.Depth > int(params.CallCreateDepth.Int64()) {
|
||||
if evm.depth > int(params.CallCreateDepth.Int64()) {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, common.Address{}, DepthError
|
||||
return nil, common.Address{}, ErrDepth
|
||||
}
|
||||
if !env.CanTransfer(env.StateDB, caller.Address(), value) {
|
||||
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
caller.ReturnGas(gas)
|
||||
|
||||
return nil, common.Address{}, ErrInsufficientBalance
|
||||
}
|
||||
|
||||
// Create a new account on the state
|
||||
nonce := env.StateDB.GetNonce(caller.Address())
|
||||
env.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||
nonce := evm.StateDB.GetNonce(caller.Address())
|
||||
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||
|
||||
snapshotPreTransfer := env.StateDB.Snapshot()
|
||||
var (
|
||||
addr = crypto.CreateAddress(caller.Address(), nonce)
|
||||
to = env.StateDB.CreateAccount(addr)
|
||||
)
|
||||
if env.ChainConfig().IsEIP158(env.BlockNumber) {
|
||||
env.StateDB.SetNonce(addr, 1)
|
||||
snapshot := evm.StateDB.Snapshot()
|
||||
contractAddr = crypto.CreateAddress(caller.Address(), nonce)
|
||||
to := evm.StateDB.CreateAccount(contractAddr)
|
||||
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
|
||||
evm.StateDB.SetNonce(contractAddr, 1)
|
||||
}
|
||||
env.Transfer(env.StateDB, caller.Address(), to.Address(), value)
|
||||
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||
|
||||
// initialise a new contract and set the code that is to be used by the
|
||||
// E The contract is a scoped environment for this execution context
|
||||
// E The contract is a scoped evmironment for this execution context
|
||||
// only.
|
||||
contract := NewContract(caller, to, value, gas)
|
||||
contract.SetCallCode(&addr, crypto.Keccak256Hash(code), code)
|
||||
contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
|
||||
defer contract.Finalise()
|
||||
|
||||
ret, err := env.EVM().Run(contract, nil)
|
||||
ret, err = evm.interpreter.Run(contract, nil)
|
||||
|
||||
// check whether the max code size has been exceeded
|
||||
maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
|
||||
// if the contract creation ran successfully and no errors were returned
|
||||
@ -281,9 +294,9 @@ func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.
|
||||
dataGas := big.NewInt(int64(len(ret)))
|
||||
dataGas.Mul(dataGas, params.CreateDataGas)
|
||||
if contract.UseGas(dataGas) {
|
||||
env.StateDB.SetCode(addr, ret)
|
||||
evm.StateDB.SetCode(contractAddr, ret)
|
||||
} else {
|
||||
err = CodeStoreOutOfGasError
|
||||
err = ErrCodeStoreOutOfGas
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,12 +304,12 @@ func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.
|
||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||
// when we're in homestead this also counts for code storage gas errors.
|
||||
if maxCodeSizeExceeded ||
|
||||
(err != nil && (env.ChainConfig().IsHomestead(env.BlockNumber) || err != CodeStoreOutOfGasError)) {
|
||||
(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
|
||||
contract.UseGas(contract.Gas)
|
||||
env.StateDB.RevertToSnapshot(snapshotPreTransfer)
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
|
||||
// Nothing should be returned when an error is thrown.
|
||||
return nil, addr, err
|
||||
return nil, contractAddr, err
|
||||
}
|
||||
// If the vm returned with an error the return value should be set to nil.
|
||||
// This isn't consensus critical but merely to for behaviour reasons such as
|
||||
@ -305,11 +318,11 @@ func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.
|
||||
ret = nil
|
||||
}
|
||||
|
||||
return ret, addr, err
|
||||
return ret, contractAddr, err
|
||||
}
|
||||
|
||||
// ChainConfig returns the environment's chain configuration
|
||||
func (env *Environment) ChainConfig() *params.ChainConfig { return env.chainConfig }
|
||||
// ChainConfig returns the evmironment's chain configuration
|
||||
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
|
||||
|
||||
// EVM returns the environments EVM
|
||||
func (env *Environment) EVM() Vm { return env.evm }
|
||||
// Interpreter returns the EVM interpreter
|
||||
func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter }
|
||||
|
15
vendor/github.com/ethereum/go-ethereum/core/vm/errors.go
generated
vendored
15
vendor/github.com/ethereum/go-ethereum/core/vm/errors.go
generated
vendored
@ -16,17 +16,12 @@
|
||||
|
||||
package vm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
OutOfGasError = errors.New("Out of gas")
|
||||
CodeStoreOutOfGasError = errors.New("Contract creation code storage out of gas")
|
||||
DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth)
|
||||
TraceLimitReachedError = errors.New("The number of logs reached the specified limit")
|
||||
ErrOutOfGas = errors.New("out of gas")
|
||||
ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas")
|
||||
ErrDepth = errors.New("max call depth exceeded")
|
||||
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit")
|
||||
ErrInsufficientBalance = errors.New("insufficient balance for transfer")
|
||||
)
|
||||
|
246
vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go
generated
vendored
Normal file
246
vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go
generated
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func memoryGasCost(mem *Memory, newMemSize *big.Int) *big.Int {
|
||||
gas := new(big.Int)
|
||||
if newMemSize.Cmp(common.Big0) > 0 {
|
||||
newMemSizeWords := toWordSize(newMemSize)
|
||||
|
||||
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
|
||||
// be careful reusing variables here when changing.
|
||||
// The order has been optimised to reduce allocation
|
||||
oldSize := toWordSize(big.NewInt(int64(mem.Len())))
|
||||
pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
|
||||
linCoef := oldSize.Mul(oldSize, params.MemoryGas)
|
||||
quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
|
||||
oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
|
||||
|
||||
pow.Exp(newMemSizeWords, common.Big2, Zero)
|
||||
linCoef = linCoef.Mul(newMemSizeWords, params.MemoryGas)
|
||||
quadCoef = quadCoef.Div(pow, params.QuadCoeffDiv)
|
||||
newTotalFee := linCoef.Add(linCoef, quadCoef)
|
||||
|
||||
fee := newTotalFee.Sub(newTotalFee, oldTotalFee)
|
||||
gas.Add(gas, fee)
|
||||
}
|
||||
}
|
||||
return gas
|
||||
}
|
||||
|
||||
func constGasFunc(gas *big.Int) gasFunc {
|
||||
return func(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return gas
|
||||
}
|
||||
}
|
||||
|
||||
func gasCalldataCopy(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := memoryGasCost(mem, memorySize)
|
||||
gas.Add(gas, GasFastestStep)
|
||||
words := toWordSize(stack.Back(2))
|
||||
|
||||
return gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
}
|
||||
|
||||
func gasSStore(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
var (
|
||||
y, x = stack.Back(1), stack.Back(0)
|
||||
val = env.StateDB.GetState(contract.Address(), common.BigToHash(x))
|
||||
)
|
||||
// This checks for 3 scenario's and calculates gas accordingly
|
||||
// 1. From a zero-value address to a non-zero value (NEW VALUE)
|
||||
// 2. From a non-zero value address to a zero-value address (DELETE)
|
||||
// 3. From a non-zero to a non-zero (CHANGE)
|
||||
if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
|
||||
// 0 => non 0
|
||||
return new(big.Int).Set(params.SstoreSetGas)
|
||||
} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
|
||||
env.StateDB.AddRefund(params.SstoreRefundGas)
|
||||
|
||||
return new(big.Int).Set(params.SstoreClearGas)
|
||||
} else {
|
||||
// non 0 => non 0 (or 0 => 0)
|
||||
return new(big.Int).Set(params.SstoreResetGas)
|
||||
}
|
||||
}
|
||||
|
||||
func makeGasLog(n uint) gasFunc {
|
||||
return func(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
mSize := stack.Back(1)
|
||||
|
||||
gas := new(big.Int).Add(memoryGasCost(mem, memorySize), params.LogGas)
|
||||
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
|
||||
gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
|
||||
return gas
|
||||
}
|
||||
}
|
||||
|
||||
func gasSha3(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := memoryGasCost(mem, memorySize)
|
||||
gas.Add(gas, params.Sha3Gas)
|
||||
words := toWordSize(stack.Back(1))
|
||||
return gas.Add(gas, words.Mul(words, params.Sha3WordGas))
|
||||
}
|
||||
|
||||
func gasCodeCopy(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := memoryGasCost(mem, memorySize)
|
||||
gas.Add(gas, GasFastestStep)
|
||||
words := toWordSize(stack.Back(2))
|
||||
|
||||
return gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
}
|
||||
|
||||
func gasExtCodeCopy(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := memoryGasCost(mem, memorySize)
|
||||
gas.Add(gas, gt.ExtcodeCopy)
|
||||
words := toWordSize(stack.Back(3))
|
||||
|
||||
return gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
}
|
||||
|
||||
func gasMLoad(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return new(big.Int).Add(GasFastestStep, memoryGasCost(mem, memorySize))
|
||||
}
|
||||
|
||||
func gasMStore8(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return new(big.Int).Add(GasFastestStep, memoryGasCost(mem, memorySize))
|
||||
}
|
||||
|
||||
func gasMStore(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return new(big.Int).Add(GasFastestStep, memoryGasCost(mem, memorySize))
|
||||
}
|
||||
|
||||
func gasCreate(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return new(big.Int).Add(params.CreateGas, memoryGasCost(mem, memorySize))
|
||||
}
|
||||
|
||||
func gasBalance(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return gt.Balance
|
||||
}
|
||||
|
||||
func gasExtCodeSize(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return gt.ExtcodeSize
|
||||
}
|
||||
|
||||
func gasSLoad(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return gt.SLoad
|
||||
}
|
||||
|
||||
func gasExp(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
expByteLen := int64((stack.data[stack.len()-2].BitLen() + 7) / 8)
|
||||
gas := big.NewInt(expByteLen)
|
||||
gas.Mul(gas, gt.ExpByte)
|
||||
return gas.Add(gas, GasSlowStep)
|
||||
}
|
||||
|
||||
func gasCall(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := new(big.Int).Set(gt.Calls)
|
||||
|
||||
transfersValue := stack.Back(2).BitLen() > 0
|
||||
var (
|
||||
address = common.BigToAddress(stack.Back(1))
|
||||
eip158 = env.ChainConfig().IsEIP158(env.BlockNumber)
|
||||
)
|
||||
if eip158 {
|
||||
if env.StateDB.Empty(address) && transfersValue {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
} else if !env.StateDB.Exist(address) {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
if transfersValue {
|
||||
gas.Add(gas, params.CallValueTransferGas)
|
||||
}
|
||||
gas.Add(gas, memoryGasCost(mem, memorySize))
|
||||
|
||||
cg := callGas(gt, contract.Gas, gas, stack.data[stack.len()-1])
|
||||
// Replace the stack item with the new gas calculation. This means that
|
||||
// either the original item is left on the stack or the item is replaced by:
|
||||
// (availableGas - gas) * 63 / 64
|
||||
// We replace the stack item so that it's available when the opCall instruction is
|
||||
// called. This information is otherwise lost due to the dependency on *current*
|
||||
// available gas.
|
||||
stack.data[stack.len()-1] = cg
|
||||
|
||||
return gas.Add(gas, cg)
|
||||
}
|
||||
|
||||
func gasCallCode(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := new(big.Int).Set(gt.Calls)
|
||||
if stack.Back(2).BitLen() > 0 {
|
||||
gas.Add(gas, params.CallValueTransferGas)
|
||||
}
|
||||
gas.Add(gas, memoryGasCost(mem, memorySize))
|
||||
|
||||
cg := callGas(gt, contract.Gas, gas, stack.data[stack.len()-1])
|
||||
// Replace the stack item with the new gas calculation. This means that
|
||||
// either the original item is left on the stack or the item is replaced by:
|
||||
// (availableGas - gas) * 63 / 64
|
||||
// We replace the stack item so that it's available when the opCall instruction is
|
||||
// called. This information is otherwise lost due to the dependency on *current*
|
||||
// available gas.
|
||||
stack.data[stack.len()-1] = cg
|
||||
|
||||
return gas.Add(gas, cg)
|
||||
}
|
||||
|
||||
func gasReturn(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return memoryGasCost(mem, memorySize)
|
||||
}
|
||||
|
||||
func gasSuicide(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := new(big.Int)
|
||||
// EIP150 homestead gas reprice fork:
|
||||
if env.ChainConfig().IsEIP150(env.BlockNumber) {
|
||||
gas.Set(gt.Suicide)
|
||||
var (
|
||||
address = common.BigToAddress(stack.Back(0))
|
||||
eip158 = env.ChainConfig().IsEIP158(env.BlockNumber)
|
||||
)
|
||||
|
||||
if eip158 {
|
||||
// if empty and transfers value
|
||||
if env.StateDB.Empty(address) && env.StateDB.GetBalance(contract.Address()).BitLen() > 0 {
|
||||
gas.Add(gas, gt.CreateBySuicide)
|
||||
}
|
||||
} else if !env.StateDB.Exist(address) {
|
||||
gas.Add(gas, gt.CreateBySuicide)
|
||||
}
|
||||
}
|
||||
|
||||
if !env.StateDB.HasSuicided(contract.Address()) {
|
||||
env.StateDB.AddRefund(params.SuicideRefundGas)
|
||||
}
|
||||
return gas
|
||||
}
|
||||
|
||||
func gasDelegateCall(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
gas := new(big.Int).Add(gt.Calls, memoryGasCost(mem, memorySize))
|
||||
|
||||
cg := callGas(gt, contract.Gas, gas, stack.data[stack.len()-1])
|
||||
// Replace the stack item with the new gas calculation. This means that
|
||||
// either the original item is left on the stack or the item is replaced by:
|
||||
// (availableGas - gas) * 63 / 64
|
||||
// We replace the stack item so that it's available when the opCall instruction is
|
||||
// called.
|
||||
stack.data[stack.len()-1] = cg
|
||||
|
||||
return gas.Add(gas, cg)
|
||||
}
|
||||
|
||||
func gasPush(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return GasFastestStep
|
||||
}
|
||||
|
||||
func gasSwap(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return GasFastestStep
|
||||
}
|
||||
|
||||
func gasDup(gt params.GasTable, env *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize *big.Int) *big.Int {
|
||||
return GasFastestStep
|
||||
}
|
371
vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go
generated
vendored
371
vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go
generated
vendored
@ -22,132 +22,44 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
type programInstruction interface {
|
||||
// executes the program instruction and allows the instruction to modify the state of the program
|
||||
do(program *Program, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
|
||||
// returns whether the program instruction halts the execution of the JIT
|
||||
halts() bool
|
||||
// Returns the current op code (debugging purposes)
|
||||
Op() OpCode
|
||||
}
|
||||
|
||||
type instrFn func(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack)
|
||||
|
||||
type instruction struct {
|
||||
op OpCode
|
||||
pc uint64
|
||||
fn instrFn
|
||||
data *big.Int
|
||||
|
||||
gas *big.Int
|
||||
spop int
|
||||
spush int
|
||||
|
||||
returns bool
|
||||
}
|
||||
|
||||
func jump(mapping map[uint64]uint64, destinations map[uint64]struct{}, contract *Contract, to *big.Int) (uint64, error) {
|
||||
if !validDest(destinations, to) {
|
||||
nop := contract.GetOp(to.Uint64())
|
||||
return 0, fmt.Errorf("invalid jump destination (%v) %v", nop, to)
|
||||
}
|
||||
|
||||
return mapping[to.Uint64()], nil
|
||||
}
|
||||
|
||||
func (instr instruction) do(program *Program, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
// calculate the new memory size and gas price for the current executing opcode
|
||||
newMemSize, cost, err := jitCalculateGasAndSize(env, contract, instr, memory, stack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use the calculated gas. When insufficient gas is present, use all gas and return an
|
||||
// Out Of Gas error
|
||||
if !contract.UseGas(cost) {
|
||||
return nil, OutOfGasError
|
||||
}
|
||||
// Resize the memory calculated previously
|
||||
memory.Resize(newMemSize.Uint64())
|
||||
|
||||
// These opcodes return an argument and are therefor handled
|
||||
// differently from the rest of the opcodes
|
||||
switch instr.op {
|
||||
case JUMP:
|
||||
if pos, err := jump(program.mapping, program.destinations, contract, stack.pop()); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
*pc = pos
|
||||
return nil, nil
|
||||
}
|
||||
case JUMPI:
|
||||
pos, cond := stack.pop(), stack.pop()
|
||||
if cond.Cmp(common.BigTrue) >= 0 {
|
||||
if pos, err := jump(program.mapping, program.destinations, contract, pos); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
*pc = pos
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
case RETURN:
|
||||
offset, size := stack.pop(), stack.pop()
|
||||
return memory.GetPtr(offset.Int64(), size.Int64()), nil
|
||||
default:
|
||||
if instr.fn == nil {
|
||||
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.op)
|
||||
}
|
||||
instr.fn(instr, pc, env, contract, memory, stack)
|
||||
}
|
||||
*pc++
|
||||
func opAdd(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(U256(x.Add(x, y)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (instr instruction) halts() bool {
|
||||
return instr.returns
|
||||
}
|
||||
|
||||
func (instr instruction) Op() OpCode {
|
||||
return instr.op
|
||||
}
|
||||
|
||||
func opStaticJump(instr instruction, pc *uint64, ret *big.Int, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
ret.Set(instr.data)
|
||||
}
|
||||
|
||||
func opAdd(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(U256(x.Add(x, y)))
|
||||
}
|
||||
|
||||
func opSub(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSub(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(U256(x.Sub(x, y)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMul(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMul(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(U256(x.Mul(x, y)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opDiv(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opDiv(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
if y.Cmp(common.Big0) != 0 {
|
||||
stack.push(U256(x.Div(x, y)))
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSdiv(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSdiv(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := S256(stack.pop()), S256(stack.pop())
|
||||
if y.Cmp(common.Big0) == 0 {
|
||||
stack.push(new(big.Int))
|
||||
return
|
||||
return nil, nil
|
||||
} else {
|
||||
n := new(big.Int)
|
||||
if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
|
||||
@ -161,18 +73,20 @@ func opSdiv(instr instruction, pc *uint64, env *Environment, contract *Contract,
|
||||
|
||||
stack.push(U256(res))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMod(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
if y.Cmp(common.Big0) == 0 {
|
||||
stack.push(new(big.Int))
|
||||
} else {
|
||||
stack.push(U256(x.Mod(x, y)))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSmod(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSmod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := S256(stack.pop()), S256(stack.pop())
|
||||
|
||||
if y.Cmp(common.Big0) == 0 {
|
||||
@ -190,14 +104,16 @@ func opSmod(instr instruction, pc *uint64, env *Environment, contract *Contract,
|
||||
|
||||
stack.push(U256(res))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opExp(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opExp(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
base, exponent := stack.pop(), stack.pop()
|
||||
stack.push(math.Exp(base, exponent))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSignExtend(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSignExtend(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
back := stack.pop()
|
||||
if back.Cmp(big.NewInt(31)) < 0 {
|
||||
bit := uint(back.Uint64()*8 + 7)
|
||||
@ -212,80 +128,91 @@ func opSignExtend(instr instruction, pc *uint64, env *Environment, contract *Con
|
||||
|
||||
stack.push(U256(num))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opNot(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opNot(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x := stack.pop()
|
||||
stack.push(U256(x.Not(x)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opLt(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opLt(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
if x.Cmp(y) < 0 {
|
||||
stack.push(big.NewInt(1))
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGt(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opGt(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
if x.Cmp(y) > 0 {
|
||||
stack.push(big.NewInt(1))
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSlt(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSlt(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := S256(stack.pop()), S256(stack.pop())
|
||||
if x.Cmp(S256(y)) < 0 {
|
||||
stack.push(big.NewInt(1))
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSgt(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSgt(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := S256(stack.pop()), S256(stack.pop())
|
||||
if x.Cmp(y) > 0 {
|
||||
stack.push(big.NewInt(1))
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opEq(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opEq(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
if x.Cmp(y) == 0 {
|
||||
stack.push(big.NewInt(1))
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opIszero(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opIszero(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x := stack.pop()
|
||||
if x.Cmp(common.Big0) > 0 {
|
||||
stack.push(new(big.Int))
|
||||
} else {
|
||||
stack.push(big.NewInt(1))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opAnd(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opAnd(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(x.And(x, y))
|
||||
return nil, nil
|
||||
}
|
||||
func opOr(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opOr(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(x.Or(x, y))
|
||||
return nil, nil
|
||||
}
|
||||
func opXor(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opXor(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y := stack.pop(), stack.pop()
|
||||
stack.push(x.Xor(x, y))
|
||||
return nil, nil
|
||||
}
|
||||
func opByte(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opByte(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
th, val := stack.pop(), stack.pop()
|
||||
if th.Cmp(big.NewInt(32)) < 0 {
|
||||
byte := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
|
||||
@ -293,8 +220,9 @@ func opByte(instr instruction, pc *uint64, env *Environment, contract *Contract,
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
func opAddmod(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opAddmod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y, z := stack.pop(), stack.pop(), stack.pop()
|
||||
if z.Cmp(Zero) > 0 {
|
||||
add := x.Add(x, y)
|
||||
@ -303,8 +231,9 @@ func opAddmod(instr instruction, pc *uint64, env *Environment, contract *Contrac
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
func opMulmod(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMulmod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
x, y, z := stack.pop(), stack.pop(), stack.pop()
|
||||
if z.Cmp(Zero) > 0 {
|
||||
mul := x.Mul(x, y)
|
||||
@ -313,67 +242,79 @@ func opMulmod(instr instruction, pc *uint64, env *Environment, contract *Contrac
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSha3(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSha3(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
offset, size := stack.pop(), stack.pop()
|
||||
hash := crypto.Keccak256(memory.Get(offset.Int64(), size.Int64()))
|
||||
|
||||
stack.push(common.BytesToBig(hash))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opAddress(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opAddress(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(common.Bytes2Big(contract.Address().Bytes()))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opBalance(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opBalance(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
addr := common.BigToAddress(stack.pop())
|
||||
balance := env.StateDB.GetBalance(addr)
|
||||
|
||||
stack.push(new(big.Int).Set(balance))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opOrigin(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opOrigin(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(env.Origin.Big())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCaller(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCaller(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(contract.Caller().Big())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallValue(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCallValue(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(new(big.Int).Set(contract.value))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCalldataLoad(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCalldataLoad(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(common.Bytes2Big(getData(contract.Input, stack.pop(), common.Big32)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCalldataSize(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCalldataSize(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(big.NewInt(int64(len(contract.Input))))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCalldataCopy(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCalldataCopy(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
var (
|
||||
mOff = stack.pop()
|
||||
cOff = stack.pop()
|
||||
l = stack.pop()
|
||||
)
|
||||
memory.Set(mOff.Uint64(), l.Uint64(), getData(contract.Input, cOff, l))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeSize(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opExtCodeSize(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
addr := common.BigToAddress(stack.pop())
|
||||
l := big.NewInt(int64(env.StateDB.GetCodeSize(addr)))
|
||||
stack.push(l)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCodeSize(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCodeSize(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
l := big.NewInt(int64(len(contract.Code)))
|
||||
stack.push(l)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCodeCopy(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCodeCopy(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
var (
|
||||
mOff = stack.pop()
|
||||
cOff = stack.pop()
|
||||
@ -382,9 +323,10 @@ func opCodeCopy(instr instruction, pc *uint64, env *Environment, contract *Contr
|
||||
codeCopy := getData(contract.Code, cOff, l)
|
||||
|
||||
memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeCopy(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opExtCodeCopy(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
var (
|
||||
addr = common.BigToAddress(stack.pop())
|
||||
mOff = stack.pop()
|
||||
@ -394,13 +336,15 @@ func opExtCodeCopy(instr instruction, pc *uint64, env *Environment, contract *Co
|
||||
codeCopy := getData(env.StateDB.GetCode(addr), cOff, l)
|
||||
|
||||
memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGasprice(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opGasprice(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(new(big.Int).Set(env.GasPrice))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opBlockhash(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opBlockhash(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
num := stack.pop()
|
||||
|
||||
n := new(big.Int).Sub(env.BlockNumber, common.Big257)
|
||||
@ -409,106 +353,115 @@ func opBlockhash(instr instruction, pc *uint64, env *Environment, contract *Cont
|
||||
} else {
|
||||
stack.push(new(big.Int))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCoinbase(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCoinbase(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(env.Coinbase.Big())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opTimestamp(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opTimestamp(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(U256(new(big.Int).Set(env.Time)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opNumber(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opNumber(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(U256(new(big.Int).Set(env.BlockNumber)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opDifficulty(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opDifficulty(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(U256(new(big.Int).Set(env.Difficulty)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGasLimit(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opGasLimit(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(U256(new(big.Int).Set(env.GasLimit)))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opPop(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opPop(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.pop()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opPush(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
stack.push(new(big.Int).Set(instr.data))
|
||||
}
|
||||
|
||||
func opDup(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
stack.dup(int(instr.data.Int64()))
|
||||
}
|
||||
|
||||
func opSwap(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
stack.swap(int(instr.data.Int64()))
|
||||
}
|
||||
|
||||
func opLog(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
n := int(instr.data.Int64())
|
||||
topics := make([]common.Hash, n)
|
||||
mStart, mSize := stack.pop(), stack.pop()
|
||||
for i := 0; i < n; i++ {
|
||||
topics[i] = common.BigToHash(stack.pop())
|
||||
}
|
||||
|
||||
d := memory.Get(mStart.Int64(), mSize.Int64())
|
||||
log := NewLog(contract.Address(), topics, d, env.BlockNumber.Uint64())
|
||||
env.StateDB.AddLog(log)
|
||||
}
|
||||
|
||||
func opMload(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMload(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
offset := stack.pop()
|
||||
val := common.BigD(memory.Get(offset.Int64(), 32))
|
||||
stack.push(val)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMstore(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMstore(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
// pop value of the stack
|
||||
mStart, val := stack.pop(), stack.pop()
|
||||
memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMstore8(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMstore8(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
off, val := stack.pop().Int64(), stack.pop().Int64()
|
||||
memory.store[off] = byte(val & 0xff)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSload(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSload(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
loc := common.BigToHash(stack.pop())
|
||||
val := env.StateDB.GetState(contract.Address(), loc).Big()
|
||||
stack.push(val)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSstore(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opSstore(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
loc := common.BigToHash(stack.pop())
|
||||
val := stack.pop()
|
||||
env.StateDB.SetState(contract.Address(), loc, common.BigToHash(val))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opJump(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opJump(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
pos := stack.pop()
|
||||
if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) {
|
||||
nop := contract.GetOp(pos.Uint64())
|
||||
return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
|
||||
}
|
||||
*pc = pos.Uint64()
|
||||
return nil, nil
|
||||
}
|
||||
func opJumpi(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opJumpi(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
pos, cond := stack.pop(), stack.pop()
|
||||
if cond.Cmp(common.BigTrue) >= 0 {
|
||||
if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) {
|
||||
nop := contract.GetOp(pos.Uint64())
|
||||
return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
|
||||
}
|
||||
*pc = pos.Uint64()
|
||||
} else {
|
||||
*pc++
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
func opJumpdest(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opJumpdest(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opPc(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
stack.push(new(big.Int).Set(instr.data))
|
||||
func opPc(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(new(big.Int).SetUint64(*pc))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMsize(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opMsize(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(big.NewInt(int64(memory.Len())))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opGas(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opGas(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(new(big.Int).Set(contract.Gas))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCreate(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCreate(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
var (
|
||||
value = stack.pop()
|
||||
offset, size = stack.pop(), stack.pop()
|
||||
@ -526,16 +479,17 @@ func opCreate(instr instruction, pc *uint64, env *Environment, contract *Contrac
|
||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||
// rule) and treat as an error, if the ruleset is frontier we must
|
||||
// ignore this error and pretend the operation was successful.
|
||||
if env.ChainConfig().IsHomestead(env.BlockNumber) && suberr == CodeStoreOutOfGasError {
|
||||
if env.ChainConfig().IsHomestead(env.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
|
||||
stack.push(new(big.Int))
|
||||
} else if suberr != nil && suberr != CodeStoreOutOfGasError {
|
||||
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
|
||||
stack.push(new(big.Int))
|
||||
} else {
|
||||
stack.push(addr.Big())
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCall(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCall(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
gas := stack.pop()
|
||||
// pop gas and value of the stack.
|
||||
addr, value := stack.pop(), stack.pop()
|
||||
@ -564,9 +518,10 @@ func opCall(instr instruction, pc *uint64, env *Environment, contract *Contract,
|
||||
|
||||
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallCode(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opCallCode(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
gas := stack.pop()
|
||||
// pop gas and value of the stack.
|
||||
addr, value := stack.pop(), stack.pop()
|
||||
@ -595,9 +550,16 @@ func opCallCode(instr instruction, pc *uint64, env *Environment, contract *Contr
|
||||
|
||||
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opDelegateCall(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opDelegateCall(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
// if not homestead return an error. DELEGATECALL is not supported
|
||||
// during pre-homestead.
|
||||
if !env.ChainConfig().IsHomestead(env.BlockNumber) {
|
||||
return nil, fmt.Errorf("invalid opcode %x", DELEGATECALL)
|
||||
}
|
||||
|
||||
gas, to, inOffset, inSize, outOffset, outSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||
|
||||
toAddr := common.BigToAddress(to)
|
||||
@ -609,25 +571,34 @@ func opDelegateCall(instr instruction, pc *uint64, env *Environment, contract *C
|
||||
stack.push(big.NewInt(1))
|
||||
memory.Set(outOffset.Uint64(), outSize.Uint64(), ret)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opReturn(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
}
|
||||
func opStop(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opReturn(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
offset, size := stack.pop(), stack.pop()
|
||||
ret := memory.GetPtr(offset.Int64(), size.Int64())
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func opSuicide(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func opStop(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSuicide(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
balance := env.StateDB.GetBalance(contract.Address())
|
||||
env.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance)
|
||||
|
||||
env.StateDB.Suicide(contract.Address())
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// following functions are used by the instruction jump table
|
||||
|
||||
// make log instruction function
|
||||
func makeLog(size int) instrFn {
|
||||
return func(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func makeLog(size int) executionFunc {
|
||||
return func(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
topics := make([]common.Hash, size)
|
||||
mStart, mSize := stack.pop(), stack.pop()
|
||||
for i := 0; i < size; i++ {
|
||||
@ -635,32 +606,42 @@ func makeLog(size int) instrFn {
|
||||
}
|
||||
|
||||
d := memory.Get(mStart.Int64(), mSize.Int64())
|
||||
log := NewLog(contract.Address(), topics, d, env.BlockNumber.Uint64())
|
||||
env.StateDB.AddLog(log)
|
||||
env.StateDB.AddLog(&types.Log{
|
||||
Address: contract.Address(),
|
||||
Topics: topics,
|
||||
Data: d,
|
||||
// This is a non-consensus field, but assigned here because
|
||||
// core/state doesn't know the current block number.
|
||||
BlockNumber: env.BlockNumber.Uint64(),
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// make push instruction function
|
||||
func makePush(size uint64, bsize *big.Int) instrFn {
|
||||
return func(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func makePush(size uint64, bsize *big.Int) executionFunc {
|
||||
return func(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
byts := getData(contract.Code, new(big.Int).SetUint64(*pc+1), bsize)
|
||||
stack.push(common.Bytes2Big(byts))
|
||||
*pc += size
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// make push instruction function
|
||||
func makeDup(size int64) instrFn {
|
||||
return func(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
func makeDup(size int64) executionFunc {
|
||||
return func(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.dup(int(size))
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// make swap instruction function
|
||||
func makeSwap(size int64) instrFn {
|
||||
func makeSwap(size int64) executionFunc {
|
||||
// switch n + 1 otherwise n would be swapped with n
|
||||
size += 1
|
||||
return func(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||
return func(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.swap(int(size))
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
21
vendor/github.com/ethereum/go-ethereum/core/vm/interface.go
generated
vendored
21
vendor/github.com/ethereum/go-ethereum/core/vm/interface.go
generated
vendored
@ -20,16 +20,9 @@ import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// Vm is the basic interface for an implementation of the EVM.
|
||||
type Vm interface {
|
||||
// Run should execute the given contract with the input given in in
|
||||
// and return the contract execution return bytes or an error if it
|
||||
// failed.
|
||||
Run(c *Contract, in []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// StateDB is an EVM database for full state querying.
|
||||
type StateDB interface {
|
||||
GetAccount(common.Address) Account
|
||||
@ -66,7 +59,7 @@ type StateDB interface {
|
||||
RevertToSnapshot(int)
|
||||
Snapshot() int
|
||||
|
||||
AddLog(*Log)
|
||||
AddLog(*types.Log)
|
||||
}
|
||||
|
||||
// Account represents a contract or basic ethereum account.
|
||||
@ -83,15 +76,15 @@ type Account interface {
|
||||
Value() *big.Int
|
||||
}
|
||||
|
||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM Environment
|
||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM EVM
|
||||
// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
|
||||
type CallContext interface {
|
||||
// Call another contract
|
||||
Call(env *Environment, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
|
||||
Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
|
||||
// Take another's contract code and execute within our own context
|
||||
CallCode(env *Environment, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
|
||||
CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
|
||||
// Same as CallCode except sender and value is propagated from parent to child scope
|
||||
DelegateCall(env *Environment, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
|
||||
DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
|
||||
// Create a new contract
|
||||
Create(env *Environment, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
|
||||
Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
|
||||
}
|
||||
|
512
vendor/github.com/ethereum/go-ethereum/core/vm/jit.go
generated
vendored
512
vendor/github.com/ethereum/go-ethereum/core/vm/jit.go
generated
vendored
@ -1,512 +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/>.
|
||||
|
||||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// progStatus is the type for the JIT program status.
|
||||
type progStatus int32
|
||||
|
||||
const (
|
||||
progUnknown progStatus = iota // unknown status
|
||||
progCompile // compile status
|
||||
progReady // ready for use status
|
||||
progError // error status (usually caused during compilation)
|
||||
|
||||
defaultJitMaxCache int = 64 // maximum amount of jit cached programs
|
||||
)
|
||||
|
||||
var MaxProgSize int // Max cache size for JIT programs
|
||||
|
||||
var programs *lru.Cache // lru cache for the JIT programs.
|
||||
|
||||
func init() {
|
||||
SetJITCacheSize(defaultJitMaxCache)
|
||||
}
|
||||
|
||||
// SetJITCacheSize recreates the program cache with the max given size. Setting
|
||||
// a new cache is **not** thread safe. Use with caution.
|
||||
func SetJITCacheSize(size int) {
|
||||
programs, _ = lru.New(size)
|
||||
}
|
||||
|
||||
// GetProgram returns the program by id or nil when non-existent
|
||||
func GetProgram(id common.Hash) *Program {
|
||||
if p, ok := programs.Get(id); ok {
|
||||
return p.(*Program)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenProgramStatus returns the status of the given program id
|
||||
func GetProgramStatus(id common.Hash) progStatus {
|
||||
program := GetProgram(id)
|
||||
if program != nil {
|
||||
return progStatus(atomic.LoadInt32(&program.status))
|
||||
}
|
||||
|
||||
return progUnknown
|
||||
}
|
||||
|
||||
// Program is a compiled program for the JIT VM and holds all required for
|
||||
// running a compiled JIT program.
|
||||
type Program struct {
|
||||
Id common.Hash // Id of the program
|
||||
status int32 // status should be accessed atomically
|
||||
|
||||
contract *Contract
|
||||
|
||||
instructions []programInstruction // instruction set
|
||||
mapping map[uint64]uint64 // real PC mapping to array indices
|
||||
destinations map[uint64]struct{} // cached jump destinations
|
||||
|
||||
code []byte
|
||||
}
|
||||
|
||||
// NewProgram returns a new JIT program
|
||||
func NewProgram(code []byte) *Program {
|
||||
program := &Program{
|
||||
Id: crypto.Keccak256Hash(code),
|
||||
mapping: make(map[uint64]uint64),
|
||||
destinations: make(map[uint64]struct{}),
|
||||
code: code,
|
||||
}
|
||||
|
||||
programs.Add(program.Id, program)
|
||||
return program
|
||||
}
|
||||
|
||||
func (p *Program) addInstr(op OpCode, pc uint64, fn instrFn, data *big.Int) {
|
||||
// PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
|
||||
// PUSH is also allowed to calculate the same price for all PUSHes
|
||||
// DUP requirements are handled elsewhere (except for the stack limit check)
|
||||
baseOp := op
|
||||
if op >= PUSH1 && op <= PUSH32 {
|
||||
baseOp = PUSH1
|
||||
}
|
||||
if op >= DUP1 && op <= DUP16 {
|
||||
baseOp = DUP1
|
||||
}
|
||||
base := _baseCheck[baseOp]
|
||||
|
||||
returns := op == RETURN || op == SUICIDE || op == STOP
|
||||
instr := instruction{op, pc, fn, data, base.gas, base.stackPop, base.stackPush, returns}
|
||||
|
||||
p.instructions = append(p.instructions, instr)
|
||||
p.mapping[pc] = uint64(len(p.instructions) - 1)
|
||||
}
|
||||
|
||||
// CompileProgram compiles the given program and return an error when it fails
|
||||
func CompileProgram(program *Program) (err error) {
|
||||
if progStatus(atomic.LoadInt32(&program.status)) == progCompile {
|
||||
return nil
|
||||
}
|
||||
atomic.StoreInt32(&program.status, int32(progCompile))
|
||||
defer func() {
|
||||
if err != nil {
|
||||
atomic.StoreInt32(&program.status, int32(progError))
|
||||
} else {
|
||||
atomic.StoreInt32(&program.status, int32(progReady))
|
||||
}
|
||||
}()
|
||||
if glog.V(logger.Debug) {
|
||||
glog.Infof("compiling %x\n", program.Id[:4])
|
||||
tstart := time.Now()
|
||||
defer func() {
|
||||
glog.Infof("compiled %x instrc: %d time: %v\n", program.Id[:4], len(program.instructions), time.Since(tstart))
|
||||
}()
|
||||
}
|
||||
|
||||
// loop thru the opcodes and "compile" in to instructions
|
||||
for pc := uint64(0); pc < uint64(len(program.code)); pc++ {
|
||||
switch op := OpCode(program.code[pc]); op {
|
||||
case ADD:
|
||||
program.addInstr(op, pc, opAdd, nil)
|
||||
case SUB:
|
||||
program.addInstr(op, pc, opSub, nil)
|
||||
case MUL:
|
||||
program.addInstr(op, pc, opMul, nil)
|
||||
case DIV:
|
||||
program.addInstr(op, pc, opDiv, nil)
|
||||
case SDIV:
|
||||
program.addInstr(op, pc, opSdiv, nil)
|
||||
case MOD:
|
||||
program.addInstr(op, pc, opMod, nil)
|
||||
case SMOD:
|
||||
program.addInstr(op, pc, opSmod, nil)
|
||||
case EXP:
|
||||
program.addInstr(op, pc, opExp, nil)
|
||||
case SIGNEXTEND:
|
||||
program.addInstr(op, pc, opSignExtend, nil)
|
||||
case NOT:
|
||||
program.addInstr(op, pc, opNot, nil)
|
||||
case LT:
|
||||
program.addInstr(op, pc, opLt, nil)
|
||||
case GT:
|
||||
program.addInstr(op, pc, opGt, nil)
|
||||
case SLT:
|
||||
program.addInstr(op, pc, opSlt, nil)
|
||||
case SGT:
|
||||
program.addInstr(op, pc, opSgt, nil)
|
||||
case EQ:
|
||||
program.addInstr(op, pc, opEq, nil)
|
||||
case ISZERO:
|
||||
program.addInstr(op, pc, opIszero, nil)
|
||||
case AND:
|
||||
program.addInstr(op, pc, opAnd, nil)
|
||||
case OR:
|
||||
program.addInstr(op, pc, opOr, nil)
|
||||
case XOR:
|
||||
program.addInstr(op, pc, opXor, nil)
|
||||
case BYTE:
|
||||
program.addInstr(op, pc, opByte, nil)
|
||||
case ADDMOD:
|
||||
program.addInstr(op, pc, opAddmod, nil)
|
||||
case MULMOD:
|
||||
program.addInstr(op, pc, opMulmod, nil)
|
||||
case SHA3:
|
||||
program.addInstr(op, pc, opSha3, nil)
|
||||
case ADDRESS:
|
||||
program.addInstr(op, pc, opAddress, nil)
|
||||
case BALANCE:
|
||||
program.addInstr(op, pc, opBalance, nil)
|
||||
case ORIGIN:
|
||||
program.addInstr(op, pc, opOrigin, nil)
|
||||
case CALLER:
|
||||
program.addInstr(op, pc, opCaller, nil)
|
||||
case CALLVALUE:
|
||||
program.addInstr(op, pc, opCallValue, nil)
|
||||
case CALLDATALOAD:
|
||||
program.addInstr(op, pc, opCalldataLoad, nil)
|
||||
case CALLDATASIZE:
|
||||
program.addInstr(op, pc, opCalldataSize, nil)
|
||||
case CALLDATACOPY:
|
||||
program.addInstr(op, pc, opCalldataCopy, nil)
|
||||
case CODESIZE:
|
||||
program.addInstr(op, pc, opCodeSize, nil)
|
||||
case EXTCODESIZE:
|
||||
program.addInstr(op, pc, opExtCodeSize, nil)
|
||||
case CODECOPY:
|
||||
program.addInstr(op, pc, opCodeCopy, nil)
|
||||
case EXTCODECOPY:
|
||||
program.addInstr(op, pc, opExtCodeCopy, nil)
|
||||
case GASPRICE:
|
||||
program.addInstr(op, pc, opGasprice, nil)
|
||||
case BLOCKHASH:
|
||||
program.addInstr(op, pc, opBlockhash, nil)
|
||||
case COINBASE:
|
||||
program.addInstr(op, pc, opCoinbase, nil)
|
||||
case TIMESTAMP:
|
||||
program.addInstr(op, pc, opTimestamp, nil)
|
||||
case NUMBER:
|
||||
program.addInstr(op, pc, opNumber, nil)
|
||||
case DIFFICULTY:
|
||||
program.addInstr(op, pc, opDifficulty, nil)
|
||||
case GASLIMIT:
|
||||
program.addInstr(op, pc, opGasLimit, nil)
|
||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
||||
size := uint64(op - PUSH1 + 1)
|
||||
bytes := getData([]byte(program.code), new(big.Int).SetUint64(pc+1), new(big.Int).SetUint64(size))
|
||||
|
||||
program.addInstr(op, pc, opPush, common.Bytes2Big(bytes))
|
||||
|
||||
pc += size
|
||||
|
||||
case POP:
|
||||
program.addInstr(op, pc, opPop, nil)
|
||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||
program.addInstr(op, pc, opDup, big.NewInt(int64(op-DUP1+1)))
|
||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||
program.addInstr(op, pc, opSwap, big.NewInt(int64(op-SWAP1+2)))
|
||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||
program.addInstr(op, pc, opLog, big.NewInt(int64(op-LOG0)))
|
||||
case MLOAD:
|
||||
program.addInstr(op, pc, opMload, nil)
|
||||
case MSTORE:
|
||||
program.addInstr(op, pc, opMstore, nil)
|
||||
case MSTORE8:
|
||||
program.addInstr(op, pc, opMstore8, nil)
|
||||
case SLOAD:
|
||||
program.addInstr(op, pc, opSload, nil)
|
||||
case SSTORE:
|
||||
program.addInstr(op, pc, opSstore, nil)
|
||||
case JUMP:
|
||||
program.addInstr(op, pc, opJump, nil)
|
||||
case JUMPI:
|
||||
program.addInstr(op, pc, opJumpi, nil)
|
||||
case JUMPDEST:
|
||||
program.addInstr(op, pc, opJumpdest, nil)
|
||||
program.destinations[pc] = struct{}{}
|
||||
case PC:
|
||||
program.addInstr(op, pc, opPc, big.NewInt(int64(pc)))
|
||||
case MSIZE:
|
||||
program.addInstr(op, pc, opMsize, nil)
|
||||
case GAS:
|
||||
program.addInstr(op, pc, opGas, nil)
|
||||
case CREATE:
|
||||
program.addInstr(op, pc, opCreate, nil)
|
||||
case DELEGATECALL:
|
||||
// Instruction added regardless of homestead phase.
|
||||
// Homestead (and execution of the opcode) is checked during
|
||||
// runtime.
|
||||
program.addInstr(op, pc, opDelegateCall, nil)
|
||||
case CALL:
|
||||
program.addInstr(op, pc, opCall, nil)
|
||||
case CALLCODE:
|
||||
program.addInstr(op, pc, opCallCode, nil)
|
||||
case RETURN:
|
||||
program.addInstr(op, pc, opReturn, nil)
|
||||
case SUICIDE:
|
||||
program.addInstr(op, pc, opSuicide, nil)
|
||||
case STOP: // Stop the contract
|
||||
program.addInstr(op, pc, opStop, nil)
|
||||
default:
|
||||
program.addInstr(op, pc, nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
optimiseProgram(program)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunProgram runs the program given the environment and contract and returns an
|
||||
// error if the execution failed (non-consensus)
|
||||
func RunProgram(program *Program, env *Environment, contract *Contract, input []byte) ([]byte, error) {
|
||||
return runProgram(program, 0, NewMemory(), newstack(), env, contract, input)
|
||||
}
|
||||
|
||||
func runProgram(program *Program, pcstart uint64, mem *Memory, stack *Stack, env *Environment, contract *Contract, input []byte) ([]byte, error) {
|
||||
contract.Input = input
|
||||
|
||||
var (
|
||||
pc uint64 = program.mapping[pcstart]
|
||||
instrCount = 0
|
||||
)
|
||||
|
||||
if glog.V(logger.Debug) {
|
||||
glog.Infof("running JIT program %x\n", program.Id[:4])
|
||||
tstart := time.Now()
|
||||
defer func() {
|
||||
glog.Infof("JIT program %x done. time: %v instrc: %v\n", program.Id[:4], time.Since(tstart), instrCount)
|
||||
}()
|
||||
}
|
||||
|
||||
homestead := env.ChainConfig().IsHomestead(env.BlockNumber)
|
||||
for pc < uint64(len(program.instructions)) {
|
||||
instrCount++
|
||||
|
||||
instr := program.instructions[pc]
|
||||
if instr.Op() == DELEGATECALL && !homestead {
|
||||
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
|
||||
}
|
||||
|
||||
ret, err := instr.do(program, &pc, env, contract, mem, stack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if instr.halts() {
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
contract.Input = nil
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// validDest checks if the given destination is a valid one given the
|
||||
// destination table of the program
|
||||
func validDest(dests map[uint64]struct{}, dest *big.Int) bool {
|
||||
// PC cannot go beyond len(code) and certainly can't be bigger than 64bits.
|
||||
// Don't bother checking for JUMPDEST in that case.
|
||||
if dest.Cmp(bigMaxUint64) > 0 {
|
||||
return false
|
||||
}
|
||||
_, ok := dests[dest.Uint64()]
|
||||
return ok
|
||||
}
|
||||
|
||||
// jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
|
||||
// the operation. This does not reduce gas or resizes the memory.
|
||||
func jitCalculateGasAndSize(env *Environment, contract *Contract, instr instruction, mem *Memory, stack *Stack) (*big.Int, *big.Int, error) {
|
||||
var (
|
||||
gas = new(big.Int)
|
||||
newMemSize *big.Int = new(big.Int)
|
||||
)
|
||||
err := jitBaseCheck(instr, stack, gas)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// stack Check, memory resize & gas phase
|
||||
switch op := instr.op; op {
|
||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||
n := int(op - SWAP1 + 2)
|
||||
err := stack.require(n)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gas.Set(GasFastestStep)
|
||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||
n := int(op - DUP1 + 1)
|
||||
err := stack.require(n)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gas.Set(GasFastestStep)
|
||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||
n := int(op - LOG0)
|
||||
err := stack.require(n + 2)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||
|
||||
add := new(big.Int)
|
||||
gas.Add(gas, params.LogGas)
|
||||
gas.Add(gas, add.Mul(big.NewInt(int64(n)), params.LogTopicGas))
|
||||
gas.Add(gas, add.Mul(mSize, params.LogDataGas))
|
||||
|
||||
newMemSize = calcMemSize(mStart, mSize)
|
||||
case EXP:
|
||||
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
|
||||
case SSTORE:
|
||||
err := stack.require(2)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var g *big.Int
|
||||
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||
val := env.StateDB.GetState(contract.Address(), common.BigToHash(x))
|
||||
|
||||
// This checks for 3 scenario's and calculates gas accordingly
|
||||
// 1. From a zero-value address to a non-zero value (NEW VALUE)
|
||||
// 2. From a non-zero value address to a zero-value address (DELETE)
|
||||
// 3. From a non-zero to a non-zero (CHANGE)
|
||||
if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
|
||||
g = params.SstoreSetGas
|
||||
} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
|
||||
env.StateDB.AddRefund(params.SstoreRefundGas)
|
||||
|
||||
g = params.SstoreClearGas
|
||||
} else {
|
||||
g = params.SstoreResetGas
|
||||
}
|
||||
gas.Set(g)
|
||||
case SUICIDE:
|
||||
if !env.StateDB.HasSuicided(contract.Address()) {
|
||||
env.StateDB.AddRefund(params.SuicideRefundGas)
|
||||
}
|
||||
case MLOAD:
|
||||
newMemSize = calcMemSize(stack.peek(), u256(32))
|
||||
case MSTORE8:
|
||||
newMemSize = calcMemSize(stack.peek(), u256(1))
|
||||
case MSTORE:
|
||||
newMemSize = calcMemSize(stack.peek(), u256(32))
|
||||
case RETURN:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
|
||||
case SHA3:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-2])
|
||||
gas.Add(gas, words.Mul(words, params.Sha3WordGas))
|
||||
case CALLDATACOPY:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-3])
|
||||
gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
case CODECOPY:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-3])
|
||||
gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
case EXTCODECOPY:
|
||||
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-4])
|
||||
gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
|
||||
case CREATE:
|
||||
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
|
||||
case CALL, CALLCODE:
|
||||
gas.Add(gas, stack.data[stack.len()-1])
|
||||
|
||||
if op == CALL {
|
||||
if !env.StateDB.Exist(common.BigToAddress(stack.data[stack.len()-2])) {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
}
|
||||
|
||||
if len(stack.data[stack.len()-3].Bytes()) > 0 {
|
||||
gas.Add(gas, params.CallValueTransferGas)
|
||||
}
|
||||
|
||||
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
case DELEGATECALL:
|
||||
gas.Add(gas, stack.data[stack.len()-1])
|
||||
|
||||
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
|
||||
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
}
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
|
||||
return newMemSize, gas, nil
|
||||
}
|
||||
|
||||
// jitBaseCheck is the same as baseCheck except it doesn't do the look up in the
|
||||
// gas table. This is done during compilation instead.
|
||||
func jitBaseCheck(instr instruction, stack *Stack, gas *big.Int) error {
|
||||
err := stack.require(instr.spop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if instr.spush > 0 && stack.len()-instr.spop+instr.spush > int(params.StackLimit.Int64()) {
|
||||
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
|
||||
}
|
||||
|
||||
// nil on gas means no base calculation
|
||||
if instr.gas == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
gas.Add(gas, instr.gas)
|
||||
|
||||
return nil
|
||||
}
|
123
vendor/github.com/ethereum/go-ethereum/core/vm/jit_optimiser.go
generated
vendored
123
vendor/github.com/ethereum/go-ethereum/core/vm/jit_optimiser.go
generated
vendored
@ -1,123 +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/>.
|
||||
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
)
|
||||
|
||||
// optimeProgram optimises a JIT program creating segments out of program
|
||||
// instructions. Currently covered are multi-pushes and static jumps
|
||||
func optimiseProgram(program *Program) {
|
||||
var load []instruction
|
||||
|
||||
var (
|
||||
statsJump = 0
|
||||
statsPush = 0
|
||||
)
|
||||
|
||||
if glog.V(logger.Debug) {
|
||||
glog.Infof("optimising %x\n", program.Id[:4])
|
||||
tstart := time.Now()
|
||||
defer func() {
|
||||
glog.Infof("optimised %x done in %v with JMP: %d PSH: %d\n", program.Id[:4], time.Since(tstart), statsJump, statsPush)
|
||||
}()
|
||||
}
|
||||
|
||||
/*
|
||||
code := Parse(program.code)
|
||||
for _, test := range [][]OpCode{
|
||||
[]OpCode{PUSH, PUSH, ADD},
|
||||
[]OpCode{PUSH, PUSH, SUB},
|
||||
[]OpCode{PUSH, PUSH, MUL},
|
||||
[]OpCode{PUSH, PUSH, DIV},
|
||||
} {
|
||||
matchCount := 0
|
||||
MatchFn(code, test, func(i int) bool {
|
||||
matchCount++
|
||||
return true
|
||||
})
|
||||
fmt.Printf("found %d match count on: %v\n", matchCount, test)
|
||||
}
|
||||
*/
|
||||
|
||||
for i := 0; i < len(program.instructions); i++ {
|
||||
instr := program.instructions[i].(instruction)
|
||||
|
||||
switch {
|
||||
case instr.op.IsPush():
|
||||
load = append(load, instr)
|
||||
case instr.op.IsStaticJump():
|
||||
if len(load) == 0 {
|
||||
continue
|
||||
}
|
||||
// if the push load is greater than 1, finalise that
|
||||
// segment first
|
||||
if len(load) > 2 {
|
||||
seg, size := makePushSeg(load[:len(load)-1])
|
||||
program.instructions[i-size-1] = seg
|
||||
statsPush++
|
||||
}
|
||||
// create a segment consisting of a pre determined
|
||||
// jump, destination and validity.
|
||||
seg := makeStaticJumpSeg(load[len(load)-1].data, program)
|
||||
program.instructions[i-1] = seg
|
||||
statsJump++
|
||||
|
||||
load = nil
|
||||
default:
|
||||
// create a new N pushes segment
|
||||
if len(load) > 1 {
|
||||
seg, size := makePushSeg(load)
|
||||
program.instructions[i-size] = seg
|
||||
statsPush++
|
||||
}
|
||||
load = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// makePushSeg creates a new push segment from N amount of push instructions
|
||||
func makePushSeg(instrs []instruction) (pushSeg, int) {
|
||||
var (
|
||||
data []*big.Int
|
||||
gas = new(big.Int)
|
||||
)
|
||||
|
||||
for _, instr := range instrs {
|
||||
data = append(data, instr.data)
|
||||
gas.Add(gas, instr.gas)
|
||||
}
|
||||
|
||||
return pushSeg{data, gas}, len(instrs)
|
||||
}
|
||||
|
||||
// makeStaticJumpSeg creates a new static jump segment from a predefined
|
||||
// destination (PUSH, JUMP).
|
||||
func makeStaticJumpSeg(to *big.Int, program *Program) jumpSeg {
|
||||
gas := new(big.Int)
|
||||
gas.Add(gas, _baseCheck[PUSH1].gas)
|
||||
gas.Add(gas, _baseCheck[JUMP].gas)
|
||||
|
||||
contract := &Contract{Code: program.code}
|
||||
pos, err := jump(program.mapping, program.destinations, contract, to)
|
||||
return jumpSeg{pos, err, gas}
|
||||
}
|
68
vendor/github.com/ethereum/go-ethereum/core/vm/jit_util.go
generated
vendored
68
vendor/github.com/ethereum/go-ethereum/core/vm/jit_util.go
generated
vendored
@ -1,68 +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/>.
|
||||
|
||||
package vm
|
||||
|
||||
// Parse parses all opcodes from the given code byte slice. This function
|
||||
// performs no error checking and may return non-existing opcodes.
|
||||
func Parse(code []byte) (opcodes []OpCode) {
|
||||
for pc := uint64(0); pc < uint64(len(code)); pc++ {
|
||||
op := OpCode(code[pc])
|
||||
|
||||
switch op {
|
||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
||||
a := uint64(op) - uint64(PUSH1) + 1
|
||||
pc += a
|
||||
opcodes = append(opcodes, PUSH)
|
||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||
opcodes = append(opcodes, DUP)
|
||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||
opcodes = append(opcodes, SWAP)
|
||||
default:
|
||||
opcodes = append(opcodes, op)
|
||||
}
|
||||
}
|
||||
|
||||
return opcodes
|
||||
}
|
||||
|
||||
// MatchFn searcher for match in the given input and calls matcheFn if it finds
|
||||
// an appropriate match. matcherFn yields the starting position in the input.
|
||||
// MatchFn will continue to search for a match until it reaches the end of the
|
||||
// buffer or if matcherFn return false.
|
||||
func MatchFn(input, match []OpCode, matcherFn func(int) bool) {
|
||||
// short circuit if either input or match is empty or if the match is
|
||||
// greater than the input
|
||||
if len(input) == 0 || len(match) == 0 || len(match) > len(input) {
|
||||
return
|
||||
}
|
||||
|
||||
main:
|
||||
for i, op := range input[:len(input)+1-len(match)] {
|
||||
// match first opcode and continue search
|
||||
if op == match[0] {
|
||||
for j := 1; j < len(match); j++ {
|
||||
if input[i+j] != match[j] {
|
||||
continue main
|
||||
}
|
||||
}
|
||||
// check for abort instruction
|
||||
if !matcherFn(i) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
970
vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go
generated
vendored
970
vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go
generated
vendored
@ -22,152 +22,838 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
type jumpPtr struct {
|
||||
fn instrFn
|
||||
type (
|
||||
executionFunc func(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
|
||||
gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, *big.Int) *big.Int
|
||||
stackValidationFunc func(*Stack) error
|
||||
memorySizeFunc func(*Stack) *big.Int
|
||||
)
|
||||
|
||||
type operation struct {
|
||||
// op 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
|
||||
// memorySize returns the memory size required for the operation
|
||||
memorySize memorySizeFunc
|
||||
// halts indicates whether the operation shoult halt further execution
|
||||
// and return
|
||||
halts bool
|
||||
// jumps indicates whether operation made a jump. This prevents the program
|
||||
// counter from further incrementing.
|
||||
jumps bool
|
||||
// valid is used to check whether the retrieved operation is valid and known
|
||||
valid bool
|
||||
}
|
||||
|
||||
type vmJumpTable [256]jumpPtr
|
||||
var defaultJumpTable = NewJumpTable()
|
||||
|
||||
func newJumpTable(ruleset *params.ChainConfig, blockNumber *big.Int) vmJumpTable {
|
||||
var jumpTable vmJumpTable
|
||||
func NewJumpTable() [256]operation {
|
||||
return [256]operation{
|
||||
ADD: {
|
||||
execute: opAdd,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
SUB: {
|
||||
execute: opSub,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
MUL: {
|
||||
execute: opMul,
|
||||
gasCost: constGasFunc(GasFastStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
DIV: {
|
||||
execute: opDiv,
|
||||
gasCost: constGasFunc(GasFastStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
SDIV: {
|
||||
execute: opSdiv,
|
||||
gasCost: constGasFunc(GasFastStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
MOD: {
|
||||
execute: opMod,
|
||||
gasCost: constGasFunc(GasFastStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
SMOD: {
|
||||
execute: opSmod,
|
||||
gasCost: constGasFunc(GasFastStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
EXP: {
|
||||
execute: opExp,
|
||||
gasCost: gasExp,
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
SIGNEXTEND: {
|
||||
execute: opSignExtend,
|
||||
gasCost: constGasFunc(GasFastStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
NOT: {
|
||||
execute: opNot,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
LT: {
|
||||
execute: opLt,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
GT: {
|
||||
execute: opGt,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
SLT: {
|
||||
execute: opSlt,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
SGT: {
|
||||
execute: opSgt,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
EQ: {
|
||||
execute: opEq,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
ISZERO: {
|
||||
execute: opIszero,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
AND: {
|
||||
execute: opAnd,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
OR: {
|
||||
execute: opOr,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
XOR: {
|
||||
execute: opXor,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
BYTE: {
|
||||
execute: opByte,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
ADDMOD: {
|
||||
execute: opAddmod,
|
||||
gasCost: constGasFunc(GasMidStep),
|
||||
validateStack: makeStackFunc(3, 1),
|
||||
valid: true,
|
||||
},
|
||||
MULMOD: {
|
||||
execute: opMulmod,
|
||||
gasCost: constGasFunc(GasMidStep),
|
||||
validateStack: makeStackFunc(3, 1),
|
||||
valid: true,
|
||||
},
|
||||
SHA3: {
|
||||
execute: opSha3,
|
||||
gasCost: gasSha3,
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
memorySize: memorySha3,
|
||||
valid: true,
|
||||
},
|
||||
ADDRESS: {
|
||||
execute: opAddress,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
BALANCE: {
|
||||
execute: opBalance,
|
||||
gasCost: gasBalance,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
ORIGIN: {
|
||||
execute: opOrigin,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
CALLER: {
|
||||
execute: opCaller,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
CALLVALUE: {
|
||||
execute: opCallValue,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
CALLDATALOAD: {
|
||||
execute: opCalldataLoad,
|
||||
gasCost: constGasFunc(GasFastestStep),
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
CALLDATASIZE: {
|
||||
execute: opCalldataSize,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
CALLDATACOPY: {
|
||||
execute: opCalldataCopy,
|
||||
gasCost: gasCalldataCopy,
|
||||
validateStack: makeStackFunc(3, 1),
|
||||
memorySize: memoryCalldataCopy,
|
||||
valid: true,
|
||||
},
|
||||
CODESIZE: {
|
||||
execute: opCodeSize,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
EXTCODESIZE: {
|
||||
execute: opExtCodeSize,
|
||||
gasCost: gasExtCodeSize,
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
CODECOPY: {
|
||||
execute: opCodeCopy,
|
||||
gasCost: gasCodeCopy,
|
||||
validateStack: makeStackFunc(3, 0),
|
||||
memorySize: memoryCodeCopy,
|
||||
valid: true,
|
||||
},
|
||||
EXTCODECOPY: {
|
||||
execute: opExtCodeCopy,
|
||||
gasCost: gasExtCodeCopy,
|
||||
validateStack: makeStackFunc(4, 0),
|
||||
memorySize: memoryExtCodeCopy,
|
||||
valid: true,
|
||||
},
|
||||
GASPRICE: {
|
||||
execute: opGasprice,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
BLOCKHASH: {
|
||||
execute: opBlockhash,
|
||||
gasCost: constGasFunc(GasExtStep),
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
COINBASE: {
|
||||
execute: opCoinbase,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
TIMESTAMP: {
|
||||
execute: opTimestamp,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
NUMBER: {
|
||||
execute: opNumber,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
DIFFICULTY: {
|
||||
execute: opDifficulty,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
GASLIMIT: {
|
||||
execute: opGasLimit,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
POP: {
|
||||
execute: opPop,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(1, 0),
|
||||
valid: true,
|
||||
},
|
||||
MLOAD: {
|
||||
execute: opMload,
|
||||
gasCost: gasMLoad,
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
memorySize: memoryMLoad,
|
||||
valid: true,
|
||||
},
|
||||
MSTORE: {
|
||||
execute: opMstore,
|
||||
gasCost: gasMStore,
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
memorySize: memoryMStore,
|
||||
valid: true,
|
||||
},
|
||||
MSTORE8: {
|
||||
execute: opMstore8,
|
||||
gasCost: gasMStore8,
|
||||
memorySize: memoryMStore8,
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
|
||||
// when initialising a new VM execution we must first check the homestead
|
||||
// changes.
|
||||
if ruleset.IsHomestead(blockNumber) {
|
||||
jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
|
||||
valid: true,
|
||||
},
|
||||
SLOAD: {
|
||||
execute: opSload,
|
||||
gasCost: gasSLoad,
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
SSTORE: {
|
||||
execute: opSstore,
|
||||
gasCost: gasSStore,
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
valid: true,
|
||||
},
|
||||
JUMPDEST: {
|
||||
execute: opJumpdest,
|
||||
gasCost: constGasFunc(params.JumpdestGas),
|
||||
validateStack: makeStackFunc(0, 0),
|
||||
valid: true,
|
||||
},
|
||||
PC: {
|
||||
execute: opPc,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
MSIZE: {
|
||||
execute: opMsize,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
GAS: {
|
||||
execute: opGas,
|
||||
gasCost: constGasFunc(GasQuickStep),
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
CREATE: {
|
||||
execute: opCreate,
|
||||
gasCost: gasCreate,
|
||||
validateStack: makeStackFunc(3, 1),
|
||||
memorySize: memoryCreate,
|
||||
valid: true,
|
||||
},
|
||||
CALL: {
|
||||
execute: opCall,
|
||||
gasCost: gasCall,
|
||||
validateStack: makeStackFunc(7, 1),
|
||||
memorySize: memoryCall,
|
||||
valid: true,
|
||||
},
|
||||
CALLCODE: {
|
||||
execute: opCallCode,
|
||||
gasCost: gasCallCode,
|
||||
validateStack: makeStackFunc(7, 1),
|
||||
memorySize: memoryCall,
|
||||
valid: true,
|
||||
},
|
||||
DELEGATECALL: {
|
||||
execute: opDelegateCall,
|
||||
gasCost: gasDelegateCall,
|
||||
validateStack: makeStackFunc(6, 1),
|
||||
memorySize: memoryDelegateCall,
|
||||
valid: true,
|
||||
},
|
||||
RETURN: {
|
||||
execute: opReturn,
|
||||
gasCost: gasReturn,
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
memorySize: memoryReturn,
|
||||
halts: true,
|
||||
valid: true,
|
||||
},
|
||||
SUICIDE: {
|
||||
execute: opSuicide,
|
||||
gasCost: gasSuicide,
|
||||
validateStack: makeStackFunc(1, 0),
|
||||
halts: true,
|
||||
valid: true,
|
||||
},
|
||||
JUMP: {
|
||||
execute: opJump,
|
||||
gasCost: constGasFunc(GasMidStep),
|
||||
validateStack: makeStackFunc(1, 0),
|
||||
jumps: true,
|
||||
valid: true,
|
||||
},
|
||||
JUMPI: {
|
||||
execute: opJumpi,
|
||||
gasCost: constGasFunc(GasSlowStep),
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
jumps: true,
|
||||
valid: true,
|
||||
},
|
||||
STOP: {
|
||||
execute: opStop,
|
||||
gasCost: constGasFunc(Zero),
|
||||
validateStack: makeStackFunc(0, 0),
|
||||
halts: true,
|
||||
valid: true,
|
||||
},
|
||||
LOG0: {
|
||||
execute: makeLog(0),
|
||||
gasCost: makeGasLog(0),
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
memorySize: memoryLog,
|
||||
valid: true,
|
||||
},
|
||||
LOG1: {
|
||||
execute: makeLog(1),
|
||||
gasCost: makeGasLog(1),
|
||||
validateStack: makeStackFunc(3, 0),
|
||||
memorySize: memoryLog,
|
||||
valid: true,
|
||||
},
|
||||
LOG2: {
|
||||
execute: makeLog(2),
|
||||
gasCost: makeGasLog(2),
|
||||
validateStack: makeStackFunc(4, 0),
|
||||
memorySize: memoryLog,
|
||||
valid: true,
|
||||
},
|
||||
LOG3: {
|
||||
execute: makeLog(3),
|
||||
gasCost: makeGasLog(3),
|
||||
validateStack: makeStackFunc(5, 0),
|
||||
memorySize: memoryLog,
|
||||
valid: true,
|
||||
},
|
||||
LOG4: {
|
||||
execute: makeLog(4),
|
||||
gasCost: makeGasLog(4),
|
||||
validateStack: makeStackFunc(6, 0),
|
||||
memorySize: memoryLog,
|
||||
valid: true,
|
||||
},
|
||||
SWAP1: {
|
||||
execute: makeSwap(1),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(2, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP2: {
|
||||
execute: makeSwap(2),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(3, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP3: {
|
||||
execute: makeSwap(3),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(4, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP4: {
|
||||
execute: makeSwap(4),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(5, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP5: {
|
||||
execute: makeSwap(5),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(6, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP6: {
|
||||
execute: makeSwap(6),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(7, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP7: {
|
||||
execute: makeSwap(7),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(8, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP8: {
|
||||
execute: makeSwap(8),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(9, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP9: {
|
||||
execute: makeSwap(9),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(10, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP10: {
|
||||
execute: makeSwap(10),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(11, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP11: {
|
||||
execute: makeSwap(11),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(12, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP12: {
|
||||
execute: makeSwap(12),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(13, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP13: {
|
||||
execute: makeSwap(13),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(14, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP14: {
|
||||
execute: makeSwap(14),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(15, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP15: {
|
||||
execute: makeSwap(15),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(16, 0),
|
||||
valid: true,
|
||||
},
|
||||
SWAP16: {
|
||||
execute: makeSwap(16),
|
||||
gasCost: gasSwap,
|
||||
validateStack: makeStackFunc(17, 0),
|
||||
valid: true,
|
||||
},
|
||||
PUSH1: {
|
||||
execute: makePush(1, big.NewInt(1)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH2: {
|
||||
execute: makePush(2, big.NewInt(2)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH3: {
|
||||
execute: makePush(3, big.NewInt(3)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH4: {
|
||||
execute: makePush(4, big.NewInt(4)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH5: {
|
||||
execute: makePush(5, big.NewInt(5)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH6: {
|
||||
execute: makePush(6, big.NewInt(6)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH7: {
|
||||
execute: makePush(7, big.NewInt(7)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH8: {
|
||||
execute: makePush(8, big.NewInt(8)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH9: {
|
||||
execute: makePush(9, big.NewInt(9)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH10: {
|
||||
execute: makePush(10, big.NewInt(10)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH11: {
|
||||
execute: makePush(11, big.NewInt(11)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH12: {
|
||||
execute: makePush(12, big.NewInt(12)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH13: {
|
||||
execute: makePush(13, big.NewInt(13)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH14: {
|
||||
execute: makePush(14, big.NewInt(14)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH15: {
|
||||
execute: makePush(15, big.NewInt(15)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH16: {
|
||||
execute: makePush(16, big.NewInt(16)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH17: {
|
||||
execute: makePush(17, big.NewInt(17)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH18: {
|
||||
execute: makePush(18, big.NewInt(18)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH19: {
|
||||
execute: makePush(19, big.NewInt(19)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH20: {
|
||||
execute: makePush(20, big.NewInt(20)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH21: {
|
||||
execute: makePush(21, big.NewInt(21)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH22: {
|
||||
execute: makePush(22, big.NewInt(22)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH23: {
|
||||
execute: makePush(23, big.NewInt(23)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH24: {
|
||||
execute: makePush(24, big.NewInt(24)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH25: {
|
||||
execute: makePush(25, big.NewInt(25)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH26: {
|
||||
execute: makePush(26, big.NewInt(26)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH27: {
|
||||
execute: makePush(27, big.NewInt(27)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH28: {
|
||||
execute: makePush(28, big.NewInt(28)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH29: {
|
||||
execute: makePush(29, big.NewInt(29)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH30: {
|
||||
execute: makePush(30, big.NewInt(30)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH31: {
|
||||
execute: makePush(31, big.NewInt(31)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
PUSH32: {
|
||||
execute: makePush(32, big.NewInt(32)),
|
||||
gasCost: gasPush,
|
||||
validateStack: makeStackFunc(0, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP1: {
|
||||
execute: makeDup(1),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(1, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP2: {
|
||||
execute: makeDup(2),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(2, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP3: {
|
||||
execute: makeDup(3),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(3, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP4: {
|
||||
execute: makeDup(4),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(4, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP5: {
|
||||
execute: makeDup(5),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(5, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP6: {
|
||||
execute: makeDup(6),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(6, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP7: {
|
||||
execute: makeDup(7),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(7, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP8: {
|
||||
execute: makeDup(8),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(8, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP9: {
|
||||
execute: makeDup(9),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(9, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP10: {
|
||||
execute: makeDup(10),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(10, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP11: {
|
||||
execute: makeDup(11),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(11, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP12: {
|
||||
execute: makeDup(12),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(12, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP13: {
|
||||
execute: makeDup(13),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(13, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP14: {
|
||||
execute: makeDup(14),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(14, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP15: {
|
||||
execute: makeDup(15),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(15, 1),
|
||||
valid: true,
|
||||
},
|
||||
DUP16: {
|
||||
execute: makeDup(16),
|
||||
gasCost: gasDup,
|
||||
validateStack: makeStackFunc(16, 1),
|
||||
valid: true,
|
||||
},
|
||||
}
|
||||
|
||||
jumpTable[ADD] = jumpPtr{opAdd, true}
|
||||
jumpTable[SUB] = jumpPtr{opSub, true}
|
||||
jumpTable[MUL] = jumpPtr{opMul, true}
|
||||
jumpTable[DIV] = jumpPtr{opDiv, true}
|
||||
jumpTable[SDIV] = jumpPtr{opSdiv, true}
|
||||
jumpTable[MOD] = jumpPtr{opMod, true}
|
||||
jumpTable[SMOD] = jumpPtr{opSmod, true}
|
||||
jumpTable[EXP] = jumpPtr{opExp, true}
|
||||
jumpTable[SIGNEXTEND] = jumpPtr{opSignExtend, true}
|
||||
jumpTable[NOT] = jumpPtr{opNot, true}
|
||||
jumpTable[LT] = jumpPtr{opLt, true}
|
||||
jumpTable[GT] = jumpPtr{opGt, true}
|
||||
jumpTable[SLT] = jumpPtr{opSlt, true}
|
||||
jumpTable[SGT] = jumpPtr{opSgt, true}
|
||||
jumpTable[EQ] = jumpPtr{opEq, true}
|
||||
jumpTable[ISZERO] = jumpPtr{opIszero, true}
|
||||
jumpTable[AND] = jumpPtr{opAnd, true}
|
||||
jumpTable[OR] = jumpPtr{opOr, true}
|
||||
jumpTable[XOR] = jumpPtr{opXor, true}
|
||||
jumpTable[BYTE] = jumpPtr{opByte, true}
|
||||
jumpTable[ADDMOD] = jumpPtr{opAddmod, true}
|
||||
jumpTable[MULMOD] = jumpPtr{opMulmod, true}
|
||||
jumpTable[SHA3] = jumpPtr{opSha3, true}
|
||||
jumpTable[ADDRESS] = jumpPtr{opAddress, true}
|
||||
jumpTable[BALANCE] = jumpPtr{opBalance, true}
|
||||
jumpTable[ORIGIN] = jumpPtr{opOrigin, true}
|
||||
jumpTable[CALLER] = jumpPtr{opCaller, true}
|
||||
jumpTable[CALLVALUE] = jumpPtr{opCallValue, true}
|
||||
jumpTable[CALLDATALOAD] = jumpPtr{opCalldataLoad, true}
|
||||
jumpTable[CALLDATASIZE] = jumpPtr{opCalldataSize, true}
|
||||
jumpTable[CALLDATACOPY] = jumpPtr{opCalldataCopy, true}
|
||||
jumpTable[CODESIZE] = jumpPtr{opCodeSize, true}
|
||||
jumpTable[EXTCODESIZE] = jumpPtr{opExtCodeSize, true}
|
||||
jumpTable[CODECOPY] = jumpPtr{opCodeCopy, true}
|
||||
jumpTable[EXTCODECOPY] = jumpPtr{opExtCodeCopy, true}
|
||||
jumpTable[GASPRICE] = jumpPtr{opGasprice, true}
|
||||
jumpTable[BLOCKHASH] = jumpPtr{opBlockhash, true}
|
||||
jumpTable[COINBASE] = jumpPtr{opCoinbase, true}
|
||||
jumpTable[TIMESTAMP] = jumpPtr{opTimestamp, true}
|
||||
jumpTable[NUMBER] = jumpPtr{opNumber, true}
|
||||
jumpTable[DIFFICULTY] = jumpPtr{opDifficulty, true}
|
||||
jumpTable[GASLIMIT] = jumpPtr{opGasLimit, true}
|
||||
jumpTable[POP] = jumpPtr{opPop, true}
|
||||
jumpTable[MLOAD] = jumpPtr{opMload, true}
|
||||
jumpTable[MSTORE] = jumpPtr{opMstore, true}
|
||||
jumpTable[MSTORE8] = jumpPtr{opMstore8, true}
|
||||
jumpTable[SLOAD] = jumpPtr{opSload, true}
|
||||
jumpTable[SSTORE] = jumpPtr{opSstore, true}
|
||||
jumpTable[JUMPDEST] = jumpPtr{opJumpdest, true}
|
||||
jumpTable[PC] = jumpPtr{nil, true}
|
||||
jumpTable[MSIZE] = jumpPtr{opMsize, true}
|
||||
jumpTable[GAS] = jumpPtr{opGas, true}
|
||||
jumpTable[CREATE] = jumpPtr{opCreate, true}
|
||||
jumpTable[CALL] = jumpPtr{opCall, true}
|
||||
jumpTable[CALLCODE] = jumpPtr{opCallCode, true}
|
||||
jumpTable[LOG0] = jumpPtr{makeLog(0), true}
|
||||
jumpTable[LOG1] = jumpPtr{makeLog(1), true}
|
||||
jumpTable[LOG2] = jumpPtr{makeLog(2), true}
|
||||
jumpTable[LOG3] = jumpPtr{makeLog(3), true}
|
||||
jumpTable[LOG4] = jumpPtr{makeLog(4), true}
|
||||
jumpTable[SWAP1] = jumpPtr{makeSwap(1), true}
|
||||
jumpTable[SWAP2] = jumpPtr{makeSwap(2), true}
|
||||
jumpTable[SWAP3] = jumpPtr{makeSwap(3), true}
|
||||
jumpTable[SWAP4] = jumpPtr{makeSwap(4), true}
|
||||
jumpTable[SWAP5] = jumpPtr{makeSwap(5), true}
|
||||
jumpTable[SWAP6] = jumpPtr{makeSwap(6), true}
|
||||
jumpTable[SWAP7] = jumpPtr{makeSwap(7), true}
|
||||
jumpTable[SWAP8] = jumpPtr{makeSwap(8), true}
|
||||
jumpTable[SWAP9] = jumpPtr{makeSwap(9), true}
|
||||
jumpTable[SWAP10] = jumpPtr{makeSwap(10), true}
|
||||
jumpTable[SWAP11] = jumpPtr{makeSwap(11), true}
|
||||
jumpTable[SWAP12] = jumpPtr{makeSwap(12), true}
|
||||
jumpTable[SWAP13] = jumpPtr{makeSwap(13), true}
|
||||
jumpTable[SWAP14] = jumpPtr{makeSwap(14), true}
|
||||
jumpTable[SWAP15] = jumpPtr{makeSwap(15), true}
|
||||
jumpTable[SWAP16] = jumpPtr{makeSwap(16), true}
|
||||
jumpTable[PUSH1] = jumpPtr{makePush(1, big.NewInt(1)), true}
|
||||
jumpTable[PUSH2] = jumpPtr{makePush(2, big.NewInt(2)), true}
|
||||
jumpTable[PUSH3] = jumpPtr{makePush(3, big.NewInt(3)), true}
|
||||
jumpTable[PUSH4] = jumpPtr{makePush(4, big.NewInt(4)), true}
|
||||
jumpTable[PUSH5] = jumpPtr{makePush(5, big.NewInt(5)), true}
|
||||
jumpTable[PUSH6] = jumpPtr{makePush(6, big.NewInt(6)), true}
|
||||
jumpTable[PUSH7] = jumpPtr{makePush(7, big.NewInt(7)), true}
|
||||
jumpTable[PUSH8] = jumpPtr{makePush(8, big.NewInt(8)), true}
|
||||
jumpTable[PUSH9] = jumpPtr{makePush(9, big.NewInt(9)), true}
|
||||
jumpTable[PUSH10] = jumpPtr{makePush(10, big.NewInt(10)), true}
|
||||
jumpTable[PUSH11] = jumpPtr{makePush(11, big.NewInt(11)), true}
|
||||
jumpTable[PUSH12] = jumpPtr{makePush(12, big.NewInt(12)), true}
|
||||
jumpTable[PUSH13] = jumpPtr{makePush(13, big.NewInt(13)), true}
|
||||
jumpTable[PUSH14] = jumpPtr{makePush(14, big.NewInt(14)), true}
|
||||
jumpTable[PUSH15] = jumpPtr{makePush(15, big.NewInt(15)), true}
|
||||
jumpTable[PUSH16] = jumpPtr{makePush(16, big.NewInt(16)), true}
|
||||
jumpTable[PUSH17] = jumpPtr{makePush(17, big.NewInt(17)), true}
|
||||
jumpTable[PUSH18] = jumpPtr{makePush(18, big.NewInt(18)), true}
|
||||
jumpTable[PUSH19] = jumpPtr{makePush(19, big.NewInt(19)), true}
|
||||
jumpTable[PUSH20] = jumpPtr{makePush(20, big.NewInt(20)), true}
|
||||
jumpTable[PUSH21] = jumpPtr{makePush(21, big.NewInt(21)), true}
|
||||
jumpTable[PUSH22] = jumpPtr{makePush(22, big.NewInt(22)), true}
|
||||
jumpTable[PUSH23] = jumpPtr{makePush(23, big.NewInt(23)), true}
|
||||
jumpTable[PUSH24] = jumpPtr{makePush(24, big.NewInt(24)), true}
|
||||
jumpTable[PUSH25] = jumpPtr{makePush(25, big.NewInt(25)), true}
|
||||
jumpTable[PUSH26] = jumpPtr{makePush(26, big.NewInt(26)), true}
|
||||
jumpTable[PUSH27] = jumpPtr{makePush(27, big.NewInt(27)), true}
|
||||
jumpTable[PUSH28] = jumpPtr{makePush(28, big.NewInt(28)), true}
|
||||
jumpTable[PUSH29] = jumpPtr{makePush(29, big.NewInt(29)), true}
|
||||
jumpTable[PUSH30] = jumpPtr{makePush(30, big.NewInt(30)), true}
|
||||
jumpTable[PUSH31] = jumpPtr{makePush(31, big.NewInt(31)), true}
|
||||
jumpTable[PUSH32] = jumpPtr{makePush(32, big.NewInt(32)), true}
|
||||
jumpTable[DUP1] = jumpPtr{makeDup(1), true}
|
||||
jumpTable[DUP2] = jumpPtr{makeDup(2), true}
|
||||
jumpTable[DUP3] = jumpPtr{makeDup(3), true}
|
||||
jumpTable[DUP4] = jumpPtr{makeDup(4), true}
|
||||
jumpTable[DUP5] = jumpPtr{makeDup(5), true}
|
||||
jumpTable[DUP6] = jumpPtr{makeDup(6), true}
|
||||
jumpTable[DUP7] = jumpPtr{makeDup(7), true}
|
||||
jumpTable[DUP8] = jumpPtr{makeDup(8), true}
|
||||
jumpTable[DUP9] = jumpPtr{makeDup(9), true}
|
||||
jumpTable[DUP10] = jumpPtr{makeDup(10), true}
|
||||
jumpTable[DUP11] = jumpPtr{makeDup(11), true}
|
||||
jumpTable[DUP12] = jumpPtr{makeDup(12), true}
|
||||
jumpTable[DUP13] = jumpPtr{makeDup(13), true}
|
||||
jumpTable[DUP14] = jumpPtr{makeDup(14), true}
|
||||
jumpTable[DUP15] = jumpPtr{makeDup(15), true}
|
||||
jumpTable[DUP16] = jumpPtr{makeDup(16), true}
|
||||
|
||||
jumpTable[RETURN] = jumpPtr{nil, true}
|
||||
jumpTable[SUICIDE] = jumpPtr{nil, true}
|
||||
jumpTable[JUMP] = jumpPtr{nil, true}
|
||||
jumpTable[JUMPI] = jumpPtr{nil, true}
|
||||
jumpTable[STOP] = jumpPtr{nil, true}
|
||||
|
||||
return jumpTable
|
||||
}
|
||||
|
10
vendor/github.com/ethereum/go-ethereum/core/vm/logger.go
generated
vendored
10
vendor/github.com/ethereum/go-ethereum/core/vm/logger.go
generated
vendored
@ -45,7 +45,7 @@ type LogConfig struct {
|
||||
Limit int // maximum length of output, but zero means unlimited
|
||||
}
|
||||
|
||||
// StructLog is emitted to the Environment each cycle and lists information about the current internal state
|
||||
// StructLog is emitted to the EVM each cycle and lists information about the current internal state
|
||||
// prior to the execution of the statement.
|
||||
type StructLog struct {
|
||||
Pc uint64
|
||||
@ -65,7 +65,7 @@ type StructLog struct {
|
||||
// Note that reference types are actual VM data structures; make copies
|
||||
// if you need to retain them beyond the current call.
|
||||
type Tracer interface {
|
||||
CaptureState(env *Environment, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
|
||||
CaptureState(env *EVM, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
|
||||
}
|
||||
|
||||
// StructLogger is an EVM state logger and implements Tracer.
|
||||
@ -94,10 +94,10 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
|
||||
// captureState logs a new structured log message and pushes it out to the environment
|
||||
//
|
||||
// captureState also tracks SSTORE ops to track dirty values.
|
||||
func (l *StructLogger) CaptureState(env *Environment, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
|
||||
func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
|
||||
// check if already accumulated the specified number of logs
|
||||
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
|
||||
return TraceLimitReachedError
|
||||
return ErrTraceLimitReached
|
||||
}
|
||||
|
||||
// initialise new changed values storage container for this contract
|
||||
@ -155,7 +155,7 @@ func (l *StructLogger) CaptureState(env *Environment, pc uint64, op OpCode, gas,
|
||||
}
|
||||
}
|
||||
// create a new snaptshot of the EVM.
|
||||
log := StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, env.Depth, err}
|
||||
log := StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, env.depth, err}
|
||||
|
||||
l.logs = append(l.logs, log)
|
||||
return nil
|
||||
|
68
vendor/github.com/ethereum/go-ethereum/core/vm/memory_table.go
generated
vendored
Normal file
68
vendor/github.com/ethereum/go-ethereum/core/vm/memory_table.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func memorySha3(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(1))
|
||||
}
|
||||
|
||||
func memoryCalldataCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryCodeCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryExtCodeCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(1), stack.Back(3))
|
||||
}
|
||||
|
||||
func memoryMLoad(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), big.NewInt(32))
|
||||
}
|
||||
|
||||
func memoryMStore8(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), big.NewInt(1))
|
||||
}
|
||||
|
||||
func memoryMStore(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), big.NewInt(32))
|
||||
}
|
||||
|
||||
func memoryCreate(stack *Stack) *big.Int {
|
||||
return calcMemSize(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 common.BigMax(x, y)
|
||||
}
|
||||
|
||||
func memoryCallCode(stack *Stack) *big.Int {
|
||||
x := calcMemSize(stack.Back(5), stack.Back(6))
|
||||
y := calcMemSize(stack.Back(3), stack.Back(4))
|
||||
|
||||
return common.BigMax(x, y)
|
||||
}
|
||||
func memoryDelegateCall(stack *Stack) *big.Int {
|
||||
x := calcMemSize(stack.Back(4), stack.Back(5))
|
||||
y := calcMemSize(stack.Back(2), stack.Back(3))
|
||||
|
||||
return common.BigMax(x, y)
|
||||
}
|
||||
|
||||
func memoryReturn(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)
|
||||
}
|
3
vendor/github.com/ethereum/go-ethereum/core/vm/noop.go
generated
vendored
3
vendor/github.com/ethereum/go-ethereum/core/vm/noop.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
func NoopCanTransfer(db StateDB, from common.Address, balance *big.Int) bool {
|
||||
@ -65,4 +66,4 @@ func (NoopStateDB) Exist(common.Address) bool { return f
|
||||
func (NoopStateDB) Empty(common.Address) bool { return false }
|
||||
func (NoopStateDB) RevertToSnapshot(int) {}
|
||||
func (NoopStateDB) Snapshot() int { return 0 }
|
||||
func (NoopStateDB) AddLog(*Log) {}
|
||||
func (NoopStateDB) AddLog(*types.Log) {}
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/core/vm/runtime/env.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/core/vm/runtime/env.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
)
|
||||
|
||||
func NewEnv(cfg *Config, state *state.StateDB) *vm.Environment {
|
||||
func NewEnv(cfg *Config, state *state.StateDB) *vm.EVM {
|
||||
context := vm.Context{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
@ -40,5 +40,5 @@ func NewEnv(cfg *Config, state *state.StateDB) *vm.Environment {
|
||||
GasPrice: new(big.Int),
|
||||
}
|
||||
|
||||
return vm.NewEnvironment(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
|
||||
return vm.NewEVM(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
|
||||
}
|
||||
|
8
vendor/github.com/ethereum/go-ethereum/core/vm/runtime/runtime.go
generated
vendored
8
vendor/github.com/ethereum/go-ethereum/core/vm/runtime/runtime.go
generated
vendored
@ -28,14 +28,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// The default, always homestead, rule set for the vm env
|
||||
type ruleSet struct{}
|
||||
|
||||
func (ruleSet) IsHomestead(*big.Int) bool { return true }
|
||||
func (ruleSet) GasTable(*big.Int) params.GasTable {
|
||||
return params.GasTableHomesteadGasRepriceFork
|
||||
}
|
||||
|
||||
// Config is a basic type specifying certain configuration flags for running
|
||||
// the EVM.
|
||||
type Config struct {
|
||||
|
60
vendor/github.com/ethereum/go-ethereum/core/vm/segments.go
generated
vendored
60
vendor/github.com/ethereum/go-ethereum/core/vm/segments.go
generated
vendored
@ -1,60 +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/>.
|
||||
|
||||
package vm
|
||||
|
||||
import "math/big"
|
||||
|
||||
type jumpSeg struct {
|
||||
pos uint64
|
||||
err error
|
||||
gas *big.Int
|
||||
}
|
||||
|
||||
func (j jumpSeg) do(program *Program, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
if !contract.UseGas(j.gas) {
|
||||
return nil, OutOfGasError
|
||||
}
|
||||
if j.err != nil {
|
||||
return nil, j.err
|
||||
}
|
||||
*pc = j.pos
|
||||
return nil, nil
|
||||
}
|
||||
func (s jumpSeg) halts() bool { return false }
|
||||
func (s jumpSeg) Op() OpCode { return 0 }
|
||||
|
||||
type pushSeg struct {
|
||||
data []*big.Int
|
||||
gas *big.Int
|
||||
}
|
||||
|
||||
func (s pushSeg) do(program *Program, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
// Use the calculated gas. When insufficient gas is present, use all gas and return an
|
||||
// Out Of Gas error
|
||||
if !contract.UseGas(s.gas) {
|
||||
return nil, OutOfGasError
|
||||
}
|
||||
|
||||
for _, d := range s.data {
|
||||
stack.push(new(big.Int).Set(d))
|
||||
}
|
||||
*pc += uint64(len(s.data))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s pushSeg) halts() bool { return false }
|
||||
func (s pushSeg) Op() OpCode { return 0 }
|
5
vendor/github.com/ethereum/go-ethereum/core/vm/stack.go
generated
vendored
5
vendor/github.com/ethereum/go-ethereum/core/vm/stack.go
generated
vendored
@ -68,6 +68,11 @@ func (st *Stack) peek() *big.Int {
|
||||
return st.data[st.len()-1]
|
||||
}
|
||||
|
||||
// Back returns the n'th item in stack
|
||||
func (st *Stack) Back(n int) *big.Int {
|
||||
return st.data[st.len()-n-1]
|
||||
}
|
||||
|
||||
func (st *Stack) require(n int) error {
|
||||
if st.len() < n {
|
||||
return fmt.Errorf("stack underflow (%d <=> %d)", len(st.data), n)
|
||||
|
20
vendor/github.com/ethereum/go-ethereum/core/vm/stack_table.go
generated
vendored
Normal file
20
vendor/github.com/ethereum/go-ethereum/core/vm/stack_table.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
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 push > 0 && int64(stack.len()-pop+push) > params.StackLimit.Int64() {
|
||||
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
455
vendor/github.com/ethereum/go-ethereum/core/vm/vm.go
generated
vendored
455
vendor/github.com/ethereum/go-ethereum/core/vm/vm.go
generated
vendored
@ -19,6 +19,7 @@ package vm
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -28,9 +29,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// Config are the configuration options for the EVM
|
||||
// Config are the configuration options for the Interpreter
|
||||
type Config struct {
|
||||
// Debug enabled debugging EVM options
|
||||
// Debug enabled debugging Interpreter options
|
||||
Debug bool
|
||||
// EnableJit enabled the JIT VM
|
||||
EnableJit bool
|
||||
@ -38,40 +39,51 @@ type Config struct {
|
||||
ForceJit bool
|
||||
// Tracer is the op code logger
|
||||
Tracer Tracer
|
||||
// NoRecursion disabled EVM call, callcode,
|
||||
// NoRecursion disabled Interpreter call, callcode,
|
||||
// delegate call and create.
|
||||
NoRecursion bool
|
||||
// Disable gas metering
|
||||
DisableGasMetering bool
|
||||
// JumpTable contains the EVM instruction table. This
|
||||
// may me left uninitialised and will be set the default
|
||||
// table.
|
||||
JumpTable [256]operation
|
||||
}
|
||||
|
||||
// EVM is used to run Ethereum based contracts and will utilise the
|
||||
// Interpreter is used to run Ethereum based contracts and will utilise the
|
||||
// passed environment to query external sources for state information.
|
||||
// The EVM will run the byte code VM or JIT VM based on the passed
|
||||
// The Interpreter will run the byte code VM or JIT VM based on the passed
|
||||
// configuration.
|
||||
type EVM struct {
|
||||
env *Environment
|
||||
jumpTable vmJumpTable
|
||||
cfg Config
|
||||
gasTable params.GasTable
|
||||
type Interpreter struct {
|
||||
env *EVM
|
||||
cfg Config
|
||||
gasTable params.GasTable
|
||||
}
|
||||
|
||||
// New returns a new instance of the EVM.
|
||||
func New(env *Environment, cfg Config) *EVM {
|
||||
return &EVM{
|
||||
env: env,
|
||||
jumpTable: newJumpTable(env.ChainConfig(), env.BlockNumber),
|
||||
cfg: cfg,
|
||||
gasTable: env.ChainConfig().GasTable(env.BlockNumber),
|
||||
// NewInterpreter returns a new instance of the Interpreter.
|
||||
func NewInterpreter(env *EVM, cfg Config) *Interpreter {
|
||||
// We use the STOP instruction whether to see
|
||||
// the jump table was initialised. If it was not
|
||||
// we'll set the default jump table.
|
||||
if !cfg.JumpTable[STOP].valid {
|
||||
cfg.JumpTable = defaultJumpTable
|
||||
}
|
||||
|
||||
return &Interpreter{
|
||||
env: env,
|
||||
cfg: cfg,
|
||||
gasTable: env.ChainConfig().GasTable(env.BlockNumber),
|
||||
}
|
||||
}
|
||||
|
||||
// Run loops and evaluates the contract's code with the given input data
|
||||
func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
evm.env.Depth++
|
||||
defer func() { evm.env.Depth-- }()
|
||||
func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
evm.env.depth++
|
||||
defer func() { evm.env.depth-- }()
|
||||
|
||||
if contract.CodeAddr != nil {
|
||||
if p := Precompiled[contract.CodeAddr.Str()]; p != nil {
|
||||
return evm.RunPrecompiled(p, input, contract)
|
||||
if p := PrecompiledContracts[*contract.CodeAddr]; p != nil {
|
||||
return RunPrecompiledContract(p, input, contract)
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,384 +96,91 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||
if codehash == (common.Hash{}) {
|
||||
codehash = crypto.Keccak256Hash(contract.Code)
|
||||
}
|
||||
var program *Program
|
||||
if false {
|
||||
// JIT disabled due to JIT not being Homestead gas reprice ready.
|
||||
|
||||
// If the JIT is enabled check the status of the JIT program,
|
||||
// if it doesn't exist compile a new program in a separate
|
||||
// goroutine or wait for compilation to finish if the JIT is
|
||||
// forced.
|
||||
switch GetProgramStatus(codehash) {
|
||||
case progReady:
|
||||
return RunProgram(GetProgram(codehash), evm.env, contract, input)
|
||||
case progUnknown:
|
||||
if evm.cfg.ForceJit {
|
||||
// Create and compile program
|
||||
program = NewProgram(contract.Code)
|
||||
perr := CompileProgram(program)
|
||||
if perr == nil {
|
||||
return RunProgram(program, evm.env, contract, input)
|
||||
}
|
||||
glog.V(logger.Info).Infoln("error compiling program", err)
|
||||
} else {
|
||||
// create and compile the program. Compilation
|
||||
// is done in a separate goroutine
|
||||
program = NewProgram(contract.Code)
|
||||
go func() {
|
||||
err := CompileProgram(program)
|
||||
if err != nil {
|
||||
glog.V(logger.Info).Infoln("error compiling program", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
caller = contract.caller
|
||||
code = contract.Code
|
||||
instrCount = 0
|
||||
|
||||
op OpCode // current opcode
|
||||
mem = NewMemory() // bound memory
|
||||
stack = newstack() // local stack
|
||||
// For optimisation reason we're using uint64 as the program counter.
|
||||
// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Practically much less so feasible.
|
||||
pc = uint64(0) // program counter
|
||||
|
||||
// jump evaluates and checks whether the given jump destination is a valid one
|
||||
// if valid move the `pc` otherwise return an error.
|
||||
jump = func(from uint64, to *big.Int) error {
|
||||
if !contract.jumpdests.has(codehash, code, to) {
|
||||
nop := contract.GetOp(to.Uint64())
|
||||
return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
|
||||
}
|
||||
|
||||
pc = to.Uint64()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
newMemSize *big.Int
|
||||
cost *big.Int
|
||||
pc = uint64(0) // program counter
|
||||
cost *big.Int
|
||||
)
|
||||
contract.Input = input
|
||||
|
||||
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
|
||||
defer func() {
|
||||
if err != nil && evm.cfg.Debug {
|
||||
evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth, err)
|
||||
evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err)
|
||||
}
|
||||
}()
|
||||
|
||||
if glog.V(logger.Debug) {
|
||||
glog.Infof("running byte VM %x\n", codehash[:4])
|
||||
glog.Infof("evm running: %x\n", codehash[:4])
|
||||
tstart := time.Now()
|
||||
defer func() {
|
||||
glog.Infof("byte VM %x done. time: %v instrc: %v\n", codehash[:4], time.Since(tstart), instrCount)
|
||||
glog.Infof("evm done: %x. time: %v\n", codehash[:4], time.Since(tstart))
|
||||
}()
|
||||
}
|
||||
|
||||
for ; ; instrCount++ {
|
||||
/*
|
||||
if EnableJit && it%100 == 0 {
|
||||
if program != nil && progStatus(atomic.LoadInt32(&program.status)) == progReady {
|
||||
// move execution
|
||||
fmt.Println("moved", it)
|
||||
glog.V(logger.Info).Infoln("Moved execution to JIT")
|
||||
return runProgram(program, pc, mem, stack, evm.env, contract, input)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// The Interpreter main run loop (contextual). This loop runs until either an
|
||||
// explicit STOP, RETURN or SUICIDE is executed, an error accured during
|
||||
// the execution of one of the operations or until the evm.done is set by
|
||||
// the parent context.Context.
|
||||
for atomic.LoadInt32(&evm.env.abort) == 0 {
|
||||
// Get the memory location of pc
|
||||
op = contract.GetOp(pc)
|
||||
//fmt.Printf("OP %d %v\n", op, op)
|
||||
// calculate the new memory size and gas price for the current executing opcode
|
||||
newMemSize, cost, err = calculateGasAndSize(evm.gasTable, evm.env, contract, caller, op, mem, stack)
|
||||
if err != nil {
|
||||
|
||||
// get the operation from the jump table matching the opcode
|
||||
operation := evm.cfg.JumpTable[op]
|
||||
|
||||
// if the op is invalid abort the process and return an error
|
||||
if !operation.valid {
|
||||
return nil, fmt.Errorf("invalid opcode %x", op)
|
||||
}
|
||||
|
||||
// validate the stack and make sure there enough stack items available
|
||||
// to perform the operation
|
||||
if err := operation.validateStack(stack); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use the calculated gas. When insufficient gas is present, use all gas and return an
|
||||
// Out Of Gas error
|
||||
if !contract.UseGas(cost) {
|
||||
return nil, OutOfGasError
|
||||
var memorySize *big.Int
|
||||
// calculate the new memory size and expand the memory to fit
|
||||
// the operation
|
||||
if operation.memorySize != nil {
|
||||
memorySize = operation.memorySize(stack)
|
||||
// memory is expanded in words of 32 bytes. Gas
|
||||
// is also calculated in words.
|
||||
memorySize.Mul(toWordSize(memorySize), big.NewInt(32))
|
||||
}
|
||||
|
||||
if !evm.cfg.DisableGasMetering {
|
||||
// consume the gas and return an error if not enough gas is available.
|
||||
// cost is explicitly set so that the capture state defer method cas get the proper cost
|
||||
cost = operation.gasCost(evm.gasTable, evm.env, contract, stack, mem, memorySize)
|
||||
if !contract.UseGas(cost) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
}
|
||||
if memorySize != nil {
|
||||
mem.Resize(memorySize.Uint64())
|
||||
}
|
||||
|
||||
// Resize the memory calculated previously
|
||||
mem.Resize(newMemSize.Uint64())
|
||||
// Add a log message
|
||||
if evm.cfg.Debug {
|
||||
err = evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err)
|
||||
}
|
||||
|
||||
if opPtr := evm.jumpTable[op]; opPtr.valid {
|
||||
if opPtr.fn != nil {
|
||||
opPtr.fn(instruction{}, &pc, evm.env, contract, mem, stack)
|
||||
} else {
|
||||
switch op {
|
||||
case PC:
|
||||
opPc(instruction{data: new(big.Int).SetUint64(pc)}, &pc, evm.env, contract, mem, stack)
|
||||
case JUMP:
|
||||
if err := jump(pc, stack.pop()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
continue
|
||||
case JUMPI:
|
||||
pos, cond := stack.pop(), stack.pop()
|
||||
|
||||
if cond.Cmp(common.BigTrue) >= 0 {
|
||||
if err := jump(pc, pos); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
case RETURN:
|
||||
offset, size := stack.pop(), stack.pop()
|
||||
ret := mem.GetPtr(offset.Int64(), size.Int64())
|
||||
|
||||
return ret, nil
|
||||
case SUICIDE:
|
||||
opSuicide(instruction{}, nil, evm.env, contract, mem, stack)
|
||||
|
||||
fallthrough
|
||||
case STOP: // Stop the contract
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid opcode %x", op)
|
||||
// execute the operation
|
||||
res, err := operation.execute(&pc, evm.env, contract, mem, stack)
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case operation.halts:
|
||||
return res, nil
|
||||
case !operation.jumps:
|
||||
pc++
|
||||
}
|
||||
|
||||
pc++
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
|
||||
// the operation. This does not reduce gas or resizes the memory.
|
||||
func calculateGasAndSize(gasTable params.GasTable, env *Environment, contract *Contract, caller ContractRef, op OpCode, mem *Memory, stack *Stack) (*big.Int, *big.Int, error) {
|
||||
var (
|
||||
gas = new(big.Int)
|
||||
newMemSize *big.Int = new(big.Int)
|
||||
)
|
||||
err := baseCheck(op, stack, gas)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// stack Check, memory resize & gas phase
|
||||
switch op {
|
||||
case SUICIDE:
|
||||
// EIP150 homestead gas reprice fork:
|
||||
if gasTable.CreateBySuicide != nil {
|
||||
gas.Set(gasTable.Suicide)
|
||||
var (
|
||||
address = common.BigToAddress(stack.data[len(stack.data)-1])
|
||||
eip158 = env.ChainConfig().IsEIP158(env.BlockNumber)
|
||||
)
|
||||
|
||||
if eip158 {
|
||||
// if empty and transfers value
|
||||
if env.StateDB.Empty(address) && env.StateDB.GetBalance(contract.Address()).BitLen() > 0 {
|
||||
gas.Add(gas, gasTable.CreateBySuicide)
|
||||
}
|
||||
} else if !env.StateDB.Exist(address) {
|
||||
gas.Add(gas, gasTable.CreateBySuicide)
|
||||
}
|
||||
}
|
||||
|
||||
if !env.StateDB.HasSuicided(contract.Address()) {
|
||||
env.StateDB.AddRefund(params.SuicideRefundGas)
|
||||
}
|
||||
case EXTCODESIZE:
|
||||
gas.Set(gasTable.ExtcodeSize)
|
||||
case BALANCE:
|
||||
gas.Set(gasTable.Balance)
|
||||
case SLOAD:
|
||||
gas.Set(gasTable.SLoad)
|
||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||
n := int(op - SWAP1 + 2)
|
||||
err := stack.require(n)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gas.Set(GasFastestStep)
|
||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||
n := int(op - DUP1 + 1)
|
||||
err := stack.require(n)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gas.Set(GasFastestStep)
|
||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||
n := int(op - LOG0)
|
||||
err := stack.require(n + 2)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||
|
||||
gas.Add(gas, params.LogGas)
|
||||
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
|
||||
gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
|
||||
|
||||
newMemSize = calcMemSize(mStart, mSize)
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case EXP:
|
||||
expByteLen := int64((stack.data[stack.len()-2].BitLen() + 7) / 8)
|
||||
gas.Add(gas, new(big.Int).Mul(big.NewInt(expByteLen), gasTable.ExpByte))
|
||||
case SSTORE:
|
||||
err := stack.require(2)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var g *big.Int
|
||||
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||
val := env.StateDB.GetState(contract.Address(), common.BigToHash(x))
|
||||
|
||||
// This checks for 3 scenario's and calculates gas accordingly
|
||||
// 1. From a zero-value address to a non-zero value (NEW VALUE)
|
||||
// 2. From a non-zero value address to a zero-value address (DELETE)
|
||||
// 3. From a non-zero to a non-zero (CHANGE)
|
||||
if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
|
||||
// 0 => non 0
|
||||
g = params.SstoreSetGas
|
||||
} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
|
||||
env.StateDB.AddRefund(params.SstoreRefundGas)
|
||||
|
||||
g = params.SstoreClearGas
|
||||
} else {
|
||||
// non 0 => non 0 (or 0 => 0)
|
||||
g = params.SstoreResetGas
|
||||
}
|
||||
gas.Set(g)
|
||||
case MLOAD:
|
||||
newMemSize = calcMemSize(stack.peek(), u256(32))
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case MSTORE8:
|
||||
newMemSize = calcMemSize(stack.peek(), u256(1))
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case MSTORE:
|
||||
newMemSize = calcMemSize(stack.peek(), u256(32))
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case RETURN:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case SHA3:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-2])
|
||||
gas.Add(gas, words.Mul(words, params.Sha3WordGas))
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case CALLDATACOPY:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-3])
|
||||
gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case CODECOPY:
|
||||
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-3])
|
||||
gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case EXTCODECOPY:
|
||||
gas.Set(gasTable.ExtcodeCopy)
|
||||
|
||||
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
|
||||
|
||||
words := toWordSize(stack.data[stack.len()-4])
|
||||
gas.Add(gas, words.Mul(words, params.CopyGas))
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case CREATE:
|
||||
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
case CALL, CALLCODE:
|
||||
gas.Set(gasTable.Calls)
|
||||
|
||||
transfersValue := stack.data[len(stack.data)-3].BitLen() > 0
|
||||
if op == CALL {
|
||||
var (
|
||||
address = common.BigToAddress(stack.data[len(stack.data)-2])
|
||||
eip158 = env.ChainConfig().IsEIP158(env.BlockNumber)
|
||||
)
|
||||
if eip158 {
|
||||
if env.StateDB.Empty(address) && transfersValue {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
} else if !env.StateDB.Exist(address) {
|
||||
gas.Add(gas, params.CallNewAccountGas)
|
||||
}
|
||||
}
|
||||
if transfersValue {
|
||||
gas.Add(gas, params.CallValueTransferGas)
|
||||
}
|
||||
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
|
||||
cg := callGas(gasTable, contract.Gas, gas, stack.data[stack.len()-1])
|
||||
// Replace the stack item with the new gas calculation. This means that
|
||||
// either the original item is left on the stack or the item is replaced by:
|
||||
// (availableGas - gas) * 63 / 64
|
||||
// We replace the stack item so that it's available when the opCall instruction is
|
||||
// called. This information is otherwise lost due to the dependency on *current*
|
||||
// available gas.
|
||||
stack.data[stack.len()-1] = cg
|
||||
gas.Add(gas, cg)
|
||||
|
||||
case DELEGATECALL:
|
||||
gas.Set(gasTable.Calls)
|
||||
|
||||
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
|
||||
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
|
||||
|
||||
newMemSize = common.BigMax(x, y)
|
||||
|
||||
quadMemGas(mem, newMemSize, gas)
|
||||
|
||||
cg := callGas(gasTable, contract.Gas, gas, stack.data[stack.len()-1])
|
||||
// Replace the stack item with the new gas calculation. This means that
|
||||
// either the original item is left on the stack or the item is replaced by:
|
||||
// (availableGas - gas) * 63 / 64
|
||||
// We replace the stack item so that it's available when the opCall instruction is
|
||||
// called.
|
||||
stack.data[stack.len()-1] = cg
|
||||
gas.Add(gas, cg)
|
||||
|
||||
}
|
||||
|
||||
return newMemSize, gas, nil
|
||||
}
|
||||
|
||||
// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
|
||||
func (evm *EVM) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Contract) (ret []byte, err error) {
|
||||
gas := p.Gas(len(input))
|
||||
if contract.UseGas(gas) {
|
||||
ret = p.Call(input)
|
||||
|
||||
return ret, nil
|
||||
} else {
|
||||
return nil, OutOfGasError
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
6
vendor/github.com/ethereum/go-ethereum/core/vm/vm_jit.go
generated
vendored
6
vendor/github.com/ethereum/go-ethereum/core/vm/vm_jit.go
generated
vendored
@ -44,7 +44,7 @@ import (
|
||||
)
|
||||
|
||||
type JitVm struct {
|
||||
env Environment
|
||||
env EVM
|
||||
me ContextRef
|
||||
callerAddr []byte
|
||||
price *big.Int
|
||||
@ -161,7 +161,7 @@ func assert(condition bool, message string) {
|
||||
}
|
||||
}
|
||||
|
||||
func NewJitVm(env Environment) *JitVm {
|
||||
func NewJitVm(env EVM) *JitVm {
|
||||
return &JitVm{env: env}
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ func (self *JitVm) Endl() VirtualMachine {
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *JitVm) Env() Environment {
|
||||
func (self *JitVm) Env() EVM {
|
||||
return self.env
|
||||
}
|
||||
|
||||
|
35
vendor/github.com/ethereum/go-ethereum/crypto/crypto.go
generated
vendored
35
vendor/github.com/ethereum/go-ethereum/crypto/crypto.go
generated
vendored
@ -167,25 +167,19 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
|
||||
return ecdsa.GenerateKey(secp256k1.S256(), rand.Reader)
|
||||
}
|
||||
|
||||
// ValidateSignatureValues verifies whether the signature values are valid with
|
||||
// the given chain rules. The v value is assumed to be either 0 or 1.
|
||||
func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
|
||||
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
|
||||
return false
|
||||
}
|
||||
vint := uint32(v)
|
||||
// reject upper range of s values (ECDSA malleability)
|
||||
// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
|
||||
if homestead && s.Cmp(secp256k1.HalfN) > 0 {
|
||||
return false
|
||||
}
|
||||
// Frontier: allow s to be in full N range
|
||||
if s.Cmp(secp256k1.N) >= 0 {
|
||||
return false
|
||||
}
|
||||
if r.Cmp(secp256k1.N) < 0 && (vint == 27 || vint == 28) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return r.Cmp(secp256k1.N) < 0 && s.Cmp(secp256k1.N) < 0 && (v == 0 || v == 1)
|
||||
}
|
||||
|
||||
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
||||
@ -199,14 +193,13 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
||||
}
|
||||
|
||||
// Sign calculates an ECDSA signature.
|
||||
// This function is susceptible to choosen plaintext attacks that can leak
|
||||
//
|
||||
// This function is susceptible to chosen plaintext attacks that can leak
|
||||
// information about the private key that is used for signing. Callers must
|
||||
// be aware that the given hash cannot be choosen by an adversery. Common
|
||||
// be aware that the given hash cannot be chosen by an adversery. Common
|
||||
// solution is to hash any input before calculating the signature.
|
||||
//
|
||||
// Note: the calculated signature is not Ethereum compliant. The yellow paper
|
||||
// dictates Ethereum singature to have a V value with and offset of 27 v in [27,28].
|
||||
// Use SignEthereum to get an Ethereum compliant signature.
|
||||
// The produced signature is in the [R || S || V] format where V is 0 or 1.
|
||||
func Sign(data []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
|
||||
if len(data) != 32 {
|
||||
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(data))
|
||||
@ -218,20 +211,6 @@ func Sign(data []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// SignEthereum calculates an Ethereum ECDSA signature.
|
||||
// This function is susceptible to choosen plaintext attacks that can leak
|
||||
// information about the private key that is used for signing. Callers must
|
||||
// be aware that the given hash cannot be freely choosen by an adversery.
|
||||
// Common solution is to hash the message before calculating the signature.
|
||||
func SignEthereum(data []byte, prv *ecdsa.PrivateKey) ([]byte, error) {
|
||||
sig, err := Sign(data, prv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig[64] += 27 // as described in the yellow paper
|
||||
return sig, err
|
||||
}
|
||||
|
||||
func Encrypt(pub *ecdsa.PublicKey, message []byte) ([]byte, error) {
|
||||
return ecies.Encrypt(rand.Reader, ecies.ImportECDSAPublic(pub), message, nil, nil)
|
||||
}
|
||||
|
12
vendor/github.com/ethereum/go-ethereum/crypto/ecies/asn1.go
generated
vendored
12
vendor/github.com/ethereum/go-ethereum/crypto/ecies/asn1.go
generated
vendored
@ -109,7 +109,7 @@ func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool {
|
||||
if len(curve) != len(curve2) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range curve {
|
||||
for i := range curve {
|
||||
if curve[i] != curve2[i] {
|
||||
return false
|
||||
}
|
||||
@ -157,7 +157,7 @@ func (a asnAlgorithmIdentifier) Cmp(b asnAlgorithmIdentifier) bool {
|
||||
if len(a.Algorithm) != len(b.Algorithm) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range a.Algorithm {
|
||||
for i := range a.Algorithm {
|
||||
if a.Algorithm[i] != b.Algorithm[i] {
|
||||
return false
|
||||
}
|
||||
@ -306,7 +306,7 @@ func (a asnECDHAlgorithm) Cmp(b asnECDHAlgorithm) bool {
|
||||
if len(a.Algorithm) != len(b.Algorithm) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range a.Algorithm {
|
||||
for i := range a.Algorithm {
|
||||
if a.Algorithm[i] != b.Algorithm[i] {
|
||||
return false
|
||||
}
|
||||
@ -325,7 +325,7 @@ func (a asnKeyDerivationFunction) Cmp(b asnKeyDerivationFunction) bool {
|
||||
if len(a.Algorithm) != len(b.Algorithm) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range a.Algorithm {
|
||||
for i := range a.Algorithm {
|
||||
if a.Algorithm[i] != b.Algorithm[i] {
|
||||
return false
|
||||
}
|
||||
@ -360,7 +360,7 @@ func (a asnSymmetricEncryption) Cmp(b asnSymmetricEncryption) bool {
|
||||
if len(a.Algorithm) != len(b.Algorithm) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range a.Algorithm {
|
||||
for i := range a.Algorithm {
|
||||
if a.Algorithm[i] != b.Algorithm[i] {
|
||||
return false
|
||||
}
|
||||
@ -380,7 +380,7 @@ func (a asnMessageAuthenticationCode) Cmp(b asnMessageAuthenticationCode) bool {
|
||||
if len(a.Algorithm) != len(b.Algorithm) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range a.Algorithm {
|
||||
for i := range a.Algorithm {
|
||||
if a.Algorithm[i] != b.Algorithm[i] {
|
||||
return false
|
||||
}
|
||||
|
7
vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go
generated
vendored
7
vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go
generated
vendored
@ -93,7 +93,7 @@ func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
|
||||
}
|
||||
|
||||
// Generate an elliptic curve public / private keypair. If params is nil,
|
||||
// the recommended default paramters for the key will be chosen.
|
||||
// the recommended default parameters for the key will be chosen.
|
||||
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
|
||||
pb, x, y, err := elliptic.GenerateKey(curve, rand)
|
||||
if err != nil {
|
||||
@ -291,9 +291,8 @@ 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) {
|
||||
if c == nil || len(c) == 0 {
|
||||
err = ErrInvalidMessage
|
||||
return
|
||||
if len(c) == 0 {
|
||||
return nil, ErrInvalidMessage
|
||||
}
|
||||
params := prv.PublicKey.Params
|
||||
if params == nil {
|
||||
|
@ -99,7 +99,7 @@ SECP256K1_API int secp256k1_schnorr_generate_nonce_pair(
|
||||
/** Produce a partial Schnorr signature, which can be combined using
|
||||
* secp256k1_schnorr_partial_combine, to end up with a full signature that is
|
||||
* verifiable using secp256k1_schnorr_verify.
|
||||
* Returns: 1: signature created succesfully.
|
||||
* Returns: 1: signature created successfully.
|
||||
* 0: no valid signature exists with this combination of keys, nonces
|
||||
* and message (chance around 1 in 2^128)
|
||||
* -1: invalid private key, nonce, or public nonces.
|
||||
@ -148,7 +148,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_sign(
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
|
||||
|
||||
/** Combine multiple Schnorr partial signatures.
|
||||
* Returns: 1: the passed signatures were succesfully combined.
|
||||
* Returns: 1: the passed signatures were successfully combined.
|
||||
* 0: the resulting signature is not valid (chance of 1 in 2^256)
|
||||
* -1: some inputs were invalid, or the signatures were not created
|
||||
* using the same set of nonces
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/notes.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/notes.go
generated
vendored
@ -163,7 +163,7 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
|
||||
int *recid);
|
||||
|
||||
* Recover an ECDSA public key from a compact signature.
|
||||
* Returns: 1: public key succesfully recovered (which guarantees a correct signature).
|
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
|
||||
* 0: otherwise.
|
||||
* In: msg: the message assumed to be signed
|
||||
* msglen: the length of the message
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/secp256.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/secp256.go
generated
vendored
@ -49,7 +49,7 @@ import (
|
||||
|
||||
/*
|
||||
TODO:
|
||||
> store private keys in buffer and shuffle (deters persistance on swap disc)
|
||||
> store private keys in buffer and shuffle (deters persistence on swap disc)
|
||||
> byte permutation (changing)
|
||||
> xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?)
|
||||
*/
|
||||
|
22
vendor/github.com/ethereum/go-ethereum/errs/errors.go
generated
vendored
22
vendor/github.com/ethereum/go-ethereum/errs/errors.go
generated
vendored
@ -19,7 +19,6 @@ package errs
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
)
|
||||
|
||||
@ -32,15 +31,10 @@ Fields:
|
||||
|
||||
Package:
|
||||
name of the package/component
|
||||
|
||||
Level:
|
||||
a function mapping error code to logger.LogLevel (severity)
|
||||
if not given, errors default to logger.InfoLevel
|
||||
*/
|
||||
type Errors struct {
|
||||
Errors map[int]string
|
||||
Package string
|
||||
Level func(code int) logger.LogLevel
|
||||
}
|
||||
|
||||
/*
|
||||
@ -58,7 +52,6 @@ type Error struct {
|
||||
Code int
|
||||
Name string
|
||||
Package string
|
||||
level logger.LogLevel
|
||||
message string
|
||||
format string
|
||||
params []interface{}
|
||||
@ -69,15 +62,10 @@ func (self *Errors) New(code int, format string, params ...interface{}) *Error {
|
||||
if !ok {
|
||||
panic("invalid error code")
|
||||
}
|
||||
level := logger.InfoLevel
|
||||
if self.Level != nil {
|
||||
level = self.Level(code)
|
||||
}
|
||||
return &Error{
|
||||
Code: code,
|
||||
Name: name,
|
||||
Package: self.Package,
|
||||
level: level,
|
||||
format: format,
|
||||
params: params,
|
||||
}
|
||||
@ -98,13 +86,3 @@ func (self Error) Log(v glog.Verbose) {
|
||||
v.Infoln(self)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
err.Fatal() is true if err's severity level is 0 or 1 (logger.ErrorLevel or logger.Silence)
|
||||
*/
|
||||
func (self *Error) Fatal() (fatal bool) {
|
||||
if self.level < logger.WarnLevel {
|
||||
fatal = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
59
vendor/github.com/ethereum/go-ethereum/eth/api.go
generated
vendored
59
vendor/github.com/ethereum/go-ethereum/eth/api.go
generated
vendored
@ -18,6 +18,7 @@ package eth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -25,10 +26,12 @@ import (
|
||||
"math/big"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/ethash"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
@ -67,8 +70,8 @@ func (s *PublicEthereumAPI) Coinbase() (common.Address, error) {
|
||||
}
|
||||
|
||||
// Hashrate returns the POW hashrate
|
||||
func (s *PublicEthereumAPI) Hashrate() *rpc.HexNumber {
|
||||
return rpc.NewHexNumber(s.e.Miner().HashRate())
|
||||
func (s *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
|
||||
return hexutil.Uint64(s.e.Miner().HashRate())
|
||||
}
|
||||
|
||||
// PublicMinerAPI provides an API to control the miner.
|
||||
@ -80,7 +83,7 @@ type PublicMinerAPI struct {
|
||||
|
||||
// NewPublicMinerAPI create a new PublicMinerAPI instance.
|
||||
func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI {
|
||||
agent := miner.NewRemoteAgent()
|
||||
agent := miner.NewRemoteAgent(e.Pow())
|
||||
e.Miner().Register(agent)
|
||||
|
||||
return &PublicMinerAPI{e, agent}
|
||||
@ -93,8 +96,8 @@ func (s *PublicMinerAPI) Mining() bool {
|
||||
|
||||
// SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was
|
||||
// accepted. Note, this is not an indication if the provided work was valid!
|
||||
func (s *PublicMinerAPI) SubmitWork(nonce rpc.HexNumber, solution, digest common.Hash) bool {
|
||||
return s.agent.SubmitWork(nonce.Uint64(), digest, solution)
|
||||
func (s *PublicMinerAPI) SubmitWork(nonce hexutil.Uint64, solution, digest common.Hash) bool {
|
||||
return s.agent.SubmitWork(uint64(nonce), digest, solution)
|
||||
}
|
||||
|
||||
// GetWork returns a work package for external miner. The work package consists of 3 strings
|
||||
@ -117,8 +120,8 @@ func (s *PublicMinerAPI) GetWork() (work [3]string, err error) {
|
||||
// SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined
|
||||
// hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which
|
||||
// must be unique between nodes.
|
||||
func (s *PublicMinerAPI) SubmitHashrate(hashrate rpc.HexNumber, id common.Hash) bool {
|
||||
s.agent.SubmitHashrate(id, hashrate.Uint64())
|
||||
func (s *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool {
|
||||
s.agent.SubmitHashrate(id, uint64(hashrate))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -135,18 +138,15 @@ func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI {
|
||||
|
||||
// Start the miner with the given number of threads. If threads is nil the number of
|
||||
// workers started is equal to the number of logical CPU's that are usable by this process.
|
||||
func (s *PrivateMinerAPI) Start(threads *rpc.HexNumber) (bool, error) {
|
||||
func (s *PrivateMinerAPI) Start(threads *int) (bool, error) {
|
||||
s.e.StartAutoDAG()
|
||||
|
||||
var err error
|
||||
if threads == nil {
|
||||
threads = rpc.NewHexNumber(runtime.NumCPU())
|
||||
err = s.e.StartMining(runtime.NumCPU())
|
||||
} else {
|
||||
err = s.e.StartMining(*threads)
|
||||
}
|
||||
|
||||
err := s.e.StartMining(threads.Int())
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
// Stop the miner
|
||||
@ -164,8 +164,8 @@ func (s *PrivateMinerAPI) SetExtra(extra string) (bool, error) {
|
||||
}
|
||||
|
||||
// SetGasPrice sets the minimum accepted gas price for the miner.
|
||||
func (s *PrivateMinerAPI) SetGasPrice(gasPrice rpc.HexNumber) bool {
|
||||
s.e.Miner().SetGasPrice(gasPrice.BigInt())
|
||||
func (s *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
|
||||
s.e.Miner().SetGasPrice((*big.Int)(&gasPrice))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -217,8 +217,14 @@ func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
var writer io.Writer = out
|
||||
if strings.HasSuffix(file, ".gz") {
|
||||
writer = gzip.NewWriter(writer)
|
||||
defer writer.(*gzip.Writer).Close()
|
||||
}
|
||||
|
||||
// Export the blockchain
|
||||
if err := api.eth.BlockChain().Export(out); err != nil {
|
||||
if err := api.eth.BlockChain().Export(writer); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
@ -243,8 +249,15 @@ func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
var reader io.Reader = in
|
||||
if strings.HasSuffix(file, ".gz") {
|
||||
if reader, err = gzip.NewReader(reader); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Run actual the import in pre-configured batches
|
||||
stream := rlp.NewStream(in, 0)
|
||||
stream := rlp.NewStream(reader, 0)
|
||||
|
||||
blocks, index := make([]*types.Block, 0, 2500), 0
|
||||
for batch := 0; ; batch++ {
|
||||
@ -422,7 +435,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConf
|
||||
return true, structLogger.StructLogs(), nil
|
||||
}
|
||||
|
||||
// callmsg is the message type used for call transations.
|
||||
// callmsg is the message type used for call transitions.
|
||||
type callmsg struct {
|
||||
addr common.Address
|
||||
to *common.Address
|
||||
@ -519,7 +532,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
|
||||
|
||||
// Mutate the state if we haven't reached the tracing transaction yet
|
||||
if uint64(idx) < txIndex {
|
||||
vmenv := vm.NewEnvironment(context, stateDb, api.config, vm.Config{})
|
||||
vmenv := vm.NewEVM(context, stateDb, api.config, vm.Config{})
|
||||
_, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("mutation failed: %v", err)
|
||||
@ -528,7 +541,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
|
||||
continue
|
||||
}
|
||||
|
||||
vmenv := vm.NewEnvironment(context, stateDb, api.config, vm.Config{Debug: true, Tracer: tracer})
|
||||
vmenv := vm.NewEVM(context, stateDb, api.config, vm.Config{Debug: true, Tracer: tracer})
|
||||
ret, gas, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tracing failed: %v", err)
|
||||
|
26
vendor/github.com/ethereum/go-ethereum/eth/api_backend.go
generated
vendored
26
vendor/github.com/ethereum/go-ethereum/eth/api_backend.go
generated
vendored
@ -31,14 +31,19 @@ import (
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
rpc "github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// EthApiBackend implements ethapi.Backend for full nodes
|
||||
type EthApiBackend struct {
|
||||
eth *Ethereum
|
||||
gpo *gasprice.GasPriceOracle
|
||||
eth *Ethereum
|
||||
gpo *gasprice.GasPriceOracle
|
||||
statusBackend *ethapi.StatusBackend
|
||||
}
|
||||
|
||||
func (b *EthApiBackend) GetStatusBackend() *ethapi.StatusBackend {
|
||||
return b.statusBackend
|
||||
}
|
||||
|
||||
func (b *EthApiBackend) ChainConfig() *params.ChainConfig {
|
||||
@ -106,14 +111,14 @@ func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int {
|
||||
return b.eth.blockchain.GetTdByHash(blockHash)
|
||||
}
|
||||
|
||||
func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header) (*vm.Environment, func() error, error) {
|
||||
func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header) (*vm.EVM, func() error, error) {
|
||||
statedb := state.(EthApiState).state
|
||||
from := statedb.GetOrNewStateObject(msg.From())
|
||||
from.SetBalance(common.MaxBig)
|
||||
vmError := func() error { return nil }
|
||||
|
||||
context := core.NewEVMContext(msg, header, b.eth.BlockChain())
|
||||
return vm.NewEnvironment(context, statedb, b.eth.chainConfig, vm.Config{}), vmError, nil
|
||||
return vm.NewEVM(context, statedb, b.eth.chainConfig, vm.Config{}), vmError, nil
|
||||
}
|
||||
|
||||
func (b *EthApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
||||
@ -131,15 +136,20 @@ func (b *EthApiBackend) RemoveTx(txHash common.Hash) {
|
||||
b.eth.txPool.Remove(txHash)
|
||||
}
|
||||
|
||||
func (b *EthApiBackend) GetPoolTransactions() types.Transactions {
|
||||
func (b *EthApiBackend) GetPoolTransactions() (types.Transactions, error) {
|
||||
b.eth.txMu.Lock()
|
||||
defer b.eth.txMu.Unlock()
|
||||
|
||||
pending, err := b.eth.txPool.Pending()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var txs types.Transactions
|
||||
for _, batch := range b.eth.txPool.Pending() {
|
||||
for _, batch := range pending {
|
||||
txs = append(txs, batch...)
|
||||
}
|
||||
return txs
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
func (b *EthApiBackend) GetPoolTransaction(hash common.Hash) *types.Transaction {
|
||||
|
16
vendor/github.com/ethereum/go-ethereum/eth/backend.go
generated
vendored
16
vendor/github.com/ethereum/go-ethereum/eth/backend.go
generated
vendored
@ -45,6 +45,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
@ -79,6 +80,7 @@ type Config struct {
|
||||
NatSpec bool
|
||||
DocRoot string
|
||||
AutoDAG bool
|
||||
PowFake bool
|
||||
PowTest bool
|
||||
PowShared bool
|
||||
ExtraData []byte
|
||||
@ -124,7 +126,7 @@ type Ethereum struct {
|
||||
chainDb ethdb.Database // Block chain database
|
||||
|
||||
eventMux *event.TypeMux
|
||||
pow *ethash.Ethash
|
||||
pow pow.PoW
|
||||
accountManager *accounts.Manager
|
||||
|
||||
ApiBackend *EthApiBackend
|
||||
@ -138,7 +140,6 @@ type Ethereum struct {
|
||||
solcPath string
|
||||
|
||||
NatSpec bool
|
||||
PowTest bool
|
||||
netVersionId int
|
||||
netRPCService *ethapi.PublicNetAPI
|
||||
}
|
||||
@ -172,7 +173,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||
stopDbUpgrade: stopDbUpgrade,
|
||||
netVersionId: config.NetworkId,
|
||||
NatSpec: config.NatSpec,
|
||||
PowTest: config.PowTest,
|
||||
etherbase: config.Etherbase,
|
||||
MinerThreads: config.MinerThreads,
|
||||
AutoDAG: config.AutoDAG,
|
||||
@ -253,7 +253,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||
GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
|
||||
}
|
||||
gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
|
||||
eth.ApiBackend = &EthApiBackend{eth, gpo}
|
||||
eth.ApiBackend = &EthApiBackend{eth, gpo, nil}
|
||||
|
||||
return eth, nil
|
||||
}
|
||||
@ -291,15 +291,17 @@ func SetupGenesisBlock(chainDb *ethdb.Database, config *Config) error {
|
||||
}
|
||||
|
||||
// CreatePoW creates the required type of PoW instance for an Ethereum service
|
||||
func CreatePoW(config *Config) (*ethash.Ethash, error) {
|
||||
func CreatePoW(config *Config) (pow.PoW, error) {
|
||||
switch {
|
||||
case config.PowFake:
|
||||
glog.V(logger.Info).Infof("ethash used in fake mode")
|
||||
return pow.PoW(core.FakePow{}), nil
|
||||
case config.PowTest:
|
||||
glog.V(logger.Info).Infof("ethash used in test mode")
|
||||
return ethash.NewForTesting()
|
||||
case config.PowShared:
|
||||
glog.V(logger.Info).Infof("ethash used in shared mode")
|
||||
return ethash.NewShared(), nil
|
||||
|
||||
default:
|
||||
return ethash.New(), nil
|
||||
}
|
||||
@ -397,7 +399,7 @@ func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager
|
||||
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
|
||||
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
|
||||
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
|
||||
func (s *Ethereum) Pow() *ethash.Ethash { return s.pow }
|
||||
func (s *Ethereum) Pow() pow.PoW { return s.pow }
|
||||
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
|
||||
func (s *Ethereum) IsListening() bool { return true } // Always listening
|
||||
func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
|
||||
|
20
vendor/github.com/ethereum/go-ethereum/eth/bind.go
generated
vendored
20
vendor/github.com/ethereum/go-ethereum/eth/bind.go
generated
vendored
@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@ -83,16 +84,16 @@ func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs {
|
||||
args := ethapi.CallArgs{
|
||||
To: msg.To,
|
||||
From: msg.From,
|
||||
Data: common.ToHex(msg.Data),
|
||||
Data: msg.Data,
|
||||
}
|
||||
if msg.Gas != nil {
|
||||
args.Gas = *rpc.NewHexNumber(msg.Gas)
|
||||
args.Gas = hexutil.Big(*msg.Gas)
|
||||
}
|
||||
if msg.GasPrice != nil {
|
||||
args.GasPrice = *rpc.NewHexNumber(msg.GasPrice)
|
||||
args.GasPrice = hexutil.Big(*msg.GasPrice)
|
||||
}
|
||||
if msg.Value != nil {
|
||||
args.Value = *rpc.NewHexNumber(msg.Value)
|
||||
args.Value = hexutil.Big(*msg.Value)
|
||||
}
|
||||
return args
|
||||
}
|
||||
@ -106,9 +107,12 @@ func toBlockNumber(num *big.Int) rpc.BlockNumber {
|
||||
|
||||
// PendingAccountNonce implements bind.ContractTransactor retrieving the current
|
||||
// pending nonce associated with an account.
|
||||
func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
|
||||
func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (nonce uint64, err error) {
|
||||
out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber)
|
||||
return out.Uint64(), err
|
||||
if out != nil {
|
||||
nonce = uint64(*out)
|
||||
}
|
||||
return nonce, err
|
||||
}
|
||||
|
||||
// SuggestGasPrice implements bind.ContractTransactor retrieving the currently
|
||||
@ -124,13 +128,13 @@ func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error)
|
||||
// should provide a basis for setting a reasonable default.
|
||||
func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) {
|
||||
out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg))
|
||||
return out.BigInt(), err
|
||||
return out.ToInt(), err
|
||||
}
|
||||
|
||||
// SendTransaction implements bind.ContractTransactor injects the transaction
|
||||
// into the pending pool for execution.
|
||||
func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
|
||||
raw, _ := rlp.EncodeToBytes(tx)
|
||||
_, err := b.txapi.SendRawTransaction(ctx, common.ToHex(raw))
|
||||
_, err := b.txapi.SendRawTransaction(ctx, raw)
|
||||
return err
|
||||
}
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go
generated
vendored
@ -1005,7 +1005,7 @@ func (d *Downloader) fetchNodeData() error {
|
||||
// - fetchHook: tester callback to notify of new tasks being initiated (allows testing the scheduling logic)
|
||||
// - fetch: network callback to actually send a particular download request to a physical remote peer
|
||||
// - cancel: task callback to abort an in-flight download request and allow rescheduling it (in case of lost peer)
|
||||
// - capacity: network callback to retreive the estimated type-specific bandwidth capacity of a peer (traffic shaping)
|
||||
// - capacity: network callback to retrieve the estimated type-specific bandwidth capacity of a peer (traffic shaping)
|
||||
// - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks
|
||||
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
|
||||
// - kind: textual label of the type being downloaded to display in log mesages
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/eth/downloader/peer.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/eth/downloader/peer.go
generated
vendored
@ -205,7 +205,7 @@ func (p *peer) FetchNodeData(request *fetchRequest) error {
|
||||
|
||||
// Convert the hash set to a retrievable slice
|
||||
hashes := make([]common.Hash, 0, len(request.Hashes))
|
||||
for hash, _ := range request.Hashes {
|
||||
for hash := range request.Hashes {
|
||||
hashes = append(hashes, hash)
|
||||
}
|
||||
go p.getNodeData(hashes)
|
||||
@ -314,7 +314,7 @@ func (p *peer) MarkLacking(hash common.Hash) {
|
||||
defer p.lock.Unlock()
|
||||
|
||||
for len(p.lacking) >= maxLackingHashes {
|
||||
for drop, _ := range p.lacking {
|
||||
for drop := range p.lacking {
|
||||
delete(p.lacking, drop)
|
||||
break
|
||||
}
|
||||
|
19
vendor/github.com/ethereum/go-ethereum/eth/downloader/queue.go
generated
vendored
19
vendor/github.com/ethereum/go-ethereum/eth/downloader/queue.go
generated
vendored
@ -844,7 +844,7 @@ func (q *queue) expire(timeout time.Duration, pendPool map[string]*fetchRequest,
|
||||
}
|
||||
}
|
||||
// Remove the expired requests from the pending pool
|
||||
for id, _ := range expiries {
|
||||
for id := range expiries {
|
||||
delete(pendPool, id)
|
||||
}
|
||||
return expiries
|
||||
@ -1063,7 +1063,7 @@ func (q *queue) DeliverNodeData(id string, data [][]byte, callback func(int, boo
|
||||
|
||||
// If no data was retrieved, mark their hashes as unavailable for the origin peer
|
||||
if len(data) == 0 {
|
||||
for hash, _ := range request.Hashes {
|
||||
for hash := range request.Hashes {
|
||||
request.Peer.MarkLacking(hash)
|
||||
}
|
||||
}
|
||||
@ -1123,15 +1123,20 @@ func (q *queue) deliverNodeData(results []trie.SyncResult, callback func(int, bo
|
||||
callback(i, progressed, errNoFetchesPending)
|
||||
return
|
||||
}
|
||||
if prog, _, err := q.stateScheduler.Process([]trie.SyncResult{result}); err != nil {
|
||||
// Processing a state result failed, bail out
|
||||
|
||||
batch := q.stateDatabase.NewBatch()
|
||||
prog, _, err := q.stateScheduler.Process([]trie.SyncResult{result}, batch)
|
||||
if err != nil {
|
||||
q.stateSchedLock.Unlock()
|
||||
callback(i, progressed, err)
|
||||
return
|
||||
} else if prog {
|
||||
progressed = true
|
||||
}
|
||||
if err = batch.Write(); err != nil {
|
||||
q.stateSchedLock.Unlock()
|
||||
callback(i, progressed, err)
|
||||
}
|
||||
|
||||
// Item processing succeeded, release the lock (temporarily)
|
||||
progressed = progressed || prog
|
||||
q.stateSchedLock.Unlock()
|
||||
}
|
||||
callback(len(results), progressed, nil)
|
||||
|
19
vendor/github.com/ethereum/go-ethereum/eth/filters/api.go
generated
vendored
19
vendor/github.com/ethereum/go-ethereum/eth/filters/api.go
generated
vendored
@ -29,7 +29,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"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/event"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
@ -46,7 +45,7 @@ type filter struct {
|
||||
deadline *time.Timer // filter is inactiv when deadline triggers
|
||||
hashes []common.Hash
|
||||
crit FilterCriteria
|
||||
logs []*vm.Log
|
||||
logs []*types.Log
|
||||
s *Subscription // associated subscription in event system
|
||||
}
|
||||
|
||||
@ -242,7 +241,7 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc
|
||||
|
||||
var (
|
||||
rpcSub = notifier.CreateSubscription()
|
||||
matchedLogs = make(chan []*vm.Log)
|
||||
matchedLogs = make(chan []*types.Log)
|
||||
)
|
||||
|
||||
logsSub, err := api.events.SubscribeLogs(crit, matchedLogs)
|
||||
@ -293,14 +292,14 @@ type FilterCriteria struct {
|
||||
//
|
||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
|
||||
func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
|
||||
logs := make(chan []*vm.Log)
|
||||
logs := make(chan []*types.Log)
|
||||
logsSub, err := api.events.SubscribeLogs(crit, logs)
|
||||
if err != nil {
|
||||
return rpc.ID(""), err
|
||||
}
|
||||
|
||||
api.filtersMu.Lock()
|
||||
api.filters[logsSub.ID] = &filter{typ: LogsSubscription, crit: crit, deadline: time.NewTimer(deadline), logs: make([]*vm.Log, 0), s: logsSub}
|
||||
api.filters[logsSub.ID] = &filter{typ: LogsSubscription, crit: crit, deadline: time.NewTimer(deadline), logs: make([]*types.Log, 0), s: logsSub}
|
||||
api.filtersMu.Unlock()
|
||||
|
||||
go func() {
|
||||
@ -327,7 +326,7 @@ func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
|
||||
// GetLogs returns logs matching the given argument that are stored within the state.
|
||||
//
|
||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
|
||||
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*vm.Log, error) {
|
||||
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
||||
if crit.FromBlock == nil {
|
||||
crit.FromBlock = big.NewInt(rpc.LatestBlockNumber.Int64())
|
||||
}
|
||||
@ -366,7 +365,7 @@ func (api *PublicFilterAPI) UninstallFilter(id rpc.ID) bool {
|
||||
// If the filter could not be found an empty array of logs is returned.
|
||||
//
|
||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs
|
||||
func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*vm.Log, error) {
|
||||
func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Log, error) {
|
||||
api.filtersMu.Lock()
|
||||
f, found := api.filters[id]
|
||||
api.filtersMu.Unlock()
|
||||
@ -441,9 +440,9 @@ func returnHashes(hashes []common.Hash) []common.Hash {
|
||||
|
||||
// returnLogs is a helper that will return an empty log array in case the given logs array is nil,
|
||||
// otherwise the given logs array is returned.
|
||||
func returnLogs(logs []*vm.Log) []*vm.Log {
|
||||
func returnLogs(logs []*types.Log) []*types.Log {
|
||||
if logs == nil {
|
||||
return []*vm.Log{}
|
||||
return []*types.Log{}
|
||||
}
|
||||
return logs
|
||||
}
|
||||
@ -506,7 +505,7 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
|
||||
switch topic := t.(type) {
|
||||
case nil:
|
||||
// ignore topic when matching logs
|
||||
args.Topics[i] = []common.Hash{common.Hash{}}
|
||||
args.Topics[i] = []common.Hash{{}}
|
||||
|
||||
case string:
|
||||
// match specific topic
|
||||
|
79
vendor/github.com/ethereum/go-ethereum/eth/filters/filter.go
generated
vendored
79
vendor/github.com/ethereum/go-ethereum/eth/filters/filter.go
generated
vendored
@ -25,7 +25,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"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/event"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
@ -54,6 +53,8 @@ type Filter struct {
|
||||
|
||||
// New creates a new filter which uses a bloom filter on blocks to figure out whether
|
||||
// a particular block is interesting or not.
|
||||
// MipMaps allow past blocks to be searched much more efficiently, but are not available
|
||||
// to light clients.
|
||||
func New(backend Backend, useMipMap bool) *Filter {
|
||||
return &Filter{
|
||||
backend: backend,
|
||||
@ -85,8 +86,11 @@ func (f *Filter) SetTopics(topics [][]common.Hash) {
|
||||
f.topics = topics
|
||||
}
|
||||
|
||||
// Run filters logs with the current parameters set
|
||||
func (f *Filter) Find(ctx context.Context) ([]*vm.Log, error) {
|
||||
// FindOnce searches the blockchain for matching log entries, returning
|
||||
// all matching entries from the first block that contains matches,
|
||||
// updating the start point of the filter accordingly. If no results are
|
||||
// found, a nil slice is returned.
|
||||
func (f *Filter) FindOnce(ctx context.Context) ([]*types.Log, error) {
|
||||
head, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||
if head == nil {
|
||||
return nil, nil
|
||||
@ -106,47 +110,69 @@ func (f *Filter) Find(ctx context.Context) ([]*vm.Log, error) {
|
||||
// uses the mipmap bloom filters to check for fast inclusion and uses
|
||||
// higher range probability in order to ensure at least a false positive
|
||||
if !f.useMipMap || len(f.addresses) == 0 {
|
||||
return f.getLogs(ctx, beginBlockNo, endBlockNo)
|
||||
logs, blockNumber, err := f.getLogs(ctx, beginBlockNo, endBlockNo)
|
||||
f.begin = int64(blockNumber + 1)
|
||||
return logs, err
|
||||
}
|
||||
return f.mipFind(beginBlockNo, endBlockNo, 0), nil
|
||||
|
||||
logs, blockNumber := f.mipFind(beginBlockNo, endBlockNo, 0)
|
||||
f.begin = int64(blockNumber + 1)
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
func (f *Filter) mipFind(start, end uint64, depth int) (logs []*vm.Log) {
|
||||
// Run filters logs with the current parameters set
|
||||
func (f *Filter) Find(ctx context.Context) (logs []*types.Log, err error) {
|
||||
for {
|
||||
newLogs, err := f.FindOnce(ctx)
|
||||
if len(newLogs) == 0 || err != nil {
|
||||
return logs, err
|
||||
}
|
||||
logs = append(logs, newLogs...)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Filter) mipFind(start, end uint64, depth int) (logs []*types.Log, blockNumber uint64) {
|
||||
level := core.MIPMapLevels[depth]
|
||||
// normalise numerator so we can work in level specific batches and
|
||||
// work with the proper range checks
|
||||
for num := start / level * level; num <= end; num += level {
|
||||
// find addresses in bloom filters
|
||||
bloom := core.GetMipmapBloom(f.db, num, level)
|
||||
// Don't bother checking the first time through the loop - we're probably picking
|
||||
// up where a previous run left off.
|
||||
first := true
|
||||
for _, addr := range f.addresses {
|
||||
if bloom.TestBytes(addr[:]) {
|
||||
if first || bloom.TestBytes(addr[:]) {
|
||||
first = false
|
||||
// range check normalised values and make sure that
|
||||
// we're resolving the correct range instead of the
|
||||
// normalised values.
|
||||
start := uint64(math.Max(float64(num), float64(start)))
|
||||
end := uint64(math.Min(float64(num+level-1), float64(end)))
|
||||
if depth+1 == len(core.MIPMapLevels) {
|
||||
l, _ := f.getLogs(context.Background(), start, end)
|
||||
logs = append(logs, l...)
|
||||
l, blockNumber, _ := f.getLogs(context.Background(), start, end)
|
||||
if len(l) > 0 {
|
||||
return l, blockNumber
|
||||
}
|
||||
} else {
|
||||
logs = append(logs, f.mipFind(start, end, depth+1)...)
|
||||
l, blockNumber := f.mipFind(start, end, depth+1)
|
||||
if len(l) > 0 {
|
||||
return l, blockNumber
|
||||
}
|
||||
}
|
||||
// break so we don't check the same range for each
|
||||
// possible address. Checks on multiple addresses
|
||||
// are handled further down the stack.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return logs
|
||||
return nil, end
|
||||
}
|
||||
|
||||
func (f *Filter) getLogs(ctx context.Context, start, end uint64) (logs []*vm.Log, err error) {
|
||||
func (f *Filter) getLogs(ctx context.Context, start, end uint64) (logs []*types.Log, blockNumber uint64, err error) {
|
||||
for i := start; i <= end; i++ {
|
||||
header, err := f.backend.HeaderByNumber(ctx, rpc.BlockNumber(i))
|
||||
blockNumber := rpc.BlockNumber(i)
|
||||
header, err := f.backend.HeaderByNumber(ctx, blockNumber)
|
||||
if header == nil || err != nil {
|
||||
return logs, err
|
||||
return logs, end, err
|
||||
}
|
||||
|
||||
// Use bloom filtering to see if this block is interesting given the
|
||||
@ -155,17 +181,20 @@ func (f *Filter) getLogs(ctx context.Context, start, end uint64) (logs []*vm.Log
|
||||
// Get the logs of the block
|
||||
receipts, err := f.backend.GetReceipts(ctx, header.Hash())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, end, err
|
||||
}
|
||||
var unfiltered []*vm.Log
|
||||
var unfiltered []*types.Log
|
||||
for _, receipt := range receipts {
|
||||
unfiltered = append(unfiltered, ([]*vm.Log)(receipt.Logs)...)
|
||||
unfiltered = append(unfiltered, ([]*types.Log)(receipt.Logs)...)
|
||||
}
|
||||
logs = filterLogs(unfiltered, nil, nil, f.addresses, f.topics)
|
||||
if len(logs) > 0 {
|
||||
return logs, uint64(blockNumber), nil
|
||||
}
|
||||
logs = append(logs, filterLogs(unfiltered, nil, nil, f.addresses, f.topics)...)
|
||||
}
|
||||
}
|
||||
|
||||
return logs, nil
|
||||
return logs, end, nil
|
||||
}
|
||||
|
||||
func includes(addresses []common.Address, a common.Address) bool {
|
||||
@ -179,8 +208,8 @@ func includes(addresses []common.Address, a common.Address) bool {
|
||||
}
|
||||
|
||||
// filterLogs creates a slice of logs matching the given criteria.
|
||||
func filterLogs(logs []*vm.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*vm.Log {
|
||||
var ret []*vm.Log
|
||||
func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*types.Log {
|
||||
var ret []*types.Log
|
||||
Logs:
|
||||
for _, log := range logs {
|
||||
if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Uint64() > log.BlockNumber {
|
||||
|
25
vendor/github.com/ethereum/go-ethereum/eth/filters/filter_system.go
generated
vendored
25
vendor/github.com/ethereum/go-ethereum/eth/filters/filter_system.go
generated
vendored
@ -27,7 +27,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"golang.org/x/net/context"
|
||||
@ -38,7 +37,7 @@ import (
|
||||
type Type byte
|
||||
|
||||
const (
|
||||
// UnknownSubscription indicates an unkown subscription type
|
||||
// UnknownSubscription indicates an unknown subscription type
|
||||
UnknownSubscription Type = iota
|
||||
// LogsSubscription queries for new or removed (chain reorg) logs
|
||||
LogsSubscription
|
||||
@ -64,7 +63,7 @@ type subscription struct {
|
||||
typ Type
|
||||
created time.Time
|
||||
logsCrit FilterCriteria
|
||||
logs chan []*vm.Log
|
||||
logs chan []*types.Log
|
||||
hashes chan common.Hash
|
||||
headers chan *types.Header
|
||||
installed chan struct{} // closed when the filter is installed
|
||||
@ -151,7 +150,7 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription {
|
||||
// SubscribeLogs creates a subscription that will write all logs matching the
|
||||
// given criteria to the given logs channel. Default value for the from and to
|
||||
// block is "latest". If the fromBlock > toBlock an error is returned.
|
||||
func (es *EventSystem) SubscribeLogs(crit FilterCriteria, logs chan []*vm.Log) (*Subscription, error) {
|
||||
func (es *EventSystem) SubscribeLogs(crit FilterCriteria, logs chan []*types.Log) (*Subscription, error) {
|
||||
var from, to rpc.BlockNumber
|
||||
if crit.FromBlock == nil {
|
||||
from = rpc.LatestBlockNumber
|
||||
@ -189,7 +188,7 @@ func (es *EventSystem) SubscribeLogs(crit FilterCriteria, logs chan []*vm.Log) (
|
||||
|
||||
// subscribeMinedPendingLogs creates a subscription that returned mined and
|
||||
// pending logs that match the given criteria.
|
||||
func (es *EventSystem) subscribeMinedPendingLogs(crit FilterCriteria, logs chan []*vm.Log) *Subscription {
|
||||
func (es *EventSystem) subscribeMinedPendingLogs(crit FilterCriteria, logs chan []*types.Log) *Subscription {
|
||||
sub := &subscription{
|
||||
id: rpc.NewID(),
|
||||
typ: MinedAndPendingLogsSubscription,
|
||||
@ -207,7 +206,7 @@ func (es *EventSystem) subscribeMinedPendingLogs(crit FilterCriteria, logs chan
|
||||
|
||||
// subscribeLogs creates a subscription that will write all logs matching the
|
||||
// given criteria to the given logs channel.
|
||||
func (es *EventSystem) subscribeLogs(crit FilterCriteria, logs chan []*vm.Log) *Subscription {
|
||||
func (es *EventSystem) subscribeLogs(crit FilterCriteria, logs chan []*types.Log) *Subscription {
|
||||
sub := &subscription{
|
||||
id: rpc.NewID(),
|
||||
typ: LogsSubscription,
|
||||
@ -225,7 +224,7 @@ func (es *EventSystem) subscribeLogs(crit FilterCriteria, logs chan []*vm.Log) *
|
||||
|
||||
// subscribePendingLogs creates a subscription that writes transaction hashes for
|
||||
// transactions that enter the transaction pool.
|
||||
func (es *EventSystem) subscribePendingLogs(crit FilterCriteria, logs chan []*vm.Log) *Subscription {
|
||||
func (es *EventSystem) subscribePendingLogs(crit FilterCriteria, logs chan []*types.Log) *Subscription {
|
||||
sub := &subscription{
|
||||
id: rpc.NewID(),
|
||||
typ: PendingLogsSubscription,
|
||||
@ -248,7 +247,7 @@ func (es *EventSystem) SubscribeNewHeads(headers chan *types.Header) *Subscripti
|
||||
id: rpc.NewID(),
|
||||
typ: BlocksSubscription,
|
||||
created: time.Now(),
|
||||
logs: make(chan []*vm.Log),
|
||||
logs: make(chan []*types.Log),
|
||||
hashes: make(chan common.Hash),
|
||||
headers: headers,
|
||||
installed: make(chan struct{}),
|
||||
@ -265,7 +264,7 @@ func (es *EventSystem) SubscribePendingTxEvents(hashes chan common.Hash) *Subscr
|
||||
id: rpc.NewID(),
|
||||
typ: PendingTransactionsSubscription,
|
||||
created: time.Now(),
|
||||
logs: make(chan []*vm.Log),
|
||||
logs: make(chan []*types.Log),
|
||||
hashes: hashes,
|
||||
headers: make(chan *types.Header),
|
||||
installed: make(chan struct{}),
|
||||
@ -284,7 +283,7 @@ func (es *EventSystem) broadcast(filters filterIndex, ev *event.Event) {
|
||||
}
|
||||
|
||||
switch e := ev.Data.(type) {
|
||||
case vm.Logs:
|
||||
case []*types.Log:
|
||||
if len(e) > 0 {
|
||||
for _, f := range filters[LogsSubscription] {
|
||||
if ev.Time.After(f.created) {
|
||||
@ -370,7 +369,7 @@ func (es *EventSystem) lightFilterNewHead(newHeader *types.Header, callBack func
|
||||
}
|
||||
|
||||
// filter logs of a single header in light client mode
|
||||
func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.Address, topics [][]common.Hash, remove bool) []*vm.Log {
|
||||
func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.Address, topics [][]common.Hash, remove bool) []*types.Log {
|
||||
if bloomFilter(header.Bloom, addresses, topics) {
|
||||
// Get the logs of the block
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
|
||||
@ -378,7 +377,7 @@ func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var unfiltered []*vm.Log
|
||||
var unfiltered []*types.Log
|
||||
for _, receipt := range receipts {
|
||||
for _, log := range receipt.Logs {
|
||||
logcopy := *log
|
||||
@ -396,7 +395,7 @@ func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.
|
||||
func (es *EventSystem) eventLoop() {
|
||||
var (
|
||||
index = make(filterIndex)
|
||||
sub = es.mux.Subscribe(core.PendingLogsEvent{}, core.RemovedLogsEvent{}, vm.Logs{}, core.TxPreEvent{}, core.ChainEvent{})
|
||||
sub = es.mux.Subscribe(core.PendingLogsEvent{}, core.RemovedLogsEvent{}, []*types.Log{}, core.TxPreEvent{}, core.ChainEvent{})
|
||||
)
|
||||
|
||||
for i := UnknownSubscription; i < LastIndexSubscription; i++ {
|
||||
|
30
vendor/github.com/ethereum/go-ethereum/eth/handler.go
generated
vendored
30
vendor/github.com/ethereum/go-ethereum/eth/handler.go
generated
vendored
@ -605,38 +605,16 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||
}
|
||||
|
||||
case msg.Code == NewBlockHashesMsg:
|
||||
// Retrieve and deserialize the remote new block hashes notification
|
||||
type announce struct {
|
||||
Hash common.Hash
|
||||
Number uint64
|
||||
}
|
||||
var announces = []announce{}
|
||||
|
||||
if p.version < eth62 {
|
||||
// We're running the old protocol, make block number unknown (0)
|
||||
var hashes []common.Hash
|
||||
if err := msg.Decode(&hashes); err != nil {
|
||||
return errResp(ErrDecode, "%v: %v", msg, err)
|
||||
}
|
||||
for _, hash := range hashes {
|
||||
announces = append(announces, announce{hash, 0})
|
||||
}
|
||||
} else {
|
||||
// Otherwise extract both block hash and number
|
||||
var request newBlockHashesData
|
||||
if err := msg.Decode(&request); err != nil {
|
||||
return errResp(ErrDecode, "%v: %v", msg, err)
|
||||
}
|
||||
for _, block := range request {
|
||||
announces = append(announces, announce{block.Hash, block.Number})
|
||||
}
|
||||
var announces newBlockHashesData
|
||||
if err := msg.Decode(&announces); err != nil {
|
||||
return errResp(ErrDecode, "%v: %v", msg, err)
|
||||
}
|
||||
// Mark the hashes as present at the remote node
|
||||
for _, block := range announces {
|
||||
p.MarkBlock(block.Hash)
|
||||
}
|
||||
// Schedule all the unknown hashes for retrieval
|
||||
unknown := make([]announce, 0, len(announces))
|
||||
unknown := make(newBlockHashesData, 0, len(announces))
|
||||
for _, block := range announces {
|
||||
if !pm.blockchain.HasBlock(block.Hash) {
|
||||
unknown = append(unknown, block)
|
||||
|
4
vendor/github.com/ethereum/go-ethereum/eth/protocol.go
generated
vendored
4
vendor/github.com/ethereum/go-ethereum/eth/protocol.go
generated
vendored
@ -98,11 +98,11 @@ var errorToString = map[int]string{
|
||||
|
||||
type txPool interface {
|
||||
// AddBatch should add the given transactions to the pool.
|
||||
AddBatch([]*types.Transaction)
|
||||
AddBatch([]*types.Transaction) error
|
||||
|
||||
// Pending should return pending transactions.
|
||||
// The slice should be modifiable by the caller.
|
||||
Pending() map[common.Address]types.Transactions
|
||||
Pending() (map[common.Address]types.Transactions, error)
|
||||
}
|
||||
|
||||
// statusData is the network packet for the status message.
|
||||
|
3
vendor/github.com/ethereum/go-ethereum/eth/sync.go
generated
vendored
3
vendor/github.com/ethereum/go-ethereum/eth/sync.go
generated
vendored
@ -46,7 +46,8 @@ type txsync struct {
|
||||
// syncTransactions starts sending all currently pending transactions to the given peer.
|
||||
func (pm *ProtocolManager) syncTransactions(p *peer) {
|
||||
var txs types.Transactions
|
||||
for _, batch := range pm.txpool.Pending() {
|
||||
pending, _ := pm.txpool.Pending()
|
||||
for _, batch := range pending {
|
||||
txs = append(txs, batch...)
|
||||
}
|
||||
if len(txs) == 0 {
|
||||
|
11
vendor/github.com/ethereum/go-ethereum/ethclient/ethclient.go
generated
vendored
11
vendor/github.com/ethereum/go-ethereum/ethclient/ethclient.go
generated
vendored
@ -26,7 +26,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"golang.org/x/net/context"
|
||||
@ -163,7 +162,7 @@ func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *
|
||||
} else if len(raw) == 0 {
|
||||
return nil, false, ethereum.NotFound
|
||||
}
|
||||
if err := json.Unmarshal(raw, tx); err != nil {
|
||||
if err := json.Unmarshal(raw, &tx); err != nil {
|
||||
return nil, false, err
|
||||
} else if _, r, _ := tx.RawSignatureValues(); r == nil {
|
||||
return nil, false, fmt.Errorf("server returned transaction without signature")
|
||||
@ -185,7 +184,7 @@ func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (
|
||||
// TransactionInBlock returns a single transaction at index in the given block.
|
||||
func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
|
||||
var tx *types.Transaction
|
||||
err := ec.c.CallContext(ctx, &tx, "eth_getTransactionByBlockHashAndIndex", blockHash, index)
|
||||
err := ec.c.CallContext(ctx, &tx, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index))
|
||||
if err == nil {
|
||||
if tx == nil {
|
||||
return nil, ethereum.NotFound
|
||||
@ -294,14 +293,14 @@ func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumb
|
||||
// Filters
|
||||
|
||||
// FilterLogs executes a filter query.
|
||||
func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]vm.Log, error) {
|
||||
var result []vm.Log
|
||||
func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
|
||||
var result []types.Log
|
||||
err := ec.c.CallContext(ctx, &result, "eth_getLogs", toFilterArg(q))
|
||||
return result, err
|
||||
}
|
||||
|
||||
// SubscribeFilterLogs subscribes to the results of a streaming filter query.
|
||||
func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- vm.Log) (ethereum.Subscription, error) {
|
||||
func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
|
||||
return ec.c.EthSubscribe(ctx, ch, "logs", toFilterArg(q))
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go
generated
vendored
@ -67,7 +67,7 @@ func (db *MemDatabase) Keys() [][]byte {
|
||||
defer db.lock.RUnlock()
|
||||
|
||||
keys := [][]byte{}
|
||||
for key, _ := range db.db {
|
||||
for key := range db.db {
|
||||
keys = append(keys, []byte(key))
|
||||
}
|
||||
return keys
|
||||
|
260
vendor/github.com/ethereum/go-ethereum/ethstats/ethstats.go
generated
vendored
260
vendor/github.com/ethereum/go-ethereum/ethstats/ethstats.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -41,6 +42,10 @@ import (
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// historyUpdateRange is the number of blocks a node should report upon login or
|
||||
// history request.
|
||||
const historyUpdateRange = 50
|
||||
|
||||
// Service implements an Ethereum netstats reporting daemon that pushes local
|
||||
// chain statistics up to a monitoring server.
|
||||
type Service struct {
|
||||
@ -53,6 +58,9 @@ type Service struct {
|
||||
node string // Name of the node to display on the monitoring page
|
||||
pass string // Password to authorize access to the monitoring page
|
||||
host string // Remote address of the monitoring service
|
||||
|
||||
pongCh chan struct{} // Pong notifications are fed into this channel
|
||||
histCh chan []uint64 // History request block numbers are fed into this channel
|
||||
}
|
||||
|
||||
// New returns a monitoring service ready for stats reporting.
|
||||
@ -65,11 +73,13 @@ func New(url string, ethServ *eth.Ethereum, lesServ *les.LightEthereum) (*Servic
|
||||
}
|
||||
// Assemble and return the stats service
|
||||
return &Service{
|
||||
eth: ethServ,
|
||||
les: lesServ,
|
||||
node: parts[1],
|
||||
pass: parts[3],
|
||||
host: parts[4],
|
||||
eth: ethServ,
|
||||
les: lesServ,
|
||||
node: parts[1],
|
||||
pass: parts[3],
|
||||
host: parts[4],
|
||||
pongCh: make(chan struct{}),
|
||||
histCh: make(chan []uint64, 1),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -115,7 +125,11 @@ func (s *Service) loop() {
|
||||
// Loop reporting until termination
|
||||
for {
|
||||
// Establish a websocket connection to the server and authenticate the node
|
||||
conn, err := websocket.Dial(fmt.Sprintf("wss://%s/api", s.host), "", "http://localhost/")
|
||||
url := fmt.Sprintf("%s/api", s.host)
|
||||
if !strings.Contains(url, "://") {
|
||||
url = "wss://" + url
|
||||
}
|
||||
conn, err := websocket.Dial(url, "", "http://localhost/")
|
||||
if err != nil {
|
||||
glog.V(logger.Warn).Infof("Stats server unreachable: %v", err)
|
||||
time.Sleep(10 * time.Second)
|
||||
@ -130,22 +144,34 @@ func (s *Service) loop() {
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
if err = s.report(in, out); err != nil {
|
||||
go s.readLoop(conn, in)
|
||||
|
||||
// Send the initial stats so our node looks decent from the get go
|
||||
if err = s.report(out); err != nil {
|
||||
glog.V(logger.Warn).Infof("Initial stats report failed: %v", err)
|
||||
conn.Close()
|
||||
continue
|
||||
}
|
||||
if err = s.reportHistory(out, nil); err != nil {
|
||||
glog.V(logger.Warn).Infof("History report failed: %v", err)
|
||||
conn.Close()
|
||||
continue
|
||||
}
|
||||
// Keep sending status updates until the connection breaks
|
||||
fullReport := time.NewTicker(15 * time.Second)
|
||||
|
||||
for err == nil {
|
||||
select {
|
||||
case <-fullReport.C:
|
||||
if err = s.report(in, out); err != nil {
|
||||
if err = s.report(out); err != nil {
|
||||
glog.V(logger.Warn).Infof("Full stats report failed: %v", err)
|
||||
}
|
||||
case head := <-headSub.Chan():
|
||||
if head == nil { // node stopped
|
||||
case list := <-s.histCh:
|
||||
if err = s.reportHistory(out, list); err != nil {
|
||||
glog.V(logger.Warn).Infof("Block history report failed: %v", err)
|
||||
}
|
||||
case head, ok := <-headSub.Chan():
|
||||
if !ok { // node stopped
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
@ -155,8 +181,8 @@ func (s *Service) loop() {
|
||||
if err = s.reportPending(out); err != nil {
|
||||
glog.V(logger.Warn).Infof("Post-block transaction stats report failed: %v", err)
|
||||
}
|
||||
case ev := <-txSub.Chan():
|
||||
if ev == nil { // node stopped
|
||||
case _, ok := <-txSub.Chan():
|
||||
if !ok { // node stopped
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
@ -178,6 +204,76 @@ func (s *Service) loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// readLoop loops as long as the connection is alive and retrieves data packets
|
||||
// from the network socket. If any of them match an active request, it forwards
|
||||
// it, if they themselves are requests it initiates a reply, and lastly it drops
|
||||
// unknown packets.
|
||||
func (s *Service) readLoop(conn *websocket.Conn, in *json.Decoder) {
|
||||
// If the read loop exists, close the connection
|
||||
defer conn.Close()
|
||||
|
||||
for {
|
||||
// Retrieve the next generic network packet and bail out on error
|
||||
var msg map[string][]interface{}
|
||||
if err := in.Decode(&msg); err != nil {
|
||||
glog.V(logger.Warn).Infof("Failed to decode stats server message: %v", err)
|
||||
return
|
||||
}
|
||||
if len(msg["emit"]) == 0 {
|
||||
glog.V(logger.Warn).Infof("Stats server sent non-broadcast: %v", msg)
|
||||
return
|
||||
}
|
||||
command, ok := msg["emit"][0].(string)
|
||||
if !ok {
|
||||
glog.V(logger.Warn).Infof("Invalid stats server message type: %v", msg["emit"][0])
|
||||
return
|
||||
}
|
||||
// If the message is a ping reply, deliver (someone must be listening!)
|
||||
if len(msg["emit"]) == 2 && command == "node-pong" {
|
||||
select {
|
||||
case s.pongCh <- struct{}{}:
|
||||
// Pong delivered, continue listening
|
||||
continue
|
||||
default:
|
||||
// Ping routine dead, abort
|
||||
glog.V(logger.Warn).Infof("Stats server pinger seems to have died")
|
||||
return
|
||||
}
|
||||
}
|
||||
// If the message is a history request, forward to the event processor
|
||||
if len(msg["emit"]) == 2 && command == "history" {
|
||||
// Make sure the request is valid and doesn't crash us
|
||||
request, ok := msg["emit"][1].(map[string]interface{})
|
||||
if !ok {
|
||||
glog.V(logger.Warn).Infof("Invalid history request: %v", msg["emit"][1])
|
||||
return
|
||||
}
|
||||
list, ok := request["list"].([]interface{})
|
||||
if !ok {
|
||||
glog.V(logger.Warn).Infof("Invalid history block list: %v", request["list"])
|
||||
return
|
||||
}
|
||||
// Convert the block number list to an integer list
|
||||
numbers := make([]uint64, len(list))
|
||||
for i, num := range list {
|
||||
n, ok := num.(float64)
|
||||
if !ok {
|
||||
glog.V(logger.Warn).Infof("Invalid history block number: %v", num)
|
||||
return
|
||||
}
|
||||
numbers[i] = uint64(n)
|
||||
}
|
||||
select {
|
||||
case s.histCh <- numbers:
|
||||
continue
|
||||
default:
|
||||
}
|
||||
}
|
||||
// Report anything else and continue
|
||||
glog.V(logger.Info).Infof("Unknown stats message: %v", msg)
|
||||
}
|
||||
}
|
||||
|
||||
// nodeInfo is the collection of metainformation about a node that is displayed
|
||||
// on the monitoring page.
|
||||
type nodeInfo struct {
|
||||
@ -190,6 +286,7 @@ type nodeInfo struct {
|
||||
Os string `json:"os"`
|
||||
OsVer string `json:"os_v"`
|
||||
Client string `json:"client"`
|
||||
History bool `json:"canUpdateHistory"`
|
||||
}
|
||||
|
||||
// authMsg is the authentication infos needed to login to a monitoring server.
|
||||
@ -224,11 +321,12 @@ func (s *Service) login(in *json.Decoder, out *json.Encoder) error {
|
||||
Os: runtime.GOOS,
|
||||
OsVer: runtime.GOARCH,
|
||||
Client: "0.1.1",
|
||||
History: true,
|
||||
},
|
||||
Secret: s.pass,
|
||||
}
|
||||
login := map[string][]interface{}{
|
||||
"emit": []interface{}{"hello", auth},
|
||||
"emit": {"hello", auth},
|
||||
}
|
||||
if err := out.Encode(login); err != nil {
|
||||
return err
|
||||
@ -244,8 +342,8 @@ func (s *Service) login(in *json.Decoder, out *json.Encoder) error {
|
||||
// report collects all possible data to report and send it to the stats server.
|
||||
// This should only be used on reconnects or rarely to avoid overloading the
|
||||
// server. Use the individual methods for reporting subscribed events.
|
||||
func (s *Service) report(in *json.Decoder, out *json.Encoder) error {
|
||||
if err := s.reportLatency(in, out); err != nil {
|
||||
func (s *Service) report(out *json.Encoder) error {
|
||||
if err := s.reportLatency(out); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.reportBlock(out, nil); err != nil {
|
||||
@ -262,12 +360,12 @@ func (s *Service) report(in *json.Decoder, out *json.Encoder) error {
|
||||
|
||||
// reportLatency sends a ping request to the server, measures the RTT time and
|
||||
// finally sends a latency update.
|
||||
func (s *Service) reportLatency(in *json.Decoder, out *json.Encoder) error {
|
||||
func (s *Service) reportLatency(out *json.Encoder) error {
|
||||
// Send the current time to the ethstats server
|
||||
start := time.Now()
|
||||
|
||||
ping := map[string][]interface{}{
|
||||
"emit": []interface{}{"node-ping", map[string]string{
|
||||
"emit": {"node-ping", map[string]string{
|
||||
"id": s.node,
|
||||
"clientTime": start.String(),
|
||||
}},
|
||||
@ -276,27 +374,28 @@ func (s *Service) reportLatency(in *json.Decoder, out *json.Encoder) error {
|
||||
return err
|
||||
}
|
||||
// Wait for the pong request to arrive back
|
||||
var pong map[string][]interface{}
|
||||
if err := in.Decode(&pong); err != nil || len(pong["emit"]) != 2 || pong["emit"][0].(string) != "node-pong" {
|
||||
return errors.New("unexpected ping reply")
|
||||
select {
|
||||
case <-s.pongCh:
|
||||
// Pong delivered, report the latency
|
||||
case <-time.After(3 * time.Second):
|
||||
// Ping timeout, abort
|
||||
return errors.New("ping timed out")
|
||||
}
|
||||
// Send back the measured latency
|
||||
latency := map[string][]interface{}{
|
||||
"emit": []interface{}{"latency", map[string]string{
|
||||
"emit": {"latency", map[string]string{
|
||||
"id": s.node,
|
||||
"latency": strconv.Itoa(int((time.Since(start) / time.Duration(2)).Nanoseconds() / 1000000)),
|
||||
}},
|
||||
}
|
||||
if err := out.Encode(latency); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return out.Encode(latency)
|
||||
}
|
||||
|
||||
// blockStats is the information to report about individual blocks.
|
||||
type blockStats struct {
|
||||
Number *big.Int `json:"number"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
Timestamp *big.Int `json:"timestamp"`
|
||||
Miner common.Address `json:"miner"`
|
||||
GasUsed *big.Int `json:"gasUsed"`
|
||||
GasLimit *big.Int `json:"gasLimit"`
|
||||
@ -330,9 +429,23 @@ func (s uncleStats) MarshalJSON() ([]byte, error) {
|
||||
|
||||
// reportBlock retrieves the current chain head and repors it to the stats server.
|
||||
func (s *Service) reportBlock(out *json.Encoder, block *types.Block) error {
|
||||
// Gather the head block infos from the local blockchain
|
||||
// Assemble the block stats report and send it to the server
|
||||
stats := map[string]interface{}{
|
||||
"id": s.node,
|
||||
"block": s.assembleBlockStats(block),
|
||||
}
|
||||
report := map[string][]interface{}{
|
||||
"emit": {"block", stats},
|
||||
}
|
||||
return out.Encode(report)
|
||||
}
|
||||
|
||||
// assembleBlockStats retrieves any required metadata to report a single block
|
||||
// and assembles the block stats. If block is nil, the current head is processed.
|
||||
func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
|
||||
// Gather the block infos from the local blockchain
|
||||
var (
|
||||
head *types.Header
|
||||
header *types.Header
|
||||
td *big.Int
|
||||
txs []*types.Transaction
|
||||
uncles []*types.Header
|
||||
@ -342,42 +455,77 @@ func (s *Service) reportBlock(out *json.Encoder, block *types.Block) error {
|
||||
if block == nil {
|
||||
block = s.eth.BlockChain().CurrentBlock()
|
||||
}
|
||||
head = block.Header()
|
||||
td = s.eth.BlockChain().GetTd(head.Hash(), head.Number.Uint64())
|
||||
header = block.Header()
|
||||
td = s.eth.BlockChain().GetTd(header.Hash(), header.Number.Uint64())
|
||||
|
||||
txs = block.Transactions()
|
||||
uncles = block.Uncles()
|
||||
} else {
|
||||
// Light nodes would need on-demand lookups for transactions/uncles, skip
|
||||
if block != nil {
|
||||
head = block.Header()
|
||||
header = block.Header()
|
||||
} else {
|
||||
header = s.les.BlockChain().CurrentHeader()
|
||||
}
|
||||
td = s.les.BlockChain().GetTd(header.Hash(), header.Number.Uint64())
|
||||
}
|
||||
// Assemble and return the block stats
|
||||
return &blockStats{
|
||||
Number: header.Number,
|
||||
Hash: header.Hash(),
|
||||
Timestamp: header.Time,
|
||||
Miner: header.Coinbase,
|
||||
GasUsed: new(big.Int).Set(header.GasUsed),
|
||||
GasLimit: new(big.Int).Set(header.GasLimit),
|
||||
Diff: header.Difficulty.String(),
|
||||
TotalDiff: td.String(),
|
||||
Txs: txs,
|
||||
Uncles: uncles,
|
||||
}
|
||||
}
|
||||
|
||||
// reportHistory retrieves the most recent batch of blocks and reports it to the
|
||||
// stats server.
|
||||
func (s *Service) reportHistory(out *json.Encoder, list []uint64) error {
|
||||
// Figure out the indexes that need reporting
|
||||
indexes := make([]uint64, 0, historyUpdateRange)
|
||||
if len(list) > 0 {
|
||||
// Specific indexes requested, send them back in particular
|
||||
indexes = append(indexes, list...)
|
||||
} else {
|
||||
// No indexes requested, send back the top ones
|
||||
var head *types.Header
|
||||
if s.eth != nil {
|
||||
head = s.eth.BlockChain().CurrentHeader()
|
||||
} else {
|
||||
head = s.les.BlockChain().CurrentHeader()
|
||||
}
|
||||
td = s.les.BlockChain().GetTd(head.Hash(), head.Number.Uint64())
|
||||
start := head.Number.Int64() - historyUpdateRange
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
for i := uint64(start); i <= head.Number.Uint64(); i++ {
|
||||
indexes = append(indexes, i)
|
||||
}
|
||||
}
|
||||
// Assemble the block stats report and send it to the server
|
||||
// Gather the batch of blocks to report
|
||||
history := make([]*blockStats, len(indexes))
|
||||
for i, number := range indexes {
|
||||
if s.eth != nil {
|
||||
history[i] = s.assembleBlockStats(s.eth.BlockChain().GetBlockByNumber(number))
|
||||
} else {
|
||||
history[i] = s.assembleBlockStats(types.NewBlockWithHeader(s.les.BlockChain().GetHeaderByNumber(number)))
|
||||
}
|
||||
}
|
||||
// Assemble the history report and send it to the server
|
||||
stats := map[string]interface{}{
|
||||
"id": s.node,
|
||||
"block": &blockStats{
|
||||
Number: head.Number,
|
||||
Hash: head.Hash(),
|
||||
Miner: head.Coinbase,
|
||||
GasUsed: new(big.Int).Set(head.GasUsed),
|
||||
GasLimit: new(big.Int).Set(head.GasLimit),
|
||||
Diff: head.Difficulty.String(),
|
||||
TotalDiff: td.String(),
|
||||
Txs: txs,
|
||||
Uncles: uncles,
|
||||
},
|
||||
"id": s.node,
|
||||
"history": history,
|
||||
}
|
||||
report := map[string][]interface{}{
|
||||
"emit": []interface{}{"block", stats},
|
||||
"emit": {"history", stats},
|
||||
}
|
||||
if err := out.Encode(report); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return out.Encode(report)
|
||||
}
|
||||
|
||||
// pendStats is the information to report about pending transactions.
|
||||
@ -403,12 +551,9 @@ func (s *Service) reportPending(out *json.Encoder) error {
|
||||
},
|
||||
}
|
||||
report := map[string][]interface{}{
|
||||
"emit": []interface{}{"pending", stats},
|
||||
"emit": {"pending", stats},
|
||||
}
|
||||
if err := out.Encode(report); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return out.Encode(report)
|
||||
}
|
||||
|
||||
// blockStats is the information to report about the local node.
|
||||
@ -457,10 +602,7 @@ func (s *Service) reportStats(out *json.Encoder) error {
|
||||
},
|
||||
}
|
||||
report := map[string][]interface{}{
|
||||
"emit": []interface{}{"stats", stats},
|
||||
"emit": {"stats", stats},
|
||||
}
|
||||
if err := out.Encode(report); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return out.Encode(report)
|
||||
}
|
||||
|
2
vendor/github.com/ethereum/go-ethereum/event/filter/generic_filter.go
generated
vendored
2
vendor/github.com/ethereum/go-ethereum/event/filter/generic_filter.go
generated
vendored
@ -34,7 +34,7 @@ func (self Generic) Compare(f Filter) bool {
|
||||
strMatch = false
|
||||
}
|
||||
|
||||
for k, _ := range self.Data {
|
||||
for k := range self.Data {
|
||||
if _, ok := filter.Data[k]; !ok {
|
||||
return false
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user