github.com/theQRL/go-zond@v0.2.1/core/vm/contracts.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/sha256"
    22  	"encoding/binary"
    23  	"errors"
    24  	"math/big"
    25  
    26  	pkgerrors "github.com/pkg/errors"
    27  	ssz "github.com/prysmaticlabs/fastssz"
    28  	"github.com/theQRL/go-zond/common"
    29  	"github.com/theQRL/go-zond/common/math"
    30  	"github.com/theQRL/go-zond/crypto/bn256"
    31  	"github.com/theQRL/go-zond/params"
    32  )
    33  
    34  // PrecompiledContract is the basic interface for native Go contracts. The implementation
    35  // requires a deterministic gas count based on the input size of the Run method of the
    36  // contract.
    37  type PrecompiledContract interface {
    38  	RequiredGas(input []byte) uint64  // RequiredPrice calculates the contract gas use
    39  	Run(input []byte) ([]byte, error) // Run runs the precompiled contract
    40  }
    41  
    42  // PrecompiledContractsBerlin contains the default set of pre-compiled Zond
    43  // contracts used in the Berlin release.
    44  var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
    45  	common.BytesToAddress([]byte{1}): &depositroot{},
    46  	common.BytesToAddress([]byte{2}): &sha256hash{},
    47  	common.BytesToAddress([]byte{4}): &dataCopy{},
    48  	common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
    49  	common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
    50  	common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
    51  	common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
    52  }
    53  
    54  var (
    55  	PrecompiledAddressesBerlin []common.Address
    56  )
    57  
    58  func init() {
    59  	for k := range PrecompiledContractsBerlin {
    60  		PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
    61  	}
    62  }
    63  
    64  // ActivePrecompiles returns the precompiles enabled with the current configuration.
    65  func ActivePrecompiles(rules params.Rules) []common.Address {
    66  	return PrecompiledAddressesBerlin
    67  }
    68  
    69  // RunPrecompiledContract runs and evaluates the output of a precompiled contract.
    70  // It returns
    71  // - the returned bytes,
    72  // - the _remaining_ gas,
    73  // - any error that occurred
    74  func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
    75  	gasCost := p.RequiredGas(input)
    76  	if suppliedGas < gasCost {
    77  		return nil, 0, ErrOutOfGas
    78  	}
    79  	suppliedGas -= gasCost
    80  	output, err := p.Run(input)
    81  	return output, suppliedGas, err
    82  }
    83  
    84  type depositroot struct{}
    85  
    86  // TODO(now.youtrack.cloud/issue/TGZ-5)
    87  func (c *depositroot) RequiredGas(input []byte) uint64 {
    88  	// NOTE(rgeraldes): number of sha256 ops below does not include the number of zero
    89  	// hashes done; these are calculated during the prysmaticlabs/fastssz lib init
    90  	// 238 sha256 ops + 64 bytes input per op
    91  	// return uint64(64+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
    92  	return (2*params.Sha256PerWordGas + params.Sha256BaseGas) * 238
    93  }
    94  
    95  func (c *depositroot) Run(input []byte) ([]byte, error) {
    96  	var (
    97  		pkBytes     = getData(input, 0, 2592)    // 2592 bytes
    98  		credsBytes  = getData(input, 2592, 32)   // 32 bytes
    99  		amountBytes = getData(input, 2624, 8)    // 8 bytes
   100  		sigBytes    = getData(input, 2632, 4595) // 4595 bytes
   101  	)
   102  
   103  	var amountUint uint64
   104  	buf := bytes.NewReader(amountBytes)
   105  	err := binary.Read(buf, binary.LittleEndian, &amountUint)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	data := &depositdata{
   111  		PublicKey:             pkBytes,
   112  		WithdrawalCredentials: credsBytes,
   113  		Amount:                amountUint,
   114  		Signature:             sigBytes,
   115  	}
   116  	h, err := data.HashTreeRoot()
   117  	if err != nil {
   118  		return nil, pkgerrors.Wrap(err, "could not hash tree root deposit data item")
   119  	}
   120  
   121  	return h[:], nil
   122  }
   123  
   124  type depositdata struct {
   125  	PublicKey             []byte
   126  	WithdrawalCredentials []byte
   127  	Amount                uint64
   128  	Signature             []byte
   129  }
   130  
   131  // HashTreeRoot ssz hashes the Deposit_Data object
   132  func (d *depositdata) HashTreeRoot() ([32]byte, error) {
   133  	return ssz.HashWithDefaultHasher(d)
   134  }
   135  
   136  // HashTreeRootWith ssz hashes the Deposit_Data object with a hasher
   137  func (d *depositdata) HashTreeRootWith(hh *ssz.Hasher) (err error) {
   138  	indx := hh.Index()
   139  
   140  	// Field (0) 'Pubkey'
   141  	if size := len(d.PublicKey); size != 2592 {
   142  		err = ssz.ErrBytesLengthFn("--.Pubkey", size, 2592)
   143  		return
   144  	}
   145  	hh.PutBytes(d.PublicKey)
   146  
   147  	// Field (1) 'WithdrawalCredentials'
   148  	if size := len(d.WithdrawalCredentials); size != 32 {
   149  		err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32)
   150  		return
   151  	}
   152  	hh.PutBytes(d.WithdrawalCredentials)
   153  
   154  	// Field (2) 'Amount'
   155  	hh.PutUint64(d.Amount)
   156  
   157  	// Field (3) 'Signature'
   158  	if size := len(d.Signature); size != 4595 {
   159  		err = ssz.ErrBytesLengthFn("--.Signature", size, 4595)
   160  		return
   161  	}
   162  	hh.PutBytes(d.Signature)
   163  
   164  	if ssz.EnableVectorizedHTR {
   165  		hh.MerkleizeVectorizedHTR(indx)
   166  	} else {
   167  		hh.Merkleize(indx)
   168  	}
   169  	return
   170  }
   171  
   172  // SHA256 implemented as a native contract.
   173  type sha256hash struct{}
   174  
   175  // RequiredGas returns the gas required to execute the pre-compiled contract.
   176  //
   177  // This method does not require any overflow checking as the input size gas costs
   178  // required for anything significant is so high it's impossible to pay for.
   179  func (c *sha256hash) RequiredGas(input []byte) uint64 {
   180  	return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
   181  }
   182  func (c *sha256hash) Run(input []byte) ([]byte, error) {
   183  	h := sha256.Sum256(input)
   184  	return h[:], nil
   185  }
   186  
   187  // data copy implemented as a native contract.
   188  type dataCopy struct{}
   189  
   190  // RequiredGas returns the gas required to execute the pre-compiled contract.
   191  //
   192  // This method does not require any overflow checking as the input size gas costs
   193  // required for anything significant is so high it's impossible to pay for.
   194  func (c *dataCopy) RequiredGas(input []byte) uint64 {
   195  	return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
   196  }
   197  func (c *dataCopy) Run(in []byte) ([]byte, error) {
   198  	return common.CopyBytes(in), nil
   199  }
   200  
   201  // bigModExp implements a native big integer exponential modular operation.
   202  type bigModExp struct {
   203  	eip2565 bool
   204  }
   205  
   206  var (
   207  	big0      = big.NewInt(0)
   208  	big1      = big.NewInt(1)
   209  	big3      = big.NewInt(3)
   210  	big4      = big.NewInt(4)
   211  	big7      = big.NewInt(7)
   212  	big8      = big.NewInt(8)
   213  	big16     = big.NewInt(16)
   214  	big20     = big.NewInt(20)
   215  	big32     = big.NewInt(32)
   216  	big64     = big.NewInt(64)
   217  	big96     = big.NewInt(96)
   218  	big480    = big.NewInt(480)
   219  	big1024   = big.NewInt(1024)
   220  	big3072   = big.NewInt(3072)
   221  	big199680 = big.NewInt(199680)
   222  )
   223  
   224  // modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198
   225  //
   226  //	def mult_complexity(x):
   227  //		if x <= 64: return x ** 2
   228  //		elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072
   229  //		else: return x ** 2 // 16 + 480 * x - 199680
   230  //
   231  // where is x is max(length_of_MODULUS, length_of_BASE)
   232  func modexpMultComplexity(x *big.Int) *big.Int {
   233  	switch {
   234  	case x.Cmp(big64) <= 0:
   235  		x.Mul(x, x) // x ** 2
   236  	case x.Cmp(big1024) <= 0:
   237  		// (x ** 2 // 4 ) + ( 96 * x - 3072)
   238  		x = new(big.Int).Add(
   239  			new(big.Int).Div(new(big.Int).Mul(x, x), big4),
   240  			new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072),
   241  		)
   242  	default:
   243  		// (x ** 2 // 16) + (480 * x - 199680)
   244  		x = new(big.Int).Add(
   245  			new(big.Int).Div(new(big.Int).Mul(x, x), big16),
   246  			new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680),
   247  		)
   248  	}
   249  	return x
   250  }
   251  
   252  // RequiredGas returns the gas required to execute the pre-compiled contract.
   253  func (c *bigModExp) RequiredGas(input []byte) uint64 {
   254  	var (
   255  		baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
   256  		expLen  = new(big.Int).SetBytes(getData(input, 32, 32))
   257  		modLen  = new(big.Int).SetBytes(getData(input, 64, 32))
   258  	)
   259  	if len(input) > 96 {
   260  		input = input[96:]
   261  	} else {
   262  		input = input[:0]
   263  	}
   264  	// Retrieve the head 32 bytes of exp for the adjusted exponent length
   265  	var expHead *big.Int
   266  	if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
   267  		expHead = new(big.Int)
   268  	} else {
   269  		if expLen.Cmp(big32) > 0 {
   270  			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
   271  		} else {
   272  			expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
   273  		}
   274  	}
   275  	// Calculate the adjusted exponent length
   276  	var msb int
   277  	if bitlen := expHead.BitLen(); bitlen > 0 {
   278  		msb = bitlen - 1
   279  	}
   280  	adjExpLen := new(big.Int)
   281  	if expLen.Cmp(big32) > 0 {
   282  		adjExpLen.Sub(expLen, big32)
   283  		adjExpLen.Mul(big8, adjExpLen)
   284  	}
   285  	adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
   286  	// Calculate the gas cost of the operation
   287  	gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
   288  	if c.eip2565 {
   289  		// EIP-2565 has three changes
   290  		// 1. Different multComplexity (inlined here)
   291  		// in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
   292  		//
   293  		// def mult_complexity(x):
   294  		//    ceiling(x/8)^2
   295  		//
   296  		//where is x is max(length_of_MODULUS, length_of_BASE)
   297  		gas = gas.Add(gas, big7)
   298  		gas = gas.Div(gas, big8)
   299  		gas.Mul(gas, gas)
   300  
   301  		gas.Mul(gas, math.BigMax(adjExpLen, big1))
   302  		// 2. Different divisor (`GQUADDIVISOR`) (3)
   303  		gas.Div(gas, big3)
   304  		if gas.BitLen() > 64 {
   305  			return math.MaxUint64
   306  		}
   307  		// 3. Minimum price of 200 gas
   308  		if gas.Uint64() < 200 {
   309  			return 200
   310  		}
   311  		return gas.Uint64()
   312  	}
   313  	gas = modexpMultComplexity(gas)
   314  	gas.Mul(gas, math.BigMax(adjExpLen, big1))
   315  	gas.Div(gas, big20)
   316  
   317  	if gas.BitLen() > 64 {
   318  		return math.MaxUint64
   319  	}
   320  	return gas.Uint64()
   321  }
   322  
   323  func (c *bigModExp) Run(input []byte) ([]byte, error) {
   324  	var (
   325  		baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
   326  		expLen  = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
   327  		modLen  = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64()
   328  	)
   329  	if len(input) > 96 {
   330  		input = input[96:]
   331  	} else {
   332  		input = input[:0]
   333  	}
   334  	// Handle a special case when both the base and mod length is zero
   335  	if baseLen == 0 && modLen == 0 {
   336  		return []byte{}, nil
   337  	}
   338  	// Retrieve the operands and execute the exponentiation
   339  	var (
   340  		base = new(big.Int).SetBytes(getData(input, 0, baseLen))
   341  		exp  = new(big.Int).SetBytes(getData(input, baseLen, expLen))
   342  		mod  = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
   343  		v    []byte
   344  	)
   345  	switch {
   346  	case mod.BitLen() == 0:
   347  		// Modulo 0 is undefined, return zero
   348  		return common.LeftPadBytes([]byte{}, int(modLen)), nil
   349  	case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1).
   350  		//If base == 1, then we can just return base % mod (if mod >= 1, which it is)
   351  		v = base.Mod(base, mod).Bytes()
   352  	default:
   353  		v = base.Exp(base, exp, mod).Bytes()
   354  	}
   355  	return common.LeftPadBytes(v, int(modLen)), nil
   356  }
   357  
   358  // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,
   359  // returning it, or an error if the point is invalid.
   360  func newCurvePoint(blob []byte) (*bn256.G1, error) {
   361  	p := new(bn256.G1)
   362  	if _, err := p.Unmarshal(blob); err != nil {
   363  		return nil, err
   364  	}
   365  	return p, nil
   366  }
   367  
   368  // newTwistPoint unmarshals a binary blob into a bn256 elliptic curve point,
   369  // returning it, or an error if the point is invalid.
   370  func newTwistPoint(blob []byte) (*bn256.G2, error) {
   371  	p := new(bn256.G2)
   372  	if _, err := p.Unmarshal(blob); err != nil {
   373  		return nil, err
   374  	}
   375  	return p, nil
   376  }
   377  
   378  // runBn256Add implements the Bn256Add precompile, referenced by both
   379  // Byzantium and Istanbul operations.
   380  func runBn256Add(input []byte) ([]byte, error) {
   381  	x, err := newCurvePoint(getData(input, 0, 64))
   382  	if err != nil {
   383  		return nil, err
   384  	}
   385  	y, err := newCurvePoint(getData(input, 64, 64))
   386  	if err != nil {
   387  		return nil, err
   388  	}
   389  	res := new(bn256.G1)
   390  	res.Add(x, y)
   391  	return res.Marshal(), nil
   392  }
   393  
   394  // bn256Add implements a native elliptic curve point addition conforming to
   395  // Istanbul consensus rules.
   396  type bn256AddIstanbul struct{}
   397  
   398  // RequiredGas returns the gas required to execute the pre-compiled contract.
   399  func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
   400  	return params.Bn256AddGasIstanbul
   401  }
   402  
   403  func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
   404  	return runBn256Add(input)
   405  }
   406  
   407  // runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by
   408  // both Byzantium and Istanbul operations.
   409  func runBn256ScalarMul(input []byte) ([]byte, error) {
   410  	p, err := newCurvePoint(getData(input, 0, 64))
   411  	if err != nil {
   412  		return nil, err
   413  	}
   414  	res := new(bn256.G1)
   415  	res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32)))
   416  	return res.Marshal(), nil
   417  }
   418  
   419  // bn256ScalarMulIstanbul implements a native elliptic curve scalar
   420  // multiplication conforming to Istanbul consensus rules.
   421  type bn256ScalarMulIstanbul struct{}
   422  
   423  // RequiredGas returns the gas required to execute the pre-compiled contract.
   424  func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
   425  	return params.Bn256ScalarMulGasIstanbul
   426  }
   427  
   428  func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
   429  	return runBn256ScalarMul(input)
   430  }
   431  
   432  var (
   433  	// true32Byte is returned if the bn256 pairing check succeeds.
   434  	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}
   435  
   436  	// false32Byte is returned if the bn256 pairing check fails.
   437  	false32Byte = make([]byte, 32)
   438  
   439  	// errBadPairingInput is returned if the bn256 pairing input is invalid.
   440  	errBadPairingInput = errors.New("bad elliptic curve pairing size")
   441  )
   442  
   443  // runBn256Pairing implements the Bn256Pairing precompile, referenced by both
   444  // Byzantium and Istanbul operations.
   445  func runBn256Pairing(input []byte) ([]byte, error) {
   446  	// Handle some corner cases cheaply
   447  	if len(input)%192 > 0 {
   448  		return nil, errBadPairingInput
   449  	}
   450  	// Convert the input into a set of coordinates
   451  	var (
   452  		cs []*bn256.G1
   453  		ts []*bn256.G2
   454  	)
   455  	for i := 0; i < len(input); i += 192 {
   456  		c, err := newCurvePoint(input[i : i+64])
   457  		if err != nil {
   458  			return nil, err
   459  		}
   460  		t, err := newTwistPoint(input[i+64 : i+192])
   461  		if err != nil {
   462  			return nil, err
   463  		}
   464  		cs = append(cs, c)
   465  		ts = append(ts, t)
   466  	}
   467  	// Execute the pairing checks and return the results
   468  	if bn256.PairingCheck(cs, ts) {
   469  		return true32Byte, nil
   470  	}
   471  	return false32Byte, nil
   472  }
   473  
   474  // bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
   475  // conforming to Istanbul consensus rules.
   476  type bn256PairingIstanbul struct{}
   477  
   478  // RequiredGas returns the gas required to execute the pre-compiled contract.
   479  func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
   480  	return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
   481  }
   482  
   483  func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
   484  	return runBn256Pairing(input)
   485  }