diff options
author | obscuren <geffobscura@gmail.com> | 2015-05-31 21:05:00 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2015-06-04 04:39:17 +0800 |
commit | fa4aefee44c5dd32fb7e0d02960c1550e9c8a330 (patch) | |
tree | b9f9cbce2e773519722b2111aa7d0f86f4ef6c19 /core/vm/contracts.go | |
parent | 861031491860c69f29e1444c22dd84c38abfedf4 (diff) | |
download | go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.tar go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.tar.gz go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.tar.bz2 go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.tar.lz go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.tar.xz go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.tar.zst go-tangerine-fa4aefee44c5dd32fb7e0d02960c1550e9c8a330.zip |
core/vm: cleanup and renames
Diffstat (limited to 'core/vm/contracts.go')
-rw-r--r-- | core/vm/contracts.go | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/core/vm/contracts.go b/core/vm/contracts.go new file mode 100644 index 000000000..742017dd2 --- /dev/null +++ b/core/vm/contracts.go @@ -0,0 +1,98 @@ +package vm + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" + "github.com/ethereum/go-ethereum/params" +) + +type Address interface { + Call(in []byte) []byte +} + +type PrecompiledAccount struct { + Gas func(l int) *big.Int + fn func(in []byte) []byte +} + +func (self PrecompiledAccount) Call(in []byte) []byte { + return self.fn(in) +} + +var Precompiled = PrecompiledContracts() + +// XXX Could set directly. Testing requires resetting and setting of pre compiled contracts. +func PrecompiledContracts() map[string]*PrecompiledAccount { + return map[string]*PrecompiledAccount{ + // ECRECOVER + string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int { + return params.EcrecoverGas + }, ecrecoverFunc}, + + // SHA256 + string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int { + n := big.NewInt(int64(l+31) / 32) + n.Mul(n, params.Sha256WordGas) + return n.Add(n, params.Sha256Gas) + }, sha256Func}, + + // RIPEMD160 + string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int { + n := big.NewInt(int64(l+31) / 32) + n.Mul(n, params.Ripemd160WordGas) + return n.Add(n, params.Ripemd160Gas) + }, ripemd160Func}, + + string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int { + n := big.NewInt(int64(l+31) / 32) + n.Mul(n, params.IdentityWordGas) + + return n.Add(n, params.IdentityGas) + }, memCpy}, + } +} + +func sha256Func(in []byte) []byte { + return crypto.Sha256(in) +} + +func ripemd160Func(in []byte) []byte { + return common.LeftPadBytes(crypto.Ripemd160(in), 32) +} + +const ecRecoverInputLength = 128 + +func ecrecoverFunc(in []byte) []byte { + // "in" is (hash, v, r, s), each 32 bytes + // but for ecrecover we want (r, s, v) + if len(in) < ecRecoverInputLength { + return nil + } + + // Treat V as a 256bit integer + v := new(big.Int).Sub(common.Bytes2Big(in[32:64]), big.NewInt(27)) + // Ethereum requires V to be either 0 or 1 => (27 || 28) + if !(v.Cmp(Zero) == 0 || v.Cmp(One) == 0) { + return nil + } + + // v needs to be moved to the end + rsv := append(in[64:128], byte(v.Uint64())) + pubKey, err := crypto.Ecrecover(in[:32], rsv) + // make sure the public key is a valid one + if err != nil { + glog.V(logger.Error).Infof("EC RECOVER FAIL: ", err) + return nil + } + + // the first byte of pubkey is bitcoin heritage + return common.LeftPadBytes(crypto.Sha3(pubKey[1:])[12:], 32) +} + +func memCpy(in []byte) []byte { + return in +} |