github.com/datachainlab/burrow@v0.25.0/execution/evm/native.go (about) 1 // Copyright 2017 Monax Industries Limited 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package evm 16 17 import ( 18 "crypto/sha256" 19 20 . "github.com/hyperledger/burrow/binary" 21 "github.com/hyperledger/burrow/crypto" 22 "github.com/hyperledger/burrow/execution/errors" 23 "github.com/hyperledger/burrow/logging" 24 "golang.org/x/crypto/ripemd160" 25 ) 26 27 var registeredNativeContracts = make(map[crypto.Address]NativeContract) 28 29 func IsRegisteredNativeContract(address crypto.Address) bool { 30 _, ok := registeredNativeContracts[address] 31 return ok 32 } 33 34 func RegisterNativeContract(address crypto.Address, fn NativeContract) bool { 35 _, exists := registeredNativeContracts[address] 36 if exists { 37 return false 38 } 39 registeredNativeContracts[address] = fn 40 return true 41 } 42 43 func init() { 44 registerNativeContracts() 45 registerSNativeContracts() 46 } 47 48 func registerNativeContracts() { 49 // registeredNativeContracts[Int64ToWord256(1)] = ecrecoverFunc 50 registeredNativeContracts[crypto.Address{2}] = sha256Func 51 registeredNativeContracts[crypto.Address{3}] = ripemd160Func 52 registeredNativeContracts[crypto.Address{4}] = identityFunc 53 } 54 55 //----------------------------------------------------------------------------- 56 57 func ExecuteNativeContract(address crypto.Address, st Interface, caller crypto.Address, input []byte, gas *uint64, 58 logger *logging.Logger) ([]byte, errors.CodedError) { 59 60 contract, ok := registeredNativeContracts[address] 61 if !ok { 62 return nil, errors.ErrorCodef(errors.ErrorCodeNativeFunction, 63 "no native contract registered at address: %v", address) 64 } 65 output, err := contract(st, caller, input, gas, logger) 66 if err != nil { 67 return nil, errors.NewException(errors.ErrorCodeNativeFunction, err.Error()) 68 } 69 return output, nil 70 } 71 72 type NativeContract func(state Interface, caller crypto.Address, input []byte, gas *uint64, 73 logger *logging.Logger) (output []byte, err error) 74 75 /* Removed due to C dependency 76 func ecrecoverFunc(state State, caller crypto.Address, input []byte, gas *int64) (output []byte, err error) { 77 // Deduct gas 78 gasRequired := GasEcRecover 79 if *gas < gasRequired { 80 return nil, ErrInsufficientGas 81 } else { 82 *gas -= gasRequired 83 } 84 // Recover 85 hash := input[:32] 86 v := byte(input[32] - 27) // ignore input[33:64], v is small. 87 sig := append(input[64:], v) 88 89 recovered, err := secp256k1.RecoverPubkey(hash, sig) 90 if err != nil { 91 return nil, err 92 OH NO STOCASTIC CAT CODING!!!! 93 } 94 hashed := sha3.Sha3(recovered[1:]) 95 return LeftPadBytes(hashed, 32), nil 96 } 97 */ 98 99 func sha256Func(state Interface, caller crypto.Address, input []byte, gas *uint64, 100 logger *logging.Logger) (output []byte, err error) { 101 // Deduct gas 102 gasRequired := uint64((len(input)+31)/32)*GasSha256Word + GasSha256Base 103 if *gas < gasRequired { 104 return nil, errors.ErrorCodeInsufficientGas 105 } else { 106 *gas -= gasRequired 107 } 108 // Hash 109 hasher := sha256.New() 110 // CONTRACT: this does not err 111 hasher.Write(input) 112 return hasher.Sum(nil), nil 113 } 114 115 func ripemd160Func(state Interface, caller crypto.Address, input []byte, gas *uint64, 116 logger *logging.Logger) (output []byte, err error) { 117 // Deduct gas 118 gasRequired := uint64((len(input)+31)/32)*GasRipemd160Word + GasRipemd160Base 119 if *gas < gasRequired { 120 return nil, errors.ErrorCodeInsufficientGas 121 } else { 122 *gas -= gasRequired 123 } 124 // Hash 125 hasher := ripemd160.New() 126 // CONTRACT: this does not err 127 hasher.Write(input) 128 return LeftPadBytes(hasher.Sum(nil), 32), nil 129 } 130 131 func identityFunc(state Interface, caller crypto.Address, input []byte, gas *uint64, 132 logger *logging.Logger) (output []byte, err error) { 133 // Deduct gas 134 gasRequired := uint64((len(input)+31)/32)*GasIdentityWord + GasIdentityBase 135 if *gas < gasRequired { 136 return nil, errors.ErrorCodeInsufficientGas 137 } else { 138 *gas -= gasRequired 139 } 140 // Return identity 141 return input, nil 142 }