mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
precompiled contract for privacy contract
This commit is contained in:
parent
fcb5aaff61
commit
1be6007042
5 changed files with 828 additions and 18 deletions
|
|
@ -92,6 +92,24 @@ func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
|
||||||
return fmt.Errorf("abi: could not locate named method or event")
|
return fmt.Errorf("abi: could not locate named method or event")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (abi ABI) UnpackTmp(v interface{}, name string, output []byte) (err error) {
|
||||||
|
if len(output) == 0 {
|
||||||
|
return fmt.Errorf("abi: unmarshalling empty output")
|
||||||
|
}
|
||||||
|
// since there can't be naming collisions with contracts and events,
|
||||||
|
// we need to decide whether we're calling a method or an event
|
||||||
|
if method, ok := abi.Methods[name]; ok {
|
||||||
|
// old stamp tx can't run in testnet.
|
||||||
|
//if len(output)%32 != 0 {
|
||||||
|
// return fmt.Errorf("abi: improperly formatted output")
|
||||||
|
//}
|
||||||
|
return method.Outputs.Unpack(v, output)
|
||||||
|
} else if event, ok := abi.Events[name]; ok {
|
||||||
|
return event.Inputs.Unpack(v, output)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("abi: could not locate named method or event")
|
||||||
|
}
|
||||||
|
|
||||||
// UnpackIntoMap unpacks a log into the provided map[string]interface{}
|
// UnpackIntoMap unpacks a log into the provided map[string]interface{}
|
||||||
func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
|
func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -17,26 +17,69 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/blake2b"
|
"github.com/ethereum/go-ethereum/crypto/blake2b"
|
||||||
"github.com/ethereum/go-ethereum/crypto/bn256"
|
"github.com/ethereum/go-ethereum/crypto/bn256"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"golang.org/x/crypto/ripemd160"
|
"golang.org/x/crypto/ripemd160"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
useCoinPrecompileAddr = common.BytesToAddress([]byte{100})
|
||||||
|
useStampPrecompileAddr = common.BytesToAddress([]byte{200})
|
||||||
|
|
||||||
|
otaBalanceStorageAddr = common.BytesToAddress(big.NewInt(300).Bytes())
|
||||||
|
otaImageStorageAddr = common.BytesToAddress(big.NewInt(301).Bytes())
|
||||||
|
|
||||||
|
// 0.01wei --> "0x0000000000000000000000010000000000000000"
|
||||||
|
otaBalancePercentdot001WStorageAddr = common.HexToAddress(UseStampdot001)
|
||||||
|
otaBalancePercentdot002WStorageAddr = common.HexToAddress(UseStampdot002)
|
||||||
|
otaBalancePercentdot005WStorageAddr = common.HexToAddress(UseStampdot005)
|
||||||
|
|
||||||
|
otaBalancePercentdot003WStorageAddr = common.HexToAddress(UseStampdot003)
|
||||||
|
otaBalancePercentdot006WStorageAddr = common.HexToAddress(UseStampdot006)
|
||||||
|
otaBalancePercentdot009WStorageAddr = common.HexToAddress(UseStampdot009)
|
||||||
|
|
||||||
|
otaBalancePercentdot03WStorageAddr = common.HexToAddress(UseStampdot03)
|
||||||
|
otaBalancePercentdot06WStorageAddr = common.HexToAddress(UseStampdot06)
|
||||||
|
otaBalancePercentdot09WStorageAddr = common.HexToAddress(UseStampdot09)
|
||||||
|
otaBalancePercentdot2WStorageAddr = common.HexToAddress(UseStampdot2)
|
||||||
|
otaBalancePercentdot5WStorageAddr = common.HexToAddress(UseStampdot5)
|
||||||
|
|
||||||
|
otaBalance10WStorageAddr = common.HexToAddress(Usecoin10)
|
||||||
|
otaBalance20WStorageAddr = common.HexToAddress(Usecoin20)
|
||||||
|
otaBalance50WStorageAddr = common.HexToAddress(Usecoin50)
|
||||||
|
otaBalance100WStorageAddr = common.HexToAddress(Usecoin100)
|
||||||
|
|
||||||
|
otaBalance200WStorageAddr = common.HexToAddress(Usecoin200)
|
||||||
|
otaBalance500WStorageAddr = common.HexToAddress(Usecoin500)
|
||||||
|
otaBalance1000WStorageAddr = common.HexToAddress(Usecoin1000)
|
||||||
|
otaBalance5000WStorageAddr = common.HexToAddress(Usecoin5000)
|
||||||
|
otaBalance50000WStorageAddr = common.HexToAddress(Usecoin50000)
|
||||||
|
)
|
||||||
|
|
||||||
// PrecompiledContract is the basic interface for native Go contracts. The implementation
|
// PrecompiledContract is the basic interface for native Go contracts. The implementation
|
||||||
// requires a deterministic gas count based on the input size of the Run method of the
|
// requires a deterministic gas count based on the input size of the Run method of the
|
||||||
// contract.
|
// contract.
|
||||||
type PrecompiledContract interface {
|
type PrecompiledContract interface {
|
||||||
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
|
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
|
||||||
Run(input []byte) ([]byte, error) // Run runs the precompiled contract
|
Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) // Run runs the precompiled contract
|
||||||
|
ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
|
||||||
|
|
@ -46,6 +89,9 @@ var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||||
|
|
||||||
|
useCoinPrecompileAddr: &useCoinSC{},
|
||||||
|
useStampPrecompileAddr: &usechainStampSC{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
|
||||||
|
|
@ -59,6 +105,9 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
|
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
|
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
||||||
|
|
||||||
|
useCoinPrecompileAddr: &useCoinSC{},
|
||||||
|
useStampPrecompileAddr: &usechainStampSC{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
|
||||||
|
|
@ -73,13 +122,16 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
common.BytesToAddress([]byte{9}): &blake2F{},
|
||||||
|
|
||||||
|
useCoinPrecompileAddr: &useCoinSC{},
|
||||||
|
useStampPrecompileAddr: &usechainStampSC{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
|
// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
|
||||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
|
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract, evm *EVM) (ret []byte, err error) {
|
||||||
gas := p.RequiredGas(input)
|
gas := p.RequiredGas(input)
|
||||||
if contract.UseGas(gas) {
|
if contract.UseGas(gas) {
|
||||||
return p.Run(input)
|
return p.Run(input, contract, evm)
|
||||||
}
|
}
|
||||||
return nil, ErrOutOfGas
|
return nil, ErrOutOfGas
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +143,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 {
|
||||||
return params.EcrecoverGas
|
return params.EcrecoverGas
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ecrecover) Run(input []byte) ([]byte, error) {
|
func (c *ecrecover) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
const ecRecoverInputLength = 128
|
const ecRecoverInputLength = 128
|
||||||
|
|
||||||
input = common.RightPadBytes(input, ecRecoverInputLength)
|
input = common.RightPadBytes(input, ecRecoverInputLength)
|
||||||
|
|
@ -117,6 +169,10 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
|
||||||
return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
|
return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ecrecover) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SHA256 implemented as a native contract.
|
// SHA256 implemented as a native contract.
|
||||||
type sha256hash struct{}
|
type sha256hash struct{}
|
||||||
|
|
||||||
|
|
@ -127,11 +183,15 @@ type sha256hash struct{}
|
||||||
func (c *sha256hash) RequiredGas(input []byte) uint64 {
|
func (c *sha256hash) RequiredGas(input []byte) uint64 {
|
||||||
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
|
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
|
||||||
}
|
}
|
||||||
func (c *sha256hash) Run(input []byte) ([]byte, error) {
|
func (c *sha256hash) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
h := sha256.Sum256(input)
|
h := sha256.Sum256(input)
|
||||||
return h[:], nil
|
return h[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *sha256hash) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// RIPEMD160 implemented as a native contract.
|
// RIPEMD160 implemented as a native contract.
|
||||||
type ripemd160hash struct{}
|
type ripemd160hash struct{}
|
||||||
|
|
||||||
|
|
@ -142,12 +202,16 @@ type ripemd160hash struct{}
|
||||||
func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
|
func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
|
||||||
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
|
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
|
||||||
}
|
}
|
||||||
func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
|
func (c *ripemd160hash) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
ripemd := ripemd160.New()
|
ripemd := ripemd160.New()
|
||||||
ripemd.Write(input)
|
ripemd.Write(input)
|
||||||
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
|
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ripemd160hash) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// data copy implemented as a native contract.
|
// data copy implemented as a native contract.
|
||||||
type dataCopy struct{}
|
type dataCopy struct{}
|
||||||
|
|
||||||
|
|
@ -158,10 +222,14 @@ type dataCopy struct{}
|
||||||
func (c *dataCopy) RequiredGas(input []byte) uint64 {
|
func (c *dataCopy) RequiredGas(input []byte) uint64 {
|
||||||
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
|
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
|
||||||
}
|
}
|
||||||
func (c *dataCopy) Run(in []byte) ([]byte, error) {
|
func (c *dataCopy) Run(in []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *dataCopy) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// bigModExp implements a native big integer exponential modular operation.
|
// bigModExp implements a native big integer exponential modular operation.
|
||||||
type bigModExp struct{}
|
type bigModExp struct{}
|
||||||
|
|
||||||
|
|
@ -239,7 +307,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
||||||
return gas.Uint64()
|
return gas.Uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bigModExp) Run(input []byte) ([]byte, error) {
|
func (c *bigModExp) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
|
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
|
||||||
expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
|
expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
|
||||||
|
|
@ -267,6 +335,10 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
|
||||||
return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil
|
return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bigModExp) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
|
// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
|
||||||
// returning it, or an error if the point is invalid.
|
// returning it, or an error if the point is invalid.
|
||||||
func newCurvePoint(blob []byte) (*bn256.G1, error) {
|
func newCurvePoint(blob []byte) (*bn256.G1, error) {
|
||||||
|
|
@ -312,10 +384,14 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
|
||||||
return params.Bn256AddGasIstanbul
|
return params.Bn256AddGasIstanbul
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
|
func (c *bn256AddIstanbul) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return runBn256Add(input)
|
return runBn256Add(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bn256AddIstanbul) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// bn256AddByzantium implements a native elliptic curve point addition
|
// bn256AddByzantium implements a native elliptic curve point addition
|
||||||
// conforming to Byzantium consensus rules.
|
// conforming to Byzantium consensus rules.
|
||||||
type bn256AddByzantium struct{}
|
type bn256AddByzantium struct{}
|
||||||
|
|
@ -325,10 +401,14 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
|
||||||
return params.Bn256AddGasByzantium
|
return params.Bn256AddGasByzantium
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) {
|
func (c *bn256AddByzantium) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return runBn256Add(input)
|
return runBn256Add(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bn256AddByzantium) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
|
// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
|
||||||
// both Byzantium and Istanbul operations.
|
// both Byzantium and Istanbul operations.
|
||||||
func runBn256ScalarMul(input []byte) ([]byte, error) {
|
func runBn256ScalarMul(input []byte) ([]byte, error) {
|
||||||
|
|
@ -350,10 +430,14 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
|
||||||
return params.Bn256ScalarMulGasIstanbul
|
return params.Bn256ScalarMulGasIstanbul
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
|
func (c *bn256ScalarMulIstanbul) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return runBn256ScalarMul(input)
|
return runBn256ScalarMul(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bn256ScalarMulIstanbul) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// bn256ScalarMulByzantium implements a native elliptic curve scalar
|
// bn256ScalarMulByzantium implements a native elliptic curve scalar
|
||||||
// multiplication conforming to Byzantium consensus rules.
|
// multiplication conforming to Byzantium consensus rules.
|
||||||
type bn256ScalarMulByzantium struct{}
|
type bn256ScalarMulByzantium struct{}
|
||||||
|
|
@ -363,10 +447,14 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
|
||||||
return params.Bn256ScalarMulGasByzantium
|
return params.Bn256ScalarMulGasByzantium
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) {
|
func (c *bn256ScalarMulByzantium) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return runBn256ScalarMul(input)
|
return runBn256ScalarMul(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bn256ScalarMulByzantium) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// true32Byte is returned if the bn256 pairing check succeeds.
|
// true32Byte is returned if the bn256 pairing check succeeds.
|
||||||
true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
||||||
|
|
@ -418,10 +506,14 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
|
||||||
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
|
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
|
func (c *bn256PairingIstanbul) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return runBn256Pairing(input)
|
return runBn256Pairing(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bn256PairingIstanbul) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve
|
// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve
|
||||||
// conforming to Byzantium consensus rules.
|
// conforming to Byzantium consensus rules.
|
||||||
type bn256PairingByzantium struct{}
|
type bn256PairingByzantium struct{}
|
||||||
|
|
@ -431,10 +523,14 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
|
||||||
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
|
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) {
|
func (c *bn256PairingByzantium) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
return runBn256Pairing(input)
|
return runBn256Pairing(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *bn256PairingByzantium) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type blake2F struct{}
|
type blake2F struct{}
|
||||||
|
|
||||||
func (c *blake2F) RequiredGas(input []byte) uint64 {
|
func (c *blake2F) RequiredGas(input []byte) uint64 {
|
||||||
|
|
@ -457,7 +553,7 @@ var (
|
||||||
errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
|
errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *blake2F) Run(input []byte) ([]byte, error) {
|
func (c *blake2F) Run(input []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
// Make sure the input is valid (correct lenth and final flag)
|
// Make sure the input is valid (correct lenth and final flag)
|
||||||
if len(input) != blake2FInputLength {
|
if len(input) != blake2FInputLength {
|
||||||
return nil, errBlake2FInvalidInputLength
|
return nil, errBlake2FInvalidInputLength
|
||||||
|
|
@ -495,3 +591,584 @@ func (c *blake2F) Run(input []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
return output, nil
|
return output, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *blake2F) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// errNotOnCurve is returned if a point being unmarshalled as a bn256 elliptic
|
||||||
|
// curve point is not on the curve.
|
||||||
|
errNotOnCurve = errors.New("point not on elliptic curve")
|
||||||
|
|
||||||
|
// errInvalidCurvePoint is returned if a point being unmarshalled as a bn256
|
||||||
|
// elliptic curve point is invalid.
|
||||||
|
errInvalidCurvePoint = errors.New("invalid elliptic curve point")
|
||||||
|
|
||||||
|
// invalid ring signed info
|
||||||
|
ErrInvalidRingSigned = errors.New("invalid ring signed info")
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
coinSCDefinition = `
|
||||||
|
[{"constant": false,"type": "function","stateMutability": "nonpayable","inputs": [{"name": "OtaAddr","type":"string"},{"name": "Value","type": "uint256"}],"name": "buyCoinNote","outputs": [{"name": "OtaAddr","type":"string"},{"name": "Value","type": "uint256"}]},{"constant": false,"type": "function","inputs": [{"name":"RingSignedData","type": "string"},{"name": "Value","type": "uint256"}],"name": "refundCoin","outputs": [{"name": "RingSignedData","type": "string"},{"name": "Value","type": "uint256"}]},{"constant": false,"type": "function","stateMutability": "nonpayable","inputs": [],"name": "getCoins","outputs": [{"name":"Value","type": "uint256"}]}]`
|
||||||
|
|
||||||
|
stampSCDefinition = `[{"constant": false,"type": "function","stateMutability": "nonpayable","inputs": [{"name":"OtaAddr","type": "string"},{"name": "Value","type": "uint256"}],"name": "buyStamp","outputs": [{"name": "OtaAddr","type": "string"},{"name": "Value","type": "uint256"}]},{"constant": false,"type": "function","inputs": [{"name": "RingSignedData","type": "string"},{"name": "Value","type": "uint256"}],"name": "refundCoin","outputs": [{"name": "RingSignedData","type": "string"},{"name": "Value","type": "uint256"}]},{"constant": false,"type": "function","stateMutability": "nonpayable","inputs": [],"name": "getCoins","outputs": [{"name": "Value","type": "uint256"}]}]`
|
||||||
|
|
||||||
|
coinAbi, errCoinSCInit = abi.JSON(strings.NewReader(coinSCDefinition))
|
||||||
|
buyIdArr, refundIdArr, getCoinsIdArr [4]byte
|
||||||
|
|
||||||
|
stampAbi, errStampSCInit = abi.JSON(strings.NewReader(stampSCDefinition))
|
||||||
|
stBuyId [4]byte
|
||||||
|
|
||||||
|
errBuyCoin = errors.New("error in buy coin")
|
||||||
|
errRefundCoin = errors.New("error in refund coin")
|
||||||
|
|
||||||
|
errBuyStamp = errors.New("error in buy stamp")
|
||||||
|
|
||||||
|
errParameters = errors.New("error parameters")
|
||||||
|
errMethodId = errors.New("error method id")
|
||||||
|
|
||||||
|
errBalance = errors.New("balance is insufficient")
|
||||||
|
|
||||||
|
errStampValue = errors.New("stamp value is not support")
|
||||||
|
|
||||||
|
errCoinValue = errors.New("usecoin value is not support")
|
||||||
|
|
||||||
|
ErrMismatchedValue = errors.New("mismatched usecoin value")
|
||||||
|
|
||||||
|
ErrInvalidOTASet = errors.New("invalid OTA mix set")
|
||||||
|
|
||||||
|
ErrOTAReused = errors.New("OTA is reused")
|
||||||
|
|
||||||
|
StampValueSet = make(map[string]string, 5)
|
||||||
|
UseCoinValueSet = make(map[string]string, 10)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Usecoin10 = "10000000000000000000" //10
|
||||||
|
Usecoin20 = "20000000000000000000" //20
|
||||||
|
Usecoin50 = "50000000000000000000" //50
|
||||||
|
Usecoin100 = "100000000000000000000" //100
|
||||||
|
|
||||||
|
Usecoin200 = "200000000000000000000" //200
|
||||||
|
Usecoin500 = "500000000000000000000" //500
|
||||||
|
Usecoin1000 = "1000000000000000000000" //1000
|
||||||
|
Usecoin5000 = "5000000000000000000000" //5000
|
||||||
|
Usecoin50000 = "50000000000000000000000" //50000
|
||||||
|
|
||||||
|
UseStampdot001 = "1000000000000000" //0.001
|
||||||
|
UseStampdot002 = "2000000000000000" //0.002
|
||||||
|
UseStampdot005 = "5000000000000000" //0.005
|
||||||
|
|
||||||
|
UseStampdot003 = "3000000000000000" //0.003
|
||||||
|
UseStampdot006 = "6000000000000000" //0.006
|
||||||
|
UseStampdot009 = "9000000000000000" //0.009
|
||||||
|
|
||||||
|
UseStampdot03 = "30000000000000000" //0.03
|
||||||
|
UseStampdot06 = "60000000000000000" //0.06
|
||||||
|
UseStampdot09 = "90000000000000000" //0.09
|
||||||
|
UseStampdot2 = "200000000000000000" //0.2
|
||||||
|
UseStampdot3 = "300000000000000000" //0.3
|
||||||
|
UseStampdot5 = "500000000000000000" //0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if errCoinSCInit != nil || errStampSCInit != nil {
|
||||||
|
panic("err in coin sc initialize or stamp error initialize ")
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(buyIdArr[:], coinAbi.Methods["buyCoinNote"].ID())
|
||||||
|
copy(refundIdArr[:], coinAbi.Methods["refundCoin"].ID())
|
||||||
|
copy(getCoinsIdArr[:], coinAbi.Methods["getCoins"].ID())
|
||||||
|
|
||||||
|
copy(stBuyId[:], stampAbi.Methods["buyStamp"].ID())
|
||||||
|
|
||||||
|
svaldot001, _ := new(big.Int).SetString(UseStampdot001, 10)
|
||||||
|
StampValueSet[svaldot001.Text(16)] = UseStampdot001
|
||||||
|
|
||||||
|
svaldot002, _ := new(big.Int).SetString(UseStampdot002, 10)
|
||||||
|
StampValueSet[svaldot002.Text(16)] = UseStampdot002
|
||||||
|
|
||||||
|
svaldot005, _ := new(big.Int).SetString(UseStampdot005, 10)
|
||||||
|
StampValueSet[svaldot005.Text(16)] = UseStampdot005
|
||||||
|
|
||||||
|
svaldot003, _ := new(big.Int).SetString(UseStampdot003, 10)
|
||||||
|
StampValueSet[svaldot003.Text(16)] = UseStampdot003
|
||||||
|
|
||||||
|
svaldot006, _ := new(big.Int).SetString(UseStampdot006, 10)
|
||||||
|
StampValueSet[svaldot006.Text(16)] = UseStampdot006
|
||||||
|
|
||||||
|
svaldot009, _ := new(big.Int).SetString(UseStampdot009, 10)
|
||||||
|
StampValueSet[svaldot009.Text(16)] = UseStampdot009
|
||||||
|
|
||||||
|
svaldot03, _ := new(big.Int).SetString(UseStampdot03, 10)
|
||||||
|
StampValueSet[svaldot03.Text(16)] = UseStampdot03
|
||||||
|
|
||||||
|
svaldot06, _ := new(big.Int).SetString(UseStampdot06, 10)
|
||||||
|
StampValueSet[svaldot06.Text(16)] = UseStampdot06
|
||||||
|
|
||||||
|
svaldot09, _ := new(big.Int).SetString(UseStampdot09, 10)
|
||||||
|
StampValueSet[svaldot09.Text(16)] = UseStampdot09
|
||||||
|
|
||||||
|
svaldot2, _ := new(big.Int).SetString(UseStampdot2, 10)
|
||||||
|
StampValueSet[svaldot2.Text(16)] = UseStampdot2
|
||||||
|
|
||||||
|
svaldot3, _ := new(big.Int).SetString(UseStampdot3, 10)
|
||||||
|
StampValueSet[svaldot3.Text(16)] = UseStampdot3
|
||||||
|
|
||||||
|
svaldot5, _ := new(big.Int).SetString(UseStampdot5, 10)
|
||||||
|
StampValueSet[svaldot5.Text(16)] = UseStampdot5
|
||||||
|
|
||||||
|
cval10, _ := new(big.Int).SetString(Usecoin10, 10)
|
||||||
|
UseCoinValueSet[cval10.Text(16)] = Usecoin10
|
||||||
|
|
||||||
|
cval20, _ := new(big.Int).SetString(Usecoin20, 10)
|
||||||
|
UseCoinValueSet[cval20.Text(16)] = Usecoin20
|
||||||
|
|
||||||
|
cval50, _ := new(big.Int).SetString(Usecoin50, 10)
|
||||||
|
UseCoinValueSet[cval50.Text(16)] = Usecoin50
|
||||||
|
|
||||||
|
cval100, _ := new(big.Int).SetString(Usecoin100, 10)
|
||||||
|
UseCoinValueSet[cval100.Text(16)] = Usecoin100
|
||||||
|
|
||||||
|
cval200, _ := new(big.Int).SetString(Usecoin200, 10)
|
||||||
|
UseCoinValueSet[cval200.Text(16)] = Usecoin200
|
||||||
|
|
||||||
|
cval500, _ := new(big.Int).SetString(Usecoin500, 10)
|
||||||
|
UseCoinValueSet[cval500.Text(16)] = Usecoin500
|
||||||
|
|
||||||
|
cval1000, _ := new(big.Int).SetString(Usecoin1000, 10)
|
||||||
|
UseCoinValueSet[cval1000.Text(16)] = Usecoin1000
|
||||||
|
|
||||||
|
cval5000, _ := new(big.Int).SetString(Usecoin5000, 10)
|
||||||
|
UseCoinValueSet[cval5000.Text(16)] = Usecoin5000
|
||||||
|
|
||||||
|
cval50000, _ := new(big.Int).SetString(Usecoin50000, 10)
|
||||||
|
UseCoinValueSet[cval50000.Text(16)] = Usecoin50000
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type useCoinSC struct{}
|
||||||
|
|
||||||
|
func (c *useCoinSC) RequiredGas(input []byte) uint64 {
|
||||||
|
if len(input) < 4 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodIdArr [4]byte
|
||||||
|
copy(methodIdArr[:], input[:4])
|
||||||
|
|
||||||
|
if methodIdArr == refundIdArr {
|
||||||
|
|
||||||
|
var RefundStruct struct {
|
||||||
|
RingSignedData string
|
||||||
|
Value *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
err := coinAbi.Unpack(&RefundStruct, "refundCoin", input[4:])
|
||||||
|
if err != nil {
|
||||||
|
return params.RequiredGasPerMixPub
|
||||||
|
}
|
||||||
|
|
||||||
|
err, publickeys, _, _, _ := DecodeRingSignOut(RefundStruct.RingSignedData)
|
||||||
|
if err != nil {
|
||||||
|
return params.RequiredGasPerMixPub
|
||||||
|
}
|
||||||
|
|
||||||
|
mixLen := len(publickeys)
|
||||||
|
ringSigDiffRequiredGas := params.RequiredGasPerMixPub * (uint64(mixLen))
|
||||||
|
|
||||||
|
// ringsign compute gas + ota image key store setting gas
|
||||||
|
return ringSigDiffRequiredGas + params.SstoreSetGas
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// ota balance store gas + ota useaddr store gas
|
||||||
|
return params.SstoreSetGas * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *useCoinSC) Run(in []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
|
if len(in) < 4 {
|
||||||
|
return nil, errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodIdArr [4]byte
|
||||||
|
copy(methodIdArr[:], in[:4])
|
||||||
|
|
||||||
|
if methodIdArr == buyIdArr {
|
||||||
|
return c.buyCoin(in[4:], contract, evm)
|
||||||
|
} else if methodIdArr == refundIdArr {
|
||||||
|
return c.refund(in[4:], contract, evm)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errMethodId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *useCoinSC) ValidBuyCoinReq(stateDB StateDB, payload []byte, txValue *big.Int) (otaAddr []byte, err error) {
|
||||||
|
if stateDB == nil || len(payload) == 0 || txValue == nil {
|
||||||
|
return nil, errors.New("unknown error")
|
||||||
|
}
|
||||||
|
|
||||||
|
var outStruct struct {
|
||||||
|
OtaAddr string
|
||||||
|
Value *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
err = coinAbi.Unpack(&outStruct, "buyCoinNote", payload)
|
||||||
|
if err != nil || outStruct.Value == nil {
|
||||||
|
return nil, errBuyCoin
|
||||||
|
}
|
||||||
|
|
||||||
|
if outStruct.Value.Cmp(txValue) != 0 {
|
||||||
|
return nil, ErrMismatchedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := UseCoinValueSet[outStruct.Value.Text(16)]
|
||||||
|
if !ok {
|
||||||
|
return nil, errCoinValue
|
||||||
|
}
|
||||||
|
|
||||||
|
useAddr, err := hexutil.Decode(outStruct.OtaAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ax, err := GetAXFromUseAddr(useAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
exist, _, err := CheckOTAAXExist(stateDB, ax)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exist {
|
||||||
|
return nil, ErrOTAReused
|
||||||
|
}
|
||||||
|
|
||||||
|
return useAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *useCoinSC) ValidRefundReq(stateDB StateDB, payload []byte, from []byte) (image []byte, value *big.Int, err error) {
|
||||||
|
if stateDB == nil || len(payload) == 0 || len(from) == 0 {
|
||||||
|
return nil, nil, errors.New("unknown error")
|
||||||
|
}
|
||||||
|
|
||||||
|
var RefundStruct struct {
|
||||||
|
RingSignedData string
|
||||||
|
Value *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
err = coinAbi.Unpack(&RefundStruct, "refundCoin", payload)
|
||||||
|
if err != nil || RefundStruct.Value == nil {
|
||||||
|
return nil, nil, errRefundCoin
|
||||||
|
}
|
||||||
|
|
||||||
|
ringSignInfo, err := FetchRingSignInfo(stateDB, from, RefundStruct.RingSignedData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ringSignInfo.OTABalance.Cmp(RefundStruct.Value) != 0 {
|
||||||
|
return nil, nil, ErrMismatchedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
kix := crypto.FromECDSAPub(ringSignInfo.KeyImage)
|
||||||
|
exist, _, err := CheckOTAImageExist(stateDB, kix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exist {
|
||||||
|
return nil, nil, ErrOTAReused
|
||||||
|
}
|
||||||
|
|
||||||
|
return kix, RefundStruct.Value, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *useCoinSC) refund(all []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
|
kix, value, err := c.ValidRefundReq(evm.StateDB, all, contract.CallerAddress.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed refund")
|
||||||
|
fmt.Println(evm.BlockNumber)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = AddOTAImage(evm.StateDB, kix, value.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addrSrc := contract.CallerAddress
|
||||||
|
|
||||||
|
evm.StateDB.AddBalance(addrSrc, value)
|
||||||
|
return []byte{1}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *useCoinSC) buyCoin(in []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
|
otaAddr, err := c.ValidBuyCoinReq(evm.StateDB, in, contract.value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
add, err := AddOTAIfNotExist(evm.StateDB, contract.value, otaAddr)
|
||||||
|
if err != nil || !add {
|
||||||
|
return nil, errBuyCoin
|
||||||
|
}
|
||||||
|
|
||||||
|
addrSrc := contract.CallerAddress
|
||||||
|
balance := evm.StateDB.GetBalance(addrSrc)
|
||||||
|
|
||||||
|
if balance.Cmp(contract.value) >= 0 {
|
||||||
|
// Need check contract value in build in value sets
|
||||||
|
evm.StateDB.SubBalance(addrSrc, contract.value)
|
||||||
|
return []byte{1}, nil
|
||||||
|
} else {
|
||||||
|
return nil, errBalance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeRingSignOut(s string) (error, []*ecdsa.PublicKey, *ecdsa.PublicKey, []*big.Int, []*big.Int) {
|
||||||
|
ss := strings.Split(s, "+")
|
||||||
|
if len(ss) < 4 {
|
||||||
|
return ErrInvalidRingSigned, nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ps := ss[0]
|
||||||
|
k := ss[1]
|
||||||
|
ws := ss[2]
|
||||||
|
qs := ss[3]
|
||||||
|
|
||||||
|
pa := strings.Split(ps, "&")
|
||||||
|
publickeys := make([]*ecdsa.PublicKey, 0)
|
||||||
|
for _, pi := range pa {
|
||||||
|
|
||||||
|
publickey := crypto.ToECDSAPub(common.FromHex(pi))
|
||||||
|
if publickey == nil || publickey.X == nil || publickey.Y == nil {
|
||||||
|
return ErrInvalidRingSigned, nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
publickeys = append(publickeys, publickey)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyimgae := crypto.ToECDSAPub(common.FromHex(k))
|
||||||
|
if keyimgae == nil || keyimgae.X == nil || keyimgae.Y == nil {
|
||||||
|
return ErrInvalidRingSigned, nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
wa := strings.Split(ws, "&")
|
||||||
|
w := make([]*big.Int, 0)
|
||||||
|
for _, wi := range wa {
|
||||||
|
bi, err := hexutil.DecodeBig(wi)
|
||||||
|
if bi == nil || err != nil {
|
||||||
|
return ErrInvalidRingSigned, nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
w = append(w, bi)
|
||||||
|
}
|
||||||
|
|
||||||
|
qa := strings.Split(qs, "&")
|
||||||
|
q := make([]*big.Int, 0)
|
||||||
|
for _, qi := range qa {
|
||||||
|
bi, err := hexutil.DecodeBig(qi)
|
||||||
|
if bi == nil || err != nil {
|
||||||
|
return ErrInvalidRingSigned, nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
q = append(q, bi)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(publickeys) != len(w) || len(publickeys) != len(q) {
|
||||||
|
return ErrInvalidRingSigned, nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, publickeys, keyimgae, w, q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *useCoinSC) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
if stateDB == nil || signer == nil || tx == nil {
|
||||||
|
return errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := tx.Data()
|
||||||
|
if len(payload) < 4 {
|
||||||
|
return errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodIdArr [4]byte
|
||||||
|
copy(methodIdArr[:], payload[:4])
|
||||||
|
|
||||||
|
if methodIdArr == buyIdArr {
|
||||||
|
_, err := c.ValidBuyCoinReq(stateDB, payload[4:], tx.Value())
|
||||||
|
return err
|
||||||
|
|
||||||
|
} else if methodIdArr == refundIdArr {
|
||||||
|
from, err := types.Sender(signer, tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = c.ValidRefundReq(stateDB, payload[4:], from.Bytes())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
type usechainStampSC struct{}
|
||||||
|
|
||||||
|
func (c *usechainStampSC) RequiredGas(input []byte) uint64 {
|
||||||
|
// ota balance store gas + ota useaddr store gas
|
||||||
|
return params.SstoreSetGas * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *usechainStampSC) Run(in []byte, contract *Contract, env *EVM) ([]byte, error) {
|
||||||
|
if len(in) < 4 {
|
||||||
|
return nil, errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodId [4]byte
|
||||||
|
copy(methodId[:], in[:4])
|
||||||
|
|
||||||
|
if methodId == stBuyId {
|
||||||
|
return c.buyStamp(in[4:], contract, env)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errMethodId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *usechainStampSC) ValidBuyStampReq(stateDB StateDB, payload []byte, value *big.Int) (otaAddr []byte, err error) {
|
||||||
|
if stateDB == nil || len(payload) == 0 || value == nil {
|
||||||
|
return nil, errors.New("unknown error")
|
||||||
|
}
|
||||||
|
|
||||||
|
var StampInput struct {
|
||||||
|
OtaAddr string
|
||||||
|
Value *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
err = stampAbi.UnpackTmp(&StampInput, "buyStamp", payload)
|
||||||
|
if err != nil || StampInput.Value == nil {
|
||||||
|
return nil, errBuyStamp
|
||||||
|
}
|
||||||
|
|
||||||
|
if StampInput.Value.Cmp(value) != 0 {
|
||||||
|
return nil, ErrMismatchedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := StampValueSet[StampInput.Value.Text(16)]
|
||||||
|
if !ok {
|
||||||
|
return nil, errStampValue
|
||||||
|
}
|
||||||
|
|
||||||
|
useAddr, err := hexutil.Decode(StampInput.OtaAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ax, err := GetAXFromUseAddr(useAddr)
|
||||||
|
exist, _, err := CheckOTAAXExist(stateDB, ax)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exist {
|
||||||
|
return nil, ErrOTAReused
|
||||||
|
}
|
||||||
|
|
||||||
|
return useAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *usechainStampSC) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||||
|
if stateDB == nil || signer == nil || tx == nil {
|
||||||
|
return errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := tx.Data()
|
||||||
|
if len(payload) < 4 {
|
||||||
|
return errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodId [4]byte
|
||||||
|
copy(methodId[:], payload[:4])
|
||||||
|
if methodId == stBuyId {
|
||||||
|
_, err := c.ValidBuyStampReq(stateDB, payload[4:], tx.Value())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *usechainStampSC) buyStamp(in []byte, contract *Contract, evm *EVM) ([]byte, error) {
|
||||||
|
useAddr, err := c.ValidBuyStampReq(evm.StateDB, in, contract.value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
add, err := AddOTAIfNotExist(evm.StateDB, contract.value, useAddr)
|
||||||
|
if err != nil || !add {
|
||||||
|
return nil, errBuyStamp
|
||||||
|
}
|
||||||
|
|
||||||
|
addrSrc := contract.CallerAddress
|
||||||
|
balance := evm.StateDB.GetBalance(addrSrc)
|
||||||
|
|
||||||
|
if balance.Cmp(contract.value) >= 0 {
|
||||||
|
// Need check contract value in build in value sets
|
||||||
|
evm.StateDB.SubBalance(addrSrc, contract.value)
|
||||||
|
return []byte{1}, nil
|
||||||
|
} else {
|
||||||
|
return nil, errBalance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RingSignInfo struct {
|
||||||
|
PublicKeys []*ecdsa.PublicKey
|
||||||
|
KeyImage *ecdsa.PublicKey
|
||||||
|
W_Random []*big.Int
|
||||||
|
Q_Random []*big.Int
|
||||||
|
OTABalance *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchRingSignInfo(stateDB StateDB, hashInput []byte, ringSignedStr string) (info *RingSignInfo, err error) {
|
||||||
|
if stateDB == nil || hashInput == nil {
|
||||||
|
return nil, errParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
infoTmp := new(RingSignInfo)
|
||||||
|
|
||||||
|
err, infoTmp.PublicKeys, infoTmp.KeyImage, infoTmp.W_Random, infoTmp.Q_Random = DecodeRingSignOut(ringSignedStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
otaLongs := make([][]byte, 0, len(infoTmp.PublicKeys))
|
||||||
|
for i := 0; i < len(infoTmp.PublicKeys); i++ {
|
||||||
|
otaLongs = append(otaLongs, keystore.ECDSAPKCompression(infoTmp.PublicKeys[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
exist, balanceGet, _, err := BatCheckOTAExist(stateDB, otaLongs)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
log.Error("verify mix ota fail", "err", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exist {
|
||||||
|
return nil, ErrInvalidOTASet
|
||||||
|
}
|
||||||
|
|
||||||
|
infoTmp.OTABalance = balanceGet
|
||||||
|
|
||||||
|
valid := crypto.VerifyRingSign(hashInput, infoTmp.PublicKeys, infoTmp.KeyImage, infoTmp.W_Random, infoTmp.Q_Random)
|
||||||
|
if !valid {
|
||||||
|
return nil, ErrInvalidRingSigned
|
||||||
|
}
|
||||||
|
|
||||||
|
return infoTmp, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -51,7 +52,7 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
|
||||||
precompiles = PrecompiledContractsIstanbul
|
precompiles = PrecompiledContractsIstanbul
|
||||||
}
|
}
|
||||||
if p := precompiles[*contract.CodeAddr]; p != nil {
|
if p := precompiles[*contract.CodeAddr]; p != nil {
|
||||||
return RunPrecompiledContract(p, input, contract)
|
return RunPrecompiledContract(p, input, contract, evm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, interpreter := range evm.interpreters {
|
for _, interpreter := range evm.interpreters {
|
||||||
|
|
@ -222,7 +223,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
}
|
}
|
||||||
evm.StateDB.CreateAccount(addr)
|
evm.StateDB.CreateAccount(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(to.Address().Bytes(), useCoinPrecompileAddr.Bytes()) && !bytes.Equal(to.Address().Bytes(), useStampPrecompileAddr.Bytes()) {
|
||||||
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||||
|
}
|
||||||
|
|
||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
contract := NewContract(caller, to, value, gas)
|
contract := NewContract(caller, to, value, gas)
|
||||||
|
|
|
||||||
107
crypto/crypto.go
107
crypto/crypto.go
|
|
@ -31,8 +31,18 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
|
||||||
|
//usha3 "github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
secp256k1_N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
|
||||||
|
secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2))
|
||||||
)
|
)
|
||||||
|
|
||||||
//SignatureLength indicates the byte length required to carry a signature with recovery id.
|
//SignatureLength indicates the byte length required to carry a signature with recovery id.
|
||||||
|
|
@ -235,6 +245,103 @@ func zeroBytes(bytes []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calc [x]Hash(P)
|
||||||
|
func xScalarHashP(x []byte, pub *ecdsa.PublicKey) (I *ecdsa.PublicKey) {
|
||||||
|
KeyImg := new(ecdsa.PublicKey)
|
||||||
|
I = new(ecdsa.PublicKey)
|
||||||
|
KeyImg.X, KeyImg.Y = S256().ScalarMult(pub.X, pub.Y, Keccak256(FromECDSAPub(pub))) //Hash(P)
|
||||||
|
I.X, I.Y = S256().ScalarMult(KeyImg.X, KeyImg.Y, x)
|
||||||
|
I.Curve = S256()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyRingSign verifies the validity of ring signature
|
||||||
|
// Pengbo added, Shi,TeemoGuo revised
|
||||||
|
func VerifyRingSign(M []byte, PublicKeys []*ecdsa.PublicKey, I *ecdsa.PublicKey, c []*big.Int, r []*big.Int) bool {
|
||||||
|
if M == nil || PublicKeys == nil || I == nil || c == nil || r == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(PublicKeys) == 0 || len(PublicKeys) != len(c) || len(PublicKeys) != len(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
n := len(PublicKeys)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
if PublicKeys[i] == nil || PublicKeys[i].X == nil || PublicKeys[i].Y == nil ||
|
||||||
|
c[i] == nil || r[i] == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("M info", "R", 0, "M", common.ToHex(M))
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
log.Debug("publicKeys", "i", i, "publickey", common.ToHex(FromECDSAPub(PublicKeys[i])))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("image info", "I", common.ToHex(FromECDSAPub(I)))
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
log.Debug("c info", "i", i, "c", common.ToHex(c[i].Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
log.Debug("r info", "i", i, "r", common.ToHex(r[i].Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
SumC := new(big.Int).SetInt64(0)
|
||||||
|
Lpub := new(ecdsa.PublicKey)
|
||||||
|
d := sha3.NewLegacyKeccak256()
|
||||||
|
d.Write(M)
|
||||||
|
|
||||||
|
//hash(M,Li,Ri)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
Lpub.X, Lpub.Y = S256().ScalarBaseMult(r[i].Bytes()) //[ri]G
|
||||||
|
if Lpub.X == nil || Lpub.Y == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Ppub := new(ecdsa.PublicKey)
|
||||||
|
Ppub.X, Ppub.Y = S256().ScalarMult(PublicKeys[i].X, PublicKeys[i].Y, c[i].Bytes()) //[ci]Pi
|
||||||
|
if Ppub.X == nil || Ppub.Y == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Lpub.X, Lpub.Y = S256().Add(Lpub.X, Lpub.Y, Ppub.X, Ppub.Y) //[ri]G+[ci]Pi
|
||||||
|
SumC.Add(SumC, c[i])
|
||||||
|
SumC.Mod(SumC, secp256k1_N)
|
||||||
|
d.Write(FromECDSAPub(Lpub))
|
||||||
|
log.Debug("LPublicKeys", "i", i, "Lpub", common.ToHex(FromECDSAPub(Lpub)))
|
||||||
|
}
|
||||||
|
|
||||||
|
Rpub := new(ecdsa.PublicKey)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
Rpub = xScalarHashP(r[i].Bytes(), PublicKeys[i]) //[qi]HashPi
|
||||||
|
if Rpub == nil || Rpub.X == nil || Rpub.Y == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Ppub := new(ecdsa.PublicKey)
|
||||||
|
Ppub.X, Ppub.Y = S256().ScalarMult(I.X, I.Y, c[i].Bytes()) //[wi]I
|
||||||
|
if Ppub.X == nil || Ppub.Y == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Rpub.X, Rpub.Y = S256().Add(Rpub.X, Rpub.Y, Ppub.X, Ppub.Y) //[qi]HashPi+[wi]I
|
||||||
|
log.Debug("RPublicKeys", "i", i, "Rpub", common.ToHex(FromECDSAPub(Rpub)))
|
||||||
|
|
||||||
|
d.Write(FromECDSAPub(Rpub))
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := new(big.Int).SetBytes(d.Sum(nil)) //hash(m,Li,Ri)
|
||||||
|
log.Debug("hash info", "i", 0, "hash", common.ToHex(hash.Bytes()))
|
||||||
|
|
||||||
|
hash.Mod(hash, secp256k1_N)
|
||||||
|
log.Debug("hash info", "i", 2, "hash", common.ToHex(hash.Bytes()))
|
||||||
|
log.Debug("SumC info", "i", 3, "SumC", common.ToHex(SumC.Bytes()))
|
||||||
|
|
||||||
|
return hash.Cmp(SumC) == 0
|
||||||
|
}
|
||||||
|
|
||||||
// A1=[hash([r]B)]G+A
|
// A1=[hash([r]B)]G+A
|
||||||
func generateA1(r []byte, A *ecdsa.PublicKey, B *ecdsa.PublicKey) ecdsa.PublicKey {
|
func generateA1(r []byte, A *ecdsa.PublicKey, B *ecdsa.PublicKey) ecdsa.PublicKey {
|
||||||
A1 := new(ecdsa.PublicKey)
|
A1 := new(ecdsa.PublicKey)
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,9 @@ const (
|
||||||
Bn256PairingBaseGasIstanbul uint64 = 45000 // Base price for an elliptic curve pairing check
|
Bn256PairingBaseGasIstanbul uint64 = 45000 // Base price for an elliptic curve pairing check
|
||||||
Bn256PairingPerPointGasByzantium uint64 = 80000 // Byzantium per-point price for an elliptic curve pairing check
|
Bn256PairingPerPointGasByzantium uint64 = 80000 // Byzantium per-point price for an elliptic curve pairing check
|
||||||
Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check
|
Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check
|
||||||
|
|
||||||
|
RequiredGasPerMixPub uint64 = 4000 // ring signature mix difficulty gas
|
||||||
|
GetOTAMixSetMaxSize uint64 = 20 // Max number of mix ota set size from once getting
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue