Skip to content
Open
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
2 changes: 2 additions & 0 deletions op-geth/core/types/hashing.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !(js || wasm || wasip1)
// +build !wasm,!wasip1, !js
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
Expand Down
144 changes: 144 additions & 0 deletions op-geth/core/types/hashing_wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//go:build js || wasm || wasip1
// +build js wasm wasip1
package types

import (
"bytes"
"sync"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
)

// hasherPool holds LegacyKeccak256 hashers for rlpHash.
var hasherPool = sync.Pool{
New: func() interface{} { return sha3.NewLegacyKeccak256() },
}

// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding.
var encodeBufferPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
}

// rlpHash encodes x and hashes the encoded bytes.
func oldrlpHash(x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
rlp.Encode(sha, x)
sha.Read(h[:])
return h
}

func checkrlpHash(x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
hash := NewHashHelper()
rlp.Encode(hash, x)
hash.WriteTo(sha)
sha.Read(h[:])
n := hash.Hash()
for i := 0; i < 32; i++ {
if h[i] != n[i] {
}
require_bool(h[i] == n[i])
}
return n
}

func rlpHash(x interface{}) (h common.Hash) {
hash := NewHashHelper()
rlp.Encode(hash, x)
n := hash.Hash()
return n
}

// prefixedRlpHash writes the prefix into the hasher before rlp-encoding x.
// It's used for typed transactions.
func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
sha.Write([]byte{prefix})
rlp.Encode(sha, x)
sha.Read(h[:])
wasm_dbg(222)
return h
}

// TrieHasher is the tool used to calculate the hash of derivable list.
// This is internal, do not use.
type TrieHasher interface {
Reset()
Update([]byte, []byte) error
Hash() common.Hash
}

// DerivableList is the input to DeriveSha.
// It is implemented by the 'Transactions' and 'Receipts' types.
// This is internal, do not use these methods.
type DerivableList interface {
Len() int
EncodeIndex(int, *bytes.Buffer)
}

func encodeForDerive(list DerivableList, i int, buf *bytes.Buffer) []byte {
buf.Reset()
list.EncodeIndex(i, buf)
// It's really unfortunate that we need to do perform this copy.
// StackTrie holds onto the values until Hash is called, so the values
// written to it must not alias.
return common.CopyBytes(buf.Bytes())
}

// DeriveSha creates the tree hashes of transactions, receipts, and withdrawals in a block header.
func DeriveSha(list DerivableList, hasher TrieHasher) common.Hash {
hasher.Reset()

valueBuf := encodeBufferPool.Get().(*bytes.Buffer)
defer encodeBufferPool.Put(valueBuf)

// StackTrie requires values to be inserted in increasing hash order, which is not the
// order that `list` provides hashes in. This insertion sequence ensures that the
// order is correct.
//
// The error returned by hasher is omitted because hasher will produce an incorrect
// hash in case any error occurs.
var indexBuf []byte
for i := 1; i < list.Len() && i <= 0x7f; i++ {
indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i))
value := encodeForDerive(list, i, valueBuf)
hasher.Update(indexBuf, value)
}
if list.Len() > 0 {
indexBuf = rlp.AppendUint64(indexBuf[:0], 0)
value := encodeForDerive(list, 0, valueBuf)
hasher.Update(indexBuf, value)
}
for i := 0x80; i < list.Len(); i++ {
indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i))
value := encodeForDerive(list, i, valueBuf)
hasher.Update(indexBuf, value)
}
wasm_dbg(111)
return hasher.Hash()
}

//go:wasmimport env wasm_dbg
//go:noescape
func wasm_dbg(uint64)

//go:wasmimport env require
//go:noescape
func require(uint32)

func require_bool(cond bool) {
if cond {
require(1)
} else {
require(0)
}
}
164 changes: 164 additions & 0 deletions op-geth/core/types/keccak256_wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//go:build js || wasm || wasip1
// +build js wasm wasip1
package types

import (
"encoding/binary"
"io"
)

//go:wasmimport env keccak_new
//go:noescape
func keccak_new(uint64)

//go:wasmimport env keccak_push
//go:noescape
func keccak_push(uint64)

//go:wasmimport env keccak_finalize
//go:noescape
func keccak_finalize() uint64

func NewHashHelper() *HashHelper {
return &HashHelper{}
}

type HashHelper struct {
data []byte
}

func (b *HashHelper) Write(p []byte) (n int, err error) {
b.data = append(b.data, p...)
return len(p), nil
}

func (b *HashHelper) WriteTo(w io.Writer) (err error) {
w.Write(b.data)
return nil
}

func (b *HashHelper) Hash() [32]byte {
size := uint64(len(b.data))
padding := size % 136
if padding != 0 {
padding = 136 - padding
} else {
padding = 136
}
buf := make([]byte, size+padding)
//wasm_dbg(size)
wasm_dbg(size + padding)
copy(buf, b.data)
hash := Keccak256Hash(buf, size, padding)
return hash
}

/*
*func (b HashHelper) PrintData() {
* for _, v := range b.data {
* wasm_dbg(v)
* }
* for i := 0; i < 136; i++ {
* wasm_dbg(v)
* }
*}
*/

var hash [32]byte

func Keccak256Hash(data []byte, size uint64, padding uint64) [32]byte {
total_len := len(data)
if padding == 1 {
data[total_len-1] = 0x81
} else {
data[size] = 0x01
data[total_len-1] = 0x80
}

var hash_0 uint64
var hash_1 uint64
var hash_2 uint64
var hash_3 uint64

var val uint64

round := total_len / 136
keccak_new(1)
for i := 0; i < round; i++ {
for j := 0; j < 17; j++ {
start := i*136 + j*8
val = binary.LittleEndian.Uint64(data[start : start+8])
keccak_push(val)
}
hash_0 = keccak_finalize()
hash_1 = keccak_finalize()
hash_2 = keccak_finalize()
hash_3 = keccak_finalize()
keccak_new(0)
}

binary.LittleEndian.PutUint64(hash[:], hash_0)
binary.LittleEndian.PutUint64(hash[8:], hash_1)
binary.LittleEndian.PutUint64(hash[16:], hash_2)
binary.LittleEndian.PutUint64(hash[24:], hash_3)

return hash
}

func Keccak256HashUint64(data []uint64) [32]byte {
var hash [32]byte
var hash_0 uint64
var hash_1 uint64
var hash_2 uint64
var hash_3 uint64

keccak_new(1)
round := len(data) / 17
for i := 0; i < round; i++ {
for j := 0; j < 17; j++ {
keccak_push(data[i*17+j])
}
hash_0 = keccak_finalize()
hash_1 = keccak_finalize()
hash_2 = keccak_finalize()
hash_3 = keccak_finalize()
keccak_new(0)
}

binary.LittleEndian.PutUint64(hash[:], hash_0)
binary.LittleEndian.PutUint64(hash[8:], hash_1)
binary.LittleEndian.PutUint64(hash[16:], hash_2)
binary.LittleEndian.PutUint64(hash[24:], hash_3)

return hash
}

/*
// for test

func keccak256check(input []byte, output []byte) {
result := Keccak256Hash(input)
for i := 0; i < len(result); i++ {
if result[i] != output[i] {
require(1)
require(0)
}
}
}

func main() {
input := make([]byte, 0)
emtpy_output := []byte{
197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83,
202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112,
}
keccak256check(input, emtpy_output)

input = []byte{102, 111, 111, 98, 97, 114, 97, 97}
short_output := []byte{
172, 132, 33, 155, 248, 181, 178, 245, 199, 105, 157, 164, 188, 53, 193, 25, 7, 35, 159,
188, 30, 123, 91, 143, 30, 100, 188, 128, 172, 248, 137, 202,
}
keccak256check(input, short_output)
}
*/
2 changes: 2 additions & 0 deletions op-preimage/oracle.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !(js || wasm || wasip1)
// +build !wasm,!wasip1, !js
package preimage

import (
Expand Down
Loading