-
Notifications
You must be signed in to change notification settings - Fork 0
/
precompiled.go
68 lines (56 loc) · 2.13 KB
/
precompiled.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package state
import (
"errors"
"github.com/ethereum/evmc/v10/bindings/go/evmc"
"github.com/umbracle/go-evm/precompiled"
)
var (
addr1 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
addr2 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
addr3 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}
addr4 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
addr5 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}
addr6 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}
addr7 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}
addr8 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}
addr9 = evmc.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}
)
var precompiledContracts map[evmc.Address]contract
func register(addr evmc.Address, b contract) {
if len(precompiledContracts) == 0 {
precompiledContracts = map[evmc.Address]contract{}
}
precompiledContracts[addr] = b
}
func init() {
register(addr1, &precompiled.Ecrecover{})
register(addr2, &precompiled.Sha256h{})
register(addr3, &precompiled.Ripemd160h{})
register(addr4, &precompiled.Identity{})
// Byzantium fork
register(addr5, &precompiled.ModExp{})
register(addr6, &precompiled.Bn256Add{})
register(addr7, &precompiled.Bn256Mul{})
register(addr8, &precompiled.Bn256Pairing{})
// Istanbul fork
register(addr9, &precompiled.Blake2f{})
}
type contract interface {
Gas(input []byte, rev evmc.Revision) uint64
Run(input []byte) ([]byte, error)
}
// runPrecompiled runs an execution
func runPrecompiled(codeAddress evmc.Address, input []byte, gas uint64, rev evmc.Revision) ([]byte, int64, error) {
contract := precompiledContracts[codeAddress]
gasCost := contract.Gas(input, rev)
// In the case of not enough gas for precompiled execution we return ErrOutOfGas
if gas < gasCost {
return nil, 0, errors.New("out of gas")
}
gas = gas - gasCost
returnValue, err := contract.Run(input)
if err != nil {
return nil, 0, err
}
return returnValue, int64(gas), nil
}