Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
package vm

import (
"github.com/tomochain/tomochain/params"
"math/big"

"github.com/tomochain/tomochain/common"
"github.com/tomochain/tomochain/common/math"
"github.com/tomochain/tomochain/core/types"
"golang.org/x/crypto/sha3"
"github.com/tomochain/tomochain/crypto"
"github.com/tomochain/tomochain/params"
)

var (
Expand Down Expand Up @@ -381,7 +381,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by
data := callContext.memory.GetPtr(offset.Int64(), size.Int64())

if interpreter.hasher == nil {
interpreter.hasher = sha3.NewLegacyKeccak256().(keccakState)
interpreter.hasher = crypto.NewKeccakState()
} else {
interpreter.hasher.Reset()
}
Expand Down Expand Up @@ -513,16 +513,21 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx
// opExtCodeHash returns the code hash of a specified account.
// There are several cases when the function is called, while we can relay everything
// to `state.GetCodeHash` function to ensure the correctness.
// (1) Caller tries to get the code hash of a normal contract account, state
//
// (1) Caller tries to get the code hash of a normal contract account, state
//
// should return the relative code hash and set it as the result.
//
// (2) Caller tries to get the code hash of a non-existent account, state should
// (2) Caller tries to get the code hash of a non-existent account, state should
//
// return common.Hash{} and zero will be set as the result.
//
// (3) Caller tries to get the code hash for an account without contract code,
// (3) Caller tries to get the code hash for an account without contract code,
//
// state should return emptyCodeHash(0xc5d246...) as the result.
//
// (4) Caller tries to get the code hash of a precompiled account, the result
// (4) Caller tries to get the code hash of a precompiled account, the result
//
// should be zero or emptyCodeHash.
//
// It is worth noting that in order to avoid unnecessary create and clean,
Expand All @@ -531,10 +536,12 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx
// If the precompile account is not transferred any amount on a private or
// customized chain, the return value will be zero.
//
// (5) Caller tries to get the code hash for an account which is marked as suicided
// (5) Caller tries to get the code hash for an account which is marked as suicided
//
// in the current transaction, the code hash of this account should be returned.
//
// (6) Caller tries to get the code hash for an account which is marked as deleted,
// (6) Caller tries to get the code hash for an account which is marked as deleted,
//
// this account should be regarded as a non-existent account and zero should be returned.
func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
slot := callContext.stack.peek()
Expand Down
14 changes: 3 additions & 11 deletions core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
package vm

import (
"hash"
"sync/atomic"

"github.com/tomochain/tomochain/common"
"github.com/tomochain/tomochain/common/math"
"github.com/tomochain/tomochain/crypto"
"github.com/tomochain/tomochain/log"
)

Expand Down Expand Up @@ -70,23 +70,15 @@ type callCtx struct {
contract *Contract
}

// keccakState wraps sha3.state. In addition to the usual hash methods, it also supports
// Read to get a variable amount of data from the hash state. Read is faster than Sum
// because it doesn't copy the internal state, but also modifies the internal state.
type keccakState interface {
hash.Hash
Read([]byte) (int, error)
}

// EVMInterpreter represents an EVM interpreter
type EVMInterpreter struct {
evm *EVM
cfg Config

intPool *intPool

hasher keccakState // Keccak256 hasher instance shared across opcodes
hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes

readOnly bool // Whether to throw on stateful modifications
returnData []byte // Last CALL's return data for subsequent reuse
Expand Down
47 changes: 41 additions & 6 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,45 +23,80 @@ import (
"encoding/hex"
"errors"
"fmt"
"hash"
"io"
"io/ioutil"
"math/big"
"os"

"github.com/tomochain/tomochain/common"
"github.com/tomochain/tomochain/common/math"
"github.com/tomochain/tomochain/crypto/sha3"
"github.com/tomochain/tomochain/rlp"
"golang.org/x/crypto/sha3"
)

// SignatureLength indicates the byte length required to carry a signature with recovery id.
const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id

// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id.
const RecoveryIDOffset = 64

// DigestLength sets the signature digest exact length
const DigestLength = 32

var (
secp256k1_N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2))
)

var errInvalidPubkey = errors.New("invalid secp256k1 public key")

// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports
// Read to get a variable amount of data from the hash state. Read is faster than Sum
// because it doesn't copy the internal state, but also modifies the internal state.
type KeccakState interface {
hash.Hash
Read([]byte) (int, error)
}

// NewKeccakState creates a new KeccakState
func NewKeccakState() KeccakState {
return sha3.NewLegacyKeccak256().(KeccakState)
}

// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
func HashData(kh KeccakState, data []byte) (h common.Hash) {
kh.Reset()
kh.Write(data)
kh.Read(h[:])
return h
}

// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
d := sha3.NewKeccak256()
b := make([]byte, 32)
d := NewKeccakState()
for _, b := range data {
d.Write(b)
}
return d.Sum(nil)
d.Read(b)
return b
}

// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
// converting it to an internal Hash data structure.
func Keccak256Hash(data ...[]byte) (h common.Hash) {
d := sha3.NewKeccak256()
d := NewKeccakState()
for _, b := range data {
d.Write(b)
}
d.Sum(h[:0])
d.Read(h[:])
return h
}

// Keccak512 calculates and returns the Keccak512 hash of the input data.
func Keccak512(data ...[]byte) []byte {
d := sha3.NewKeccak512()
d := sha3.NewLegacyKeccak512()
for _, b := range data {
d.Write(b)
}
Expand Down
6 changes: 3 additions & 3 deletions trie/committer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
"sync"

"github.com/tomochain/tomochain/common"
"github.com/tomochain/tomochain/crypto"
"github.com/tomochain/tomochain/rlp"
"golang.org/x/crypto/sha3"
)

// leafChanSize is the size of the leafCh. It's a pretty arbitrary number, to allow
Expand All @@ -46,7 +46,7 @@ type leaf struct {
// processed sequentially - onleaf will never be called in parallel or out of order.
type committer struct {
tmp sliceBuffer
sha keccakState
sha crypto.KeccakState

onleaf LeafCallback
leafCh chan *leaf
Expand All @@ -57,7 +57,7 @@ var committerPool = sync.Pool{
New: func() interface{} {
return &committer{
tmp: make(sliceBuffer, 0, 550), // cap is as large as a full FullNode.
sha: sha3.NewLegacyKeccak256().(keccakState),
sha: crypto.NewKeccakState(),
}
},
}
Expand Down
15 changes: 3 additions & 12 deletions trie/hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,12 @@
package trie

import (
"hash"
"sync"

"github.com/tomochain/tomochain/crypto"
"github.com/tomochain/tomochain/rlp"
"golang.org/x/crypto/sha3"
)

// keccakState wraps sha3.state. In addition to the usual hash methods, it also supports
// Read to get a variable amount of data from the hash state. Read is faster than Sum
// because it doesn't copy the internal state, but also modifies the internal state.
type keccakState interface {
hash.Hash
Read([]byte) (int, error)
}

type sliceBuffer []byte

func (b *sliceBuffer) Write(data []byte) (n int, err error) {
Expand All @@ -46,7 +37,7 @@ func (b *sliceBuffer) Reset() {
// hasher is a type used for the trie Hash operation. A hasher has some
// internal preallocated temp space
type hasher struct {
sha keccakState
sha crypto.KeccakState
tmp sliceBuffer
parallel bool // Whether to use paralallel threads when hashing
}
Expand All @@ -56,7 +47,7 @@ var hasherPool = sync.Pool{
New: func() interface{} {
return &hasher{
tmp: make(sliceBuffer, 0, 550), // cap is as large as a full FullNode.
sha: sha3.NewLegacyKeccak256().(keccakState),
sha: crypto.NewKeccakState(),
}
},
}
Expand Down