|
|
- package vm
-
- import (
- "code.google.com/p/go.crypto/ripemd160"
- "crypto/sha256"
- . "github.com/tendermint/tendermint2/common"
- "github.com/tendermint/tendermint2/vm/secp256k1"
- "github.com/tendermint/tendermint2/vm/sha3"
- )
-
- var nativeContracts = make(map[Word256]NativeContract)
-
- func init() {
- nativeContracts[Uint64ToWord256(1)] = ecrecoverFunc
- nativeContracts[Uint64ToWord256(2)] = sha256Func
- nativeContracts[Uint64ToWord256(3)] = ripemd160Func
- nativeContracts[Uint64ToWord256(4)] = identityFunc
- }
-
- //-----------------------------------------------------------------------------
-
- type NativeContract func(input []byte, gas *uint64) (output []byte, err error)
-
- func ecrecoverFunc(input []byte, gas *uint64) (output []byte, err error) {
- // Deduct gas
- gasRequired := GasEcRecover
- if *gas < gasRequired {
- return nil, ErrInsufficientGas
- } else {
- *gas -= gasRequired
- }
- // Recover
- hash := input[:32]
- v := byte(input[32] - 27) // ignore input[33:64], v is small.
- sig := append(input[64:], v)
-
- recovered, err := secp256k1.RecoverPubkey(hash, sig)
- if err != nil {
- return nil, err
- }
- hashed := sha3.Sha3(recovered[1:])
- return RightPadBytes(hashed, 32), nil
- }
-
- func sha256Func(input []byte, gas *uint64) (output []byte, err error) {
- // Deduct gas
- gasRequired := uint64((len(input)+31)/32)*GasSha256Word + GasSha256Base
- if *gas < gasRequired {
- return nil, ErrInsufficientGas
- } else {
- *gas -= gasRequired
- }
- // Hash
- hasher := sha256.New()
- _, err = hasher.Write(input)
- if err != nil {
- panic(err)
- }
- return hasher.Sum(nil), nil
- }
-
- func ripemd160Func(input []byte, gas *uint64) (output []byte, err error) {
- // Deduct gas
- gasRequired := uint64((len(input)+31)/32)*GasRipemd160Word + GasRipemd160Base
- if *gas < gasRequired {
- return nil, ErrInsufficientGas
- } else {
- *gas -= gasRequired
- }
- // Hash
- hasher := ripemd160.New()
- _, err = hasher.Write(input)
- if err != nil {
- panic(err)
- }
- return RightPadBytes(hasher.Sum(nil), 32), nil
- }
-
- func identityFunc(input []byte, gas *uint64) (output []byte, err error) {
- // Deduct gas
- gasRequired := uint64((len(input)+31)/32)*GasIdentityWord + GasIdentityBase
- if *gas < gasRequired {
- return nil, ErrInsufficientGas
- } else {
- *gas -= gasRequired
- }
- // Return identity
- return input, nil
- }
|