You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
2.2 KiB

10 years ago
  1. package vm
  2. import (
  3. "code.google.com/p/go.crypto/ripemd160"
  4. "crypto/sha256"
  5. "github.com/tendermint/tendermint/vm/secp256k1"
  6. "github.com/tendermint/tendermint/vm/sha3"
  7. . "github.com/tendermint/tendermint/common"
  8. )
  9. var nativeContracts = make(map[Word]NativeContract)
  10. func init() {
  11. nativeContracts[Uint64ToWord(1)] = ecrecoverFunc
  12. nativeContracts[Uint64ToWord(2)] = sha256Func
  13. nativeContracts[Uint64ToWord(3)] = ripemd160Func
  14. nativeContracts[Uint64ToWord(4)] = identityFunc
  15. }
  16. //-----------------------------------------------------------------------------
  17. type NativeContract func(input []byte, gas *uint64) (output []byte, err error)
  18. func ecrecoverFunc(input []byte, gas *uint64) (output []byte, err error) {
  19. // Deduct gas
  20. gasRequired := GasEcRecover
  21. if *gas < gasRequired {
  22. return nil, ErrInsufficientGas
  23. } else {
  24. *gas -= gasRequired
  25. }
  26. // Recover
  27. hash := input[:32]
  28. v := byte(input[32] - 27) // ignore input[33:64], v is small.
  29. sig := append(input[64:], v)
  30. recovered, err := secp256k1.RecoverPubkey(hash, sig)
  31. if err != nil {
  32. return nil, err
  33. }
  34. hashed := sha3.Sha3(recovered[1:])
  35. return RightPadBytes(hashed, 32), nil
  36. }
  37. func sha256Func(input []byte, gas *uint64) (output []byte, err error) {
  38. // Deduct gas
  39. gasRequired := uint64((len(input)+31)/32)*GasSha256Word + GasSha256Base
  40. if *gas < gasRequired {
  41. return nil, ErrInsufficientGas
  42. } else {
  43. *gas -= gasRequired
  44. }
  45. // Hash
  46. hasher := sha256.New()
  47. _, err = hasher.Write(input)
  48. if err != nil {
  49. panic(err)
  50. }
  51. return hasher.Sum(nil), nil
  52. }
  53. func ripemd160Func(input []byte, gas *uint64) (output []byte, err error) {
  54. // Deduct gas
  55. gasRequired := uint64((len(input)+31)/32)*GasRipemd160Word + GasRipemd160Base
  56. if *gas < gasRequired {
  57. return nil, ErrInsufficientGas
  58. } else {
  59. *gas -= gasRequired
  60. }
  61. // Hash
  62. hasher := ripemd160.New()
  63. _, err = hasher.Write(input)
  64. if err != nil {
  65. panic(err)
  66. }
  67. return RightPadBytes(hasher.Sum(nil), 32), nil
  68. }
  69. func identityFunc(input []byte, gas *uint64) (output []byte, err error) {
  70. // Deduct gas
  71. gasRequired := uint64((len(input)+31)/32)*GasIdentityWord + GasIdentityBase
  72. if *gas < gasRequired {
  73. return nil, ErrInsufficientGas
  74. } else {
  75. *gas -= gasRequired
  76. }
  77. // Return identity
  78. return input, nil
  79. }