func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
	return Bn256ScalarMulGas
}
RequiredGas returns the gas required to execute the pre-compiled contract.
package vm
import (
	"crypto/sha256"
	"encoding/binary"
	"errors"
	"math/big"
	"golang.org/x/crypto/ripemd160"
	btcsecp256k1 "github.com/btcsuite/btcd/btcec"
	ethcrypto "github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/crypto/blake2b"
	"github.com/ethereum/go-ethereum/crypto/bn256"
	"github.com/Dipper-Labs/Dipper-Protocol/app/v0/vm/common"
	"github.com/Dipper-Labs/Dipper-Protocol/app/v0/vm/common/math"
	sdk "github.com/Dipper-Labs/Dipper-Protocol/types"
)
type PrecompiledContract interface {
	RequiredGas(input []byte) uint64   
	Run(input []byte) ([]byte, error)  
}
var PrecompiledContracts = map[string]PrecompiledContract{
	(sdk.BytesToAddress([]byte{1})).String(): &ecrecover{},
	(sdk.BytesToAddress([]byte{2})).String(): &sha256hash{},
	(sdk.BytesToAddress([]byte{3})).String(): &ripemd160hash{},
	(sdk.BytesToAddress([]byte{4})).String(): &dataCopy{},
	(sdk.BytesToAddress([]byte{5})).String(): &bigModExp{},
	(sdk.BytesToAddress([]byte{6})).String(): &bn256Add{},
	(sdk.BytesToAddress([]byte{7})).String(): &bn256ScalarMul{},
	(sdk.BytesToAddress([]byte{8})).String(): &bn256Pairing{},
	(sdk.BytesToAddress([]byte{9})).String(): &blake2F{},
}
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
	gas := p.RequiredGas(input)
	if contract.UseGas(gas) {
		return p.Run(input)
	}
	return nil, ErrOutOfGas
}
type ecrecover struct{}
func (c *ecrecover) RequiredGas(input []byte) uint64 {
	return EcrecoverGas
}
func (c *ecrecover) Run(input []byte) ([]byte, error) {
	const ecRecoverInputLength = 128
	input = common.RightPadBytes(input, ecRecoverInputLength)
	r := new(big.Int).SetBytes(input[64:96])
	s := new(big.Int).SetBytes(input[96:128])
	v := input[63] - 27
	if !allZero(input[32:63]) || !ethcrypto.ValidateSignatureValues(v, r, s, false) {
		return nil, nil
	}
	sig := make([]byte, 65)
	copy(sig, input[64:128])
	sig[64] = v
	pubkeyBin, err := ethcrypto.Ecrecover(input[:32], sig)
	if err != nil {
		return nil, nil
	}
	pubkey, _ := btcsecp256k1.ParsePubKey(pubkeyBin, btcsecp256k1.S256())
	hasherSHA256 := sha256.New()
	hasherSHA256.Write(pubkey.SerializeCompressed())
	sha := hasherSHA256.Sum(nil)
	hasherRIPEMD160 := ripemd160.New()
	hasherRIPEMD160.Write(sha)
	return common.LeftPadBytes(hasherRIPEMD160.Sum(nil), 32), nil
}
type sha256hash struct{}
func (c *sha256hash) RequiredGas(input []byte) uint64 {
	return uint64(len(input)+31)/32*Sha256PerWordGas + Sha256BaseGas
}
func (c *sha256hash) Run(input []byte) ([]byte, error) {
	h := sha256.Sum256(input)
	return h[:], nil
}
type ripemd160hash struct{}
func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
	return uint64(len(input)+31)/32*Ripemd160PerWordGas + Ripemd160BaseGas
}
func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
	ripemd := ripemd160.New()
	ripemd.Write(input)
	return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
}
type dataCopy struct{}
func (c *dataCopy) RequiredGas(input []byte) uint64 {
	return uint64(len(input)+31)/32*IdentityPerWordGas + IdentityBaseGas
}
func (c *dataCopy) Run(in []byte) ([]byte, error) {
	return in, nil
}
type bigModExp struct{}
func (c *bigModExp) RequiredGas(input []byte) uint64 {
	var (
		baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
		expLen  = new(big.Int).SetBytes(getData(input, 32, 32))
		modLen  = new(big.Int).SetBytes(getData(input, 64, 32))
	)
	if len(input) > 96 {
		input = input[96:]
	} else {
		input = input[:0]
	}
	var expHead *big.Int
	if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
		expHead = new(big.Int)
	} else {
		if expLen.Cmp(common.Big32) > 0 {
			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
		} else {
			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
		}
	}
	var msb int
	if bitlen := expHead.BitLen(); bitlen > 0 {
		msb = bitlen - 1
	}
	adjExpLen := new(big.Int)
	if expLen.Cmp(common.Big32) > 0 {
		adjExpLen.Sub(expLen, common.Big32)
		adjExpLen.Mul(common.Big8, adjExpLen)
	}
	adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
	gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
	switch {
	case gas.Cmp(common.Big64) <= 0:
		gas.Mul(gas, gas)
	case gas.Cmp(common.Big1024) <= 0:
		gas = new(big.Int).Add(
			new(big.Int).Div(new(big.Int).Mul(gas, gas), common.Big4),
			new(big.Int).Sub(new(big.Int).Mul(common.Big96, gas), common.Big3072),
		)
	default:
		gas = new(big.Int).Add(
			new(big.Int).Div(new(big.Int).Mul(gas, gas), common.Big16),
			new(big.Int).Sub(new(big.Int).Mul(common.Big480, gas), common.Big199680),
		)
	}
	gas.Mul(gas, math.BigMax(adjExpLen, common.Big1))
	gas.Div(gas, new(big.Int).SetUint64(ModExpQuadCoeffDiv))
	if gas.BitLen() > 64 {
		return math.MaxUint64
	}
	return gas.Uint64()
}
func (c *bigModExp) Run(input []byte) ([]byte, error) {
	var (
		baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
		expLen  = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
		modLen  = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64()
	)
	if len(input) > 96 {
		input = input[96:]
	} else {
		input = input[:0]
	}
	if baseLen == 0 && modLen == 0 {
		return []byte{}, nil
	}
	var (
		base = new(big.Int).SetBytes(getData(input, 0, baseLen))
		exp  = new(big.Int).SetBytes(getData(input, baseLen, expLen))
		mod  = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
	)
	if mod.BitLen() == 0 {
		return common.LeftPadBytes([]byte{}, int(modLen)), nil
	}
	return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil
}
type blake2F struct{}
const (
	blake2FInputLength        = 213
	blake2FFinalBlockBytes    = byte(1)
	blake2FNonFinalBlockBytes = byte(0)
)
var (
	errBlake2FInvalidInputLength = errors.New("invalid input length")
	errBlake2FInvalidFinalFlag   = errors.New("invalid final flag")
)
func (c *blake2F) RequiredGas(input []byte) uint64 {
	if len(input) != blake2FInputLength {
		return 0
	}
	return uint64(binary.BigEndian.Uint32(input[0:4]))
}
func (c *blake2F) Run(input []byte) ([]byte, error) {
	if len(input) != blake2FInputLength {
		return nil, errBlake2FInvalidInputLength
	}
	if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes {
		return nil, errBlake2FInvalidFinalFlag
	}
	var (
		rounds = binary.BigEndian.Uint32(input[0:4])
		final  = (input[212] == blake2FFinalBlockBytes)
		h [8]uint64
		m [16]uint64
		t [2]uint64
	)
	for i := 0; i < 8; i++ {
		offset := 4 + i*8
		h[i] = binary.LittleEndian.Uint64(input[offset : offset+8])
	}
	for i := 0; i < 16; i++ {
		offset := 68 + i*8
		m[i] = binary.LittleEndian.Uint64(input[offset : offset+8])
	}
	t[0] = binary.LittleEndian.Uint64(input[196:204])
	t[1] = binary.LittleEndian.Uint64(input[204:212])
	blake2b.F(&h, m, t, final, rounds)
	output := make([]byte, 64)
	for i := 0; i < 8; i++ {
		offset := i * 8
		binary.LittleEndian.PutUint64(output[offset:offset+8], h[i])
	}
	return output, nil
}
type bn256Pairing struct{}
var (
	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}
	false32Byte = make([]byte, 32)
	errBadPairingInput = errors.New("bad elliptic curve pairing size")
)
func newCurvePoint(blob []byte) (*bn256.G1, error) {
	p := new(bn256.G1)
	if _, err := p.Unmarshal(blob); err != nil {
		return nil, err
	}
	return p, nil
}
func newTwistPoint(blob []byte) (*bn256.G2, error) {
	p := new(bn256.G2)
	if _, err := p.Unmarshal(blob); err != nil {
		return nil, err
	}
	return p, nil
}
func (c *bn256Pairing) RequiredGas(input []byte) uint64 {
	return Bn256PairingBaseGas + uint64(len(input)/192)*Bn256PairingPerPointGas
}
func (c *bn256Pairing) Run(input []byte) ([]byte, error) {
	if len(input)%192 > 0 {
		return nil, errBadPairingInput
	}
	var (
		cs []*bn256.G1
		ts []*bn256.G2
	)
	for i := 0; i < len(input); i += 192 {
		c, err := newCurvePoint(input[i : i+64])
		if err != nil {
			return nil, err
		}
		t, err := newTwistPoint(input[i+64 : i+192])
		if err != nil {
			return nil, err
		}
		cs = append(cs, c)
		ts = append(ts, t)
	}
	if bn256.PairingCheck(cs, ts) {
		return true32Byte, nil
	}
	return false32Byte, nil
}
func runBn256Add(input []byte) ([]byte, error) {
	x, err := newCurvePoint(getData(input, 0, 64))
	if err != nil {
		return nil, err
	}
	y, err := newCurvePoint(getData(input, 64, 64))
	if err != nil {
		return nil, err
	}
	res := new(bn256.G1)
	res.Add(x, y)
	return res.Marshal(), nil
}
type bn256Add struct{}
func (c *bn256Add) RequiredGas(input []byte) uint64 {
	return Bn256AddGas
}
func (c *bn256Add) Run(input []byte) ([]byte, error) {
	return runBn256Add(input)
}
type bn256ScalarMul struct{}
func runBn256ScalarMul(input []byte) ([]byte, error) {
	p, err := newCurvePoint(getData(input, 0, 64))
	if err != nil {
		return nil, err
	}
	res := new(bn256.G1)
	res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32)))
	return res.Marshal(), nil
}