contracts.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright 2014 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package vm
  17. import (
  18. "math/big"
  19. "github.com/ethereum/go-ethereum/common"
  20. "github.com/ethereum/go-ethereum/crypto"
  21. "github.com/ethereum/go-ethereum/logger"
  22. "github.com/ethereum/go-ethereum/logger/glog"
  23. "github.com/ethereum/go-ethereum/params"
  24. )
  25. type Address interface {
  26. Call(in []byte) []byte
  27. }
  28. type PrecompiledAccount struct {
  29. Gas func(l int) *big.Int
  30. fn func(in []byte) []byte
  31. }
  32. func (self PrecompiledAccount) Call(in []byte) []byte {
  33. return self.fn(in)
  34. }
  35. var Precompiled = PrecompiledContracts()
  36. // XXX Could set directly. Testing requires resetting and setting of pre compiled contracts.
  37. func PrecompiledContracts() map[string]*PrecompiledAccount {
  38. return map[string]*PrecompiledAccount{
  39. // ECRECOVER
  40. string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int {
  41. return params.EcrecoverGas
  42. }, ecrecoverFunc},
  43. // SHA256
  44. string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int {
  45. n := big.NewInt(int64(l+31) / 32)
  46. n.Mul(n, params.Sha256WordGas)
  47. return n.Add(n, params.Sha256Gas)
  48. }, sha256Func},
  49. // RIPEMD160
  50. string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int {
  51. n := big.NewInt(int64(l+31) / 32)
  52. n.Mul(n, params.Ripemd160WordGas)
  53. return n.Add(n, params.Ripemd160Gas)
  54. }, ripemd160Func},
  55. string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int {
  56. n := big.NewInt(int64(l+31) / 32)
  57. n.Mul(n, params.IdentityWordGas)
  58. return n.Add(n, params.IdentityGas)
  59. }, memCpy},
  60. }
  61. }
  62. func sha256Func(in []byte) []byte {
  63. return crypto.Sha256(in)
  64. }
  65. func ripemd160Func(in []byte) []byte {
  66. return common.LeftPadBytes(crypto.Ripemd160(in), 32)
  67. }
  68. const ecRecoverInputLength = 128
  69. func ecrecoverFunc(in []byte) []byte {
  70. in = common.RightPadBytes(in, 128)
  71. // "in" is (hash, v, r, s), each 32 bytes
  72. // but for ecrecover we want (r, s, v)
  73. r := common.BytesToBig(in[64:96])
  74. s := common.BytesToBig(in[96:128])
  75. // Treat V as a 256bit integer
  76. vbig := common.Bytes2Big(in[32:64])
  77. v := byte(vbig.Uint64())
  78. if !crypto.ValidateSignatureValues(v, r, s) {
  79. glog.V(logger.Debug).Infof("EC RECOVER FAIL: v, r or s value invalid")
  80. return nil
  81. }
  82. // v needs to be at the end and normalized for libsecp256k1
  83. vbignormal := new(big.Int).Sub(vbig, big.NewInt(27))
  84. vnormal := byte(vbignormal.Uint64())
  85. rsv := append(in[64:128], vnormal)
  86. pubKey, err := crypto.Ecrecover(in[:32], rsv)
  87. // make sure the public key is a valid one
  88. if err != nil {
  89. glog.V(logger.Error).Infof("EC RECOVER FAIL: ", err)
  90. return nil
  91. }
  92. // the first byte of pubkey is bitcoin heritage
  93. return common.LeftPadBytes(crypto.Sha3(pubKey[1:])[12:], 32)
  94. }
  95. func memCpy(in []byte) []byte {
  96. return in
  97. }