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.

89 lines
2.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package vm
  2. import (
  3. "code.google.com/p/go.crypto/ripemd160"
  4. "crypto/sha256"
  5. . "github.com/tendermint/tendermint/common"
  6. "github.com/tendermint/tendermint/vm/secp256k1"
  7. "github.com/tendermint/tendermint/vm/sha3"
  8. )
  9. var nativeContracts = make(map[Word256]NativeContract)
  10. func init() {
  11. nativeContracts[Uint64ToWord256(1)] = ecrecoverFunc
  12. nativeContracts[Uint64ToWord256(2)] = sha256Func
  13. nativeContracts[Uint64ToWord256(3)] = ripemd160Func
  14. nativeContracts[Uint64ToWord256(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 LeftPadBytes(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 LeftPadBytes(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. }