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")
|
||||
}
|
||||
|
||||
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{}
|
||||
func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
|
||||
if len(data) == 0 {
|
||||
|
|
|
|||
|
|
@ -17,26 +17,69 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"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/hexutil"
|
||||
"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/blake2b"
|
||||
"github.com/ethereum/go-ethereum/crypto/bn256"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"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
|
||||
// requires a deterministic gas count based on the input size of the Run method of the
|
||||
// contract.
|
||||
type PrecompiledContract interface {
|
||||
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
|
||||
Run(input []byte) ([]byte, error) // Run runs the precompiled contract
|
||||
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
|
||||
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
|
||||
|
|
@ -46,6 +89,9 @@ var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
|
|||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||
|
||||
useCoinPrecompileAddr: &useCoinSC{},
|
||||
useStampPrecompileAddr: &usechainStampSC{},
|
||||
}
|
||||
|
||||
// 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{7}): &bn256ScalarMulByzantium{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
||||
|
||||
useCoinPrecompileAddr: &useCoinSC{},
|
||||
useStampPrecompileAddr: &usechainStampSC{},
|
||||
}
|
||||
|
||||
// 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{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
||||
|
||||
useCoinPrecompileAddr: &useCoinSC{},
|
||||
useStampPrecompileAddr: &usechainStampSC{},
|
||||
}
|
||||
|
||||
// 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)
|
||||
if contract.UseGas(gas) {
|
||||
return p.Run(input)
|
||||
return p.Run(input, contract, evm)
|
||||
}
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -91,7 +143,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 {
|
|||
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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (c *ecrecover) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SHA256 implemented as a native contract.
|
||||
type sha256hash struct{}
|
||||
|
||||
|
|
@ -127,11 +183,15 @@ type sha256hash struct{}
|
|||
func (c *sha256hash) RequiredGas(input []byte) uint64 {
|
||||
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)
|
||||
return h[:], nil
|
||||
}
|
||||
|
||||
func (c *sha256hash) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RIPEMD160 implemented as a native contract.
|
||||
type ripemd160hash struct{}
|
||||
|
||||
|
|
@ -142,12 +202,16 @@ type ripemd160hash struct{}
|
|||
func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
|
||||
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.Write(input)
|
||||
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.
|
||||
type dataCopy struct{}
|
||||
|
||||
|
|
@ -158,10 +222,14 @@ type dataCopy struct{}
|
|||
func (c *dataCopy) RequiredGas(input []byte) uint64 {
|
||||
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
|
||||
}
|
||||
|
||||
func (c *dataCopy) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bigModExp implements a native big integer exponential modular operation.
|
||||
type bigModExp struct{}
|
||||
|
||||
|
|
@ -239,7 +307,7 @@ func (c *bigModExp) RequiredGas(input []byte) 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 (
|
||||
baseLen = new(big.Int).SetBytes(getData(input, 0, 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
|
||||
}
|
||||
|
||||
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,
|
||||
// returning it, or an error if the point is invalid.
|
||||
func newCurvePoint(blob []byte) (*bn256.G1, error) {
|
||||
|
|
@ -312,10 +384,14 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
|
|||
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)
|
||||
}
|
||||
|
||||
func (c *bn256AddIstanbul) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bn256AddByzantium implements a native elliptic curve point addition
|
||||
// conforming to Byzantium consensus rules.
|
||||
type bn256AddByzantium struct{}
|
||||
|
|
@ -325,10 +401,14 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
|
|||
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)
|
||||
}
|
||||
|
||||
func (c *bn256AddByzantium) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
|
||||
// both Byzantium and Istanbul operations.
|
||||
func runBn256ScalarMul(input []byte) ([]byte, error) {
|
||||
|
|
@ -350,10 +430,14 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
|
|||
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)
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMulIstanbul) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bn256ScalarMulByzantium implements a native elliptic curve scalar
|
||||
// multiplication conforming to Byzantium consensus rules.
|
||||
type bn256ScalarMulByzantium struct{}
|
||||
|
|
@ -363,10 +447,14 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
|
|||
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)
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMulByzantium) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
// 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}
|
||||
|
|
@ -418,10 +506,14 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
|
|||
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)
|
||||
}
|
||||
|
||||
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
|
||||
// conforming to Byzantium consensus rules.
|
||||
type bn256PairingByzantium struct{}
|
||||
|
|
@ -431,10 +523,14 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
|
|||
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)
|
||||
}
|
||||
|
||||
func (c *bn256PairingByzantium) ValidTx(stateDB StateDB, signer types.Signer, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type blake2F struct{}
|
||||
|
||||
func (c *blake2F) RequiredGas(input []byte) uint64 {
|
||||
|
|
@ -457,7 +553,7 @@ var (
|
|||
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)
|
||||
if len(input) != blake2FInputLength {
|
||||
return nil, errBlake2FInvalidInputLength
|
||||
|
|
@ -495,3 +591,584 @@ func (c *blake2F) Run(input []byte) ([]byte, error) {
|
|||
}
|
||||
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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
|
@ -51,7 +52,7 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
|
|||
precompiles = PrecompiledContractsIstanbul
|
||||
}
|
||||
if p := precompiles[*contract.CodeAddr]; p != nil {
|
||||
return RunPrecompiledContract(p, input, contract)
|
||||
return RunPrecompiledContract(p, input, contract, evm)
|
||||
}
|
||||
}
|
||||
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.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||
|
||||
if !bytes.Equal(to.Address().Bytes(), useCoinPrecompileAddr.Bytes()) && !bytes.Equal(to.Address().Bytes(), useStampPrecompileAddr.Bytes()) {
|
||||
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.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
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/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
|
||||
//usha3 "github.com/ethereum/go-ethereum/crypto/sha3"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
||||
"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.
|
||||
|
|
@ -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
|
||||
func generateA1(r []byte, A *ecdsa.PublicKey, B *ecdsa.PublicKey) ecdsa.PublicKey {
|
||||
A1 := new(ecdsa.PublicKey)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,9 @@ const (
|
|||
Bn256PairingBaseGasIstanbul uint64 = 45000 // Base 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
|
||||
|
||||
RequiredGasPerMixPub uint64 = 4000 // ring signature mix difficulty gas
|
||||
GetOTAMixSetMaxSize uint64 = 20 // Max number of mix ota set size from once getting
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
Loading…
Reference in a new issue