embedded_mips.go 2.8 KB
Newer Older
1
//go:build mips
George Hotz's avatar
George Hotz committed
2
// +build mips
3 4 5 6 7 8

package oracle

import (
	"math/big"
	"os"
9 10
	"reflect"
	"unsafe"
11 12

	"github.com/ethereum/go-ethereum/common"
George Hotz's avatar
George Hotz committed
13
	"github.com/ethereum/go-ethereum/core/types"
14
	"github.com/ethereum/go-ethereum/crypto"
15 16
)

George Hotz's avatar
George Hotz committed
17
var preimages = make(map[common.Hash][]byte)
George Hotz's avatar
George Hotz committed
18

George Hotz's avatar
George Hotz committed
19 20
// only 6 here
var inputs [6]common.Hash
George Hotz's avatar
George Hotz committed
21 22
var inputsLoaded bool = false

23 24 25 26 27 28 29 30 31
func byteAt(addr uint64, length int) []byte {
	var ret []byte
	bh := (*reflect.SliceHeader)(unsafe.Pointer(&ret))
	bh.Data = uintptr(addr)
	bh.Len = length
	bh.Cap = length
	return ret
}

George Hotz's avatar
George Hotz committed
32
func Input(index int) common.Hash {
33
	if index < 0 || index > 6 {
George Hotz's avatar
George Hotz committed
34 35 36
		panic("bad input index")
	}
	if !inputsLoaded {
37 38
		// before this isn't run on chain (confirm this isn't cached)
		// does this interact with the GC?
39
		ret := byteAt(0xB0000000, len(inputs)*0x20)
40 41

		os.Stderr.WriteString("********* on chain starts here *********\n")
George Hotz's avatar
George Hotz committed
42 43 44

		for i := 0; i < len(inputs); i++ {
			inputs[i] = common.BytesToHash(ret[i*0x20 : i*0x20+0x20])
45
			//fmt.Println(i, inputs[i])
George Hotz's avatar
George Hotz committed
46 47 48 49 50 51 52
		}

		inputsLoaded = true
	}
	return inputs[index]
}

George Hotz's avatar
George Hotz committed
53
func Halt() {
54 55
	//os.Stderr.WriteString("THIS SHOULD BE PATCHED OUT\n")
	// the exit syscall is a jump to 0x5ead0000 now
George Hotz's avatar
George Hotz committed
56 57 58
	os.Exit(0)
}

George Hotz's avatar
George Hotz committed
59
func Output(output common.Hash, receipts common.Hash) {
60
	ret := byteAt(0xB0000804, 0x20)
61
	copy(ret, output.Bytes())
62
	rret := byteAt(0xB0000824, 0x20)
George Hotz's avatar
George Hotz committed
63
	copy(rret, receipts.Bytes())
64
	magic := byteAt(0xB0000800, 4)
65
	copy(magic, []byte{0x13, 0x37, 0xf0, 0x0d})
George Hotz's avatar
George Hotz committed
66
	Halt()
George Hotz's avatar
George Hotz committed
67
}
68

George Hotz's avatar
George Hotz committed
69 70 71
func Preimage(hash common.Hash) []byte {
	val, ok := preimages[hash]
	if !ok {
George Hotz's avatar
George Hotz committed
72
		// load in hash
73
		preImageHash := byteAt(0xB0001000, 0x20)
George Hotz's avatar
George Hotz committed
74 75 76 77 78 79 80
		copy(preImageHash, hash.Bytes())

		// used in unicorn emulator to trigger the load
		// in onchain mips, it's instant
		os.Getpid()

		// ready
81
		rawSize := common.CopyBytes(byteAt(0xB1000000, 4))
George Hotz's avatar
George Hotz committed
82
		size := (int(rawSize[0]) << 24) | (int(rawSize[1]) << 16) | (int(rawSize[2]) << 8) | int(rawSize[3])
83
		ret := common.CopyBytes(byteAt(0xB1000004, size))
George Hotz's avatar
George Hotz committed
84

85 86
		// this is 20% of the exec instructions, this speedup is always an option
		realhash := crypto.Keccak256Hash(ret)
George Hotz's avatar
George Hotz committed
87 88
		if realhash != hash {
			panic("preimage has wrong hash")
89
		}
George Hotz's avatar
George Hotz committed
90 91 92

		preimages[hash] = ret
		return ret
93
	}
George Hotz's avatar
George Hotz committed
94
	return val
95 96 97
}

// these are stubs in embedded world
98 99
func PrefetchStorage(*big.Int, common.Address, common.Hash, func(map[common.Hash][]byte)) {}
func PrefetchAccount(*big.Int, common.Address, func(map[common.Hash][]byte))              {}
100 101 102 103 104 105 106 107
func PrefetchCode(blockNumber *big.Int, addrHash common.Hash)                             {}
func PrefetchBlock(blockNumber *big.Int, startBlock bool, hasher types.TrieHasher)        {}

// KeyValueWriter wraps the Put method of a backing data store.
type PreimageKeyValueWriter struct{}

func (kw PreimageKeyValueWriter) Put(key []byte, value []byte) error { return nil }
func (kw PreimageKeyValueWriter) Delete(key []byte) error            { return nil }