github.com/amazechain/amc@v0.1.3/internal/avm/types/exchange.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/amazechain/amc/common/block"
     7  	"github.com/amazechain/amc/common/crypto"
     8  	"github.com/amazechain/amc/common/transaction"
     9  	"github.com/amazechain/amc/common/types"
    10  	"github.com/amazechain/amc/internal/avm/common"
    11  	"github.com/amazechain/amc/internal/avm/rlp"
    12  	"github.com/amazechain/amc/log"
    13  	"github.com/amazechain/amc/params"
    14  	"github.com/holiman/uint256"
    15  	"golang.org/x/crypto/sha3"
    16  	"math/big"
    17  	"sync"
    18  	"sync/atomic"
    19  	"time"
    20  )
    21  
    22  // hasherPool holds LegacyKeccak256 hashers for rlpHash.
    23  var hasherPool = sync.Pool{
    24  	New: func() interface{} { return sha3.NewLegacyKeccak256() },
    25  }
    26  
    27  type writeCounter common.StorageSize
    28  
    29  func (c *writeCounter) Write(b []byte) (int, error) {
    30  	*c += writeCounter(len(b))
    31  	return len(b), nil
    32  }
    33  
    34  func ToAmcAddress(addr *common.Address) *types.Address {
    35  	if addr == nil {
    36  		return nil
    37  	}
    38  	nullAddress := common.Address{}
    39  	if bytes.Equal(addr[:], nullAddress[:]) {
    40  		return &types.Address{0}
    41  	}
    42  	var a types.Address
    43  	copy(a[:], addr[:])
    44  	return &a
    45  }
    46  
    47  func ToAmcAccessList(accessList AccessList) transaction.AccessList {
    48  	var txAccessList transaction.AccessList
    49  	for _, accessTuple := range accessList {
    50  		txAccessTuple := new(transaction.AccessTuple)
    51  		txAccessTuple.Address = *ToAmcAddress(&accessTuple.Address)
    52  		for _, hash := range accessTuple.StorageKeys {
    53  			txAccessTuple.StorageKeys = append(txAccessTuple.StorageKeys, ToAmcHash(hash))
    54  		}
    55  		txAccessList = append(txAccessList, *txAccessTuple)
    56  	}
    57  	return txAccessList
    58  }
    59  
    60  func FromAmcAccessList(accessList transaction.AccessList) AccessList {
    61  	var txAccessList AccessList
    62  	for _, accessTuple := range accessList {
    63  		txAccessTuple := new(AccessTuple)
    64  		txAccessTuple.Address = *FromAmcAddress(&accessTuple.Address)
    65  		for _, hash := range accessTuple.StorageKeys {
    66  			txAccessTuple.StorageKeys = append(txAccessTuple.StorageKeys, FromAmcHash(hash))
    67  		}
    68  		txAccessList = append(txAccessList, *txAccessTuple)
    69  	}
    70  	return txAccessList
    71  }
    72  
    73  func FromAmcAddress(address *types.Address) *common.Address {
    74  	if address == nil {
    75  		return nil
    76  	}
    77  	var a common.Address
    78  	copy(a[:], address[:])
    79  	return &a
    80  }
    81  
    82  func ToAmcHash(hash common.Hash) types.Hash {
    83  	var h types.Hash
    84  	copy(h[:], hash[:])
    85  	return h
    86  }
    87  
    88  func FromAmcHash(hash types.Hash) common.Hash {
    89  	var h common.Hash
    90  	copy(h[:], hash[:])
    91  	return h
    92  }
    93  
    94  func ToAmcLog(log *Log) *block.Log {
    95  	if log == nil {
    96  		return nil
    97  	}
    98  
    99  	var topics []types.Hash
   100  	for _, topic := range log.Topics {
   101  		topics = append(topics, ToAmcHash(topic))
   102  	}
   103  
   104  	return &block.Log{
   105  		Address:     *ToAmcAddress(&log.Address),
   106  		Topics:      topics,
   107  		Data:        log.Data,
   108  		BlockNumber: uint256.NewInt(log.BlockNumber),
   109  		TxHash:      ToAmcHash(log.TxHash),
   110  		TxIndex:     log.TxIndex,
   111  		BlockHash:   ToAmcHash(log.BlockHash),
   112  		Index:       log.Index,
   113  		Removed:     log.Removed,
   114  	}
   115  }
   116  
   117  func FromAmcLog(log *block.Log) *Log {
   118  	if log == nil {
   119  		return nil
   120  	}
   121  
   122  	var topics []common.Hash
   123  	for _, topic := range log.Topics {
   124  		topics = append(topics, FromAmcHash(topic))
   125  	}
   126  
   127  	return &Log{
   128  		Address:     *FromAmcAddress(&log.Address),
   129  		Topics:      topics,
   130  		Data:        log.Data,
   131  		BlockNumber: log.BlockNumber.Uint64(),
   132  		TxHash:      FromAmcHash(log.TxHash),
   133  		TxIndex:     log.TxIndex,
   134  		BlockHash:   FromAmcHash(log.BlockHash),
   135  		Index:       log.Index,
   136  		Removed:     log.Removed,
   137  	}
   138  }
   139  
   140  func ToAmcLogs(logs []*Log) []*block.Log {
   141  	var amcLogs []*block.Log
   142  	for _, log := range logs {
   143  		amcLogs = append(amcLogs, ToAmcLog(log))
   144  	}
   145  	return amcLogs
   146  }
   147  
   148  func FromAmcLogs(amcLogs []*block.Log) []*Log {
   149  	var logs []*Log
   150  	for _, log := range amcLogs {
   151  		logs = append(logs, FromAmcLog(log))
   152  	}
   153  	return logs
   154  }
   155  
   156  type Transaction struct {
   157  	inner TxData    // Consensus contents of a transaction
   158  	time  time.Time // Time first seen locally (spam avoidance)
   159  
   160  	// caches
   161  	hash atomic.Value
   162  	size atomic.Value
   163  	from atomic.Value
   164  }
   165  
   166  // NewTx creates a new transaction.
   167  func NewTx(inner TxData) *Transaction {
   168  	tx := new(Transaction)
   169  	tx.setDecoded(inner.copy(), 0)
   170  	return tx
   171  }
   172  
   173  // Hash returns the transaction hash.
   174  func (tx *Transaction) Hash() common.Hash {
   175  	if hash := tx.hash.Load(); hash != nil {
   176  		return hash.(common.Hash)
   177  	}
   178  
   179  	var h common.Hash
   180  	if tx.Type() == LegacyTxType {
   181  		h = rlpHash(tx.inner)
   182  	} else {
   183  		h = prefixedRlpHash(tx.Type(), tx.inner)
   184  	}
   185  	tx.hash.Store(h)
   186  	return h
   187  }
   188  
   189  func isProtectedV(V *big.Int) bool {
   190  	if V.BitLen() <= 8 {
   191  		v := V.Uint64()
   192  		return v != 27 && v != 28 && v != 1 && v != 0
   193  	}
   194  	// anything not 27 or 28 is considered protected
   195  	return true
   196  }
   197  
   198  // Protected says whether the transaction is replay-protected.
   199  func (tx *Transaction) Protected() bool {
   200  	switch tx := tx.inner.(type) {
   201  	case *LegacyTx:
   202  		return tx.V != nil && isProtectedV(tx.V)
   203  	default:
   204  		return true
   205  	}
   206  }
   207  
   208  // Type returns the transaction type.
   209  func (tx *Transaction) Type() uint8 {
   210  	return tx.inner.txType()
   211  }
   212  
   213  // ChainId returns the EIP155 chain ID of the transaction. The return value will always be
   214  // non-nil. For legacy transactions which are not replay-protected, the return value is
   215  // zero.
   216  func (tx *Transaction) ChainId() *big.Int {
   217  	return tx.inner.chainID()
   218  }
   219  
   220  // Data returns the input data of the transaction.
   221  func (tx *Transaction) Data() []byte { return tx.inner.data() }
   222  
   223  // AccessList returns the access list of the transaction.
   224  func (tx *Transaction) AccessList() AccessList { return tx.inner.accessList() }
   225  
   226  // Gas returns the gas limit of the transaction.
   227  func (tx *Transaction) Gas() uint64 { return tx.inner.gas() }
   228  
   229  // GasPrice returns the gas price of the transaction.
   230  func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.inner.gasPrice()) }
   231  
   232  // GasTipCap returns the gasTipCap per gas of the transaction.
   233  func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.gasTipCap()) }
   234  
   235  // GasFeeCap returns the fee cap per gas of the transaction.
   236  func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) }
   237  
   238  // Value returns the ether amount of the transaction.
   239  func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) }
   240  
   241  // Nonce returns the sender account nonce of the transaction.
   242  func (tx *Transaction) Nonce() uint64 { return tx.inner.nonce() }
   243  
   244  // To returns the recipient address of the transaction.
   245  // For contract-creation transactions, To returns nil.
   246  func (tx *Transaction) To() *common.Address {
   247  	return copyAddressPtr(tx.inner.to())
   248  }
   249  
   250  func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) {
   251  	return tx.inner.rawSignatureValues()
   252  }
   253  
   254  // Size returns the true RLP encoded storage size of the transaction, either by
   255  // encoding and returning it, or returning a previously cached value.
   256  func (tx *Transaction) Size() common.StorageSize {
   257  	if size := tx.size.Load(); size != nil {
   258  		return size.(common.StorageSize)
   259  	}
   260  	c := writeCounter(0)
   261  	rlp.Encode(&c, &tx.inner)
   262  	tx.size.Store(common.StorageSize(c))
   263  	return common.StorageSize(c)
   264  }
   265  
   266  // WithSignature returns a new transaction with the given signature.
   267  // This signature needs to be in the [R || S || V] format where V is 0 or 1.
   268  func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) {
   269  	r, s, v, err := signer.SignatureValues(tx, sig)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  	cpy := tx.inner.copy()
   274  	cpy.setSignatureValues(signer.ChainID(), v, r, s)
   275  	return &Transaction{inner: cpy, time: tx.time}, nil
   276  }
   277  
   278  // UnmarshalBinary
   279  func (tx *Transaction) UnmarshalBinary(b []byte) error {
   280  	if len(b) > 0 && b[0] > 0x7f {
   281  		// It's a legacy transaction.
   282  		var data LegacyTx
   283  		err := rlp.DecodeBytes(b, &data)
   284  		if err != nil {
   285  			return err
   286  		}
   287  		tx.setDecoded(&data, len(b))
   288  		return nil
   289  	}
   290  	// It's an EIP2718 typed transaction envelope.
   291  	inner, err := tx.decodeTyped(b)
   292  	if err != nil {
   293  		return err
   294  	}
   295  	tx.setDecoded(inner, len(b))
   296  	return nil
   297  }
   298  
   299  // decodeTyped decodes a typed transaction from the canonical format.
   300  func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
   301  	if len(b) <= 1 {
   302  		return nil, fmt.Errorf("typed transaction too short")
   303  	}
   304  	switch b[0] {
   305  	case AccessListTxType:
   306  		var inner AccessListTx
   307  		err := rlp.DecodeBytes(b[1:], &inner)
   308  		return &inner, err
   309  	case DynamicFeeTxType:
   310  		var inner DynamicFeeTx
   311  		err := rlp.DecodeBytes(b[1:], &inner)
   312  		return &inner, err
   313  	default:
   314  		return nil, fmt.Errorf("transaction type not valid in this context")
   315  	}
   316  }
   317  
   318  // setDecoded sets the inner transaction and size after decoding.
   319  func (tx *Transaction) setDecoded(inner TxData, size int) {
   320  	tx.inner = inner
   321  	tx.time = time.Now()
   322  	if size > 0 {
   323  		tx.size.Store(common.StorageSize(size))
   324  	}
   325  }
   326  
   327  func (tx *Transaction) ToAmcTransaction(chainConfig *params.ChainConfig, blockNumber *big.Int) (*transaction.Transaction, error) {
   328  
   329  	var inner transaction.TxData
   330  	gasPrice, overflow := uint256.FromBig(tx.GasPrice())
   331  	if overflow {
   332  		return nil, fmt.Errorf("cannot convert big int to int256")
   333  	}
   334  
   335  	vl, overflow := uint256.FromBig(tx.Value())
   336  	if overflow {
   337  		return nil, fmt.Errorf("cannot convert big int to int256")
   338  	}
   339  
   340  	signer := MakeSigner(chainConfig, blockNumber)
   341  	from, err := Sender(signer, tx)
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  
   346  	v, r, s := tx.RawSignatureValues()
   347  	V, is1 := uint256.FromBig(v)
   348  	R, is2 := uint256.FromBig(r)
   349  	S, is3 := uint256.FromBig(s)
   350  	if is1 || is2 || is3 {
   351  		return nil, fmt.Errorf("r,s,v overflow")
   352  	}
   353  	switch tx.Type() {
   354  	case LegacyTxType:
   355  		inner = &transaction.LegacyTx{
   356  			Nonce:    tx.Nonce(),
   357  			Gas:      tx.Gas(),
   358  			Data:     common.CopyBytes(tx.Data()),
   359  			GasPrice: gasPrice,
   360  			Value:    vl,
   361  			To:       ToAmcAddress(tx.To()),
   362  			From:     ToAmcAddress(&from),
   363  			V:        V,
   364  			R:        R,
   365  			S:        S,
   366  		}
   367  
   368  		log.Debug("tx type is LegacyTxType")
   369  	case AccessListTxType:
   370  		at := &transaction.AccessListTx{
   371  			Nonce:      tx.Nonce(),
   372  			Gas:        tx.Gas(),
   373  			Data:       common.CopyBytes(tx.Data()),
   374  			To:         ToAmcAddress(tx.To()),
   375  			GasPrice:   gasPrice,
   376  			Value:      vl,
   377  			From:       ToAmcAddress(&from),
   378  			AccessList: ToAmcAccessList(tx.AccessList()),
   379  			V:          V,
   380  			R:          R,
   381  			S:          S,
   382  		}
   383  		at.ChainID, _ = uint256.FromBig(tx.ChainId())
   384  		inner = at
   385  		log.Debug("tx type is AccessListTxType")
   386  	case DynamicFeeTxType:
   387  		dft := &transaction.DynamicFeeTx{
   388  			Nonce:      tx.Nonce(),
   389  			Gas:        tx.Gas(),
   390  			To:         ToAmcAddress(tx.To()),
   391  			Data:       common.CopyBytes(tx.Data()),
   392  			AccessList: ToAmcAccessList(tx.AccessList()),
   393  			Value:      vl,
   394  			From:       ToAmcAddress(&from),
   395  			V:          V,
   396  			R:          R,
   397  			S:          S,
   398  		}
   399  		dft.ChainID, _ = uint256.FromBig(tx.ChainId())
   400  		dft.GasTipCap, _ = uint256.FromBig(tx.GasTipCap())
   401  		dft.GasFeeCap, _ = uint256.FromBig(tx.GasFeeCap())
   402  		inner = dft
   403  		log.Debug("tx type is DynamicFeeTxType")
   404  	}
   405  
   406  	amcTx := transaction.NewTx(inner)
   407  	return amcTx, nil
   408  }
   409  
   410  func (tx *Transaction) FromAmcTransaction(amcTx *transaction.Transaction) {
   411  
   412  	var inner TxData
   413  
   414  	gasPrice := amcTx.GasPrice().ToBig()
   415  	vl := amcTx.Value().ToBig()
   416  
   417  	switch amcTx.Type() {
   418  	case transaction.LegacyTxType:
   419  		inner = &LegacyTx{
   420  			Nonce:    amcTx.Nonce(),
   421  			Gas:      amcTx.Gas(),
   422  			Data:     common.CopyBytes(amcTx.Data()),
   423  			GasPrice: gasPrice,
   424  			Value:    vl,
   425  			To:       FromAmcAddress(amcTx.To()),
   426  		}
   427  
   428  	case transaction.AccessListTxType:
   429  		at := &AccessListTx{
   430  			Nonce:      amcTx.Nonce(),
   431  			Gas:        amcTx.Gas(),
   432  			Data:       common.CopyBytes(amcTx.Data()),
   433  			To:         FromAmcAddress(amcTx.To()),
   434  			GasPrice:   gasPrice,
   435  			Value:      vl,
   436  			AccessList: FromAmcAccessList(amcTx.AccessList()),
   437  		}
   438  		at.ChainID = amcTx.ChainId().ToBig()
   439  		inner = at
   440  
   441  	case transaction.DynamicFeeTxType:
   442  		dft := &DynamicFeeTx{
   443  			Nonce:      amcTx.Nonce(),
   444  			Gas:        amcTx.Gas(),
   445  			To:         FromAmcAddress(amcTx.To()),
   446  			Data:       common.CopyBytes(amcTx.Data()),
   447  			AccessList: FromAmcAccessList(amcTx.AccessList()),
   448  			Value:      vl,
   449  		}
   450  		dft.ChainID = amcTx.ChainId().ToBig()
   451  		dft.GasTipCap = amcTx.GasTipCap().ToBig()
   452  		dft.GasFeeCap = amcTx.GasFeeCap().ToBig()
   453  		inner = dft
   454  	}
   455  
   456  	v, r, s := amcTx.RawSignatureValues()
   457  	inner.setSignatureValues(amcTx.ChainId().ToBig(), v.ToBig(), r.ToBig(), s.ToBig())
   458  
   459  	tx.setDecoded(inner.copy(), 0)
   460  }
   461  
   462  func FromAmcHeader(iHeader block.IHeader) *Header {
   463  	header := iHeader.(*block.Header)
   464  	//author, _ := engine.Author(iHeader)
   465  
   466  	var baseFee *big.Int
   467  	if header.BaseFee != nil {
   468  		baseFee = header.BaseFee.ToBig()
   469  	}
   470  
   471  	bloom := new(Bloom)
   472  	bloom.SetBytes(header.Bloom.Bytes())
   473  
   474  	return &Header{
   475  		ParentHash:  FromAmcHash(header.ParentHash),
   476  		UncleHash:   FromAmcHash(EmptyUncleHash),
   477  		Coinbase:    *FromAmcAddress(&header.Coinbase),
   478  		Root:        FromAmcHash(header.Root),
   479  		TxHash:      FromAmcHash(header.TxHash),
   480  		ReceiptHash: FromAmcHash(header.ReceiptHash),
   481  		Difficulty:  header.Difficulty.ToBig(),
   482  		Number:      header.Number.ToBig(),
   483  		GasLimit:    header.GasLimit,
   484  		GasUsed:     header.GasUsed,
   485  		Time:        header.Time,
   486  		Extra:       header.Extra,
   487  		MixDigest:   FromAmcHash(header.MixDigest),
   488  		Nonce:       EncodeNonce(header.Nonce.Uint64()),
   489  		BaseFee:     baseFee,
   490  		Bloom:       *bloom,
   491  	}
   492  }
   493  
   494  func rlpHash(x interface{}) (h common.Hash) {
   495  	sha := hasherPool.Get().(crypto.KeccakState)
   496  	defer hasherPool.Put(sha)
   497  	sha.Reset()
   498  	rlp.Encode(sha, x)
   499  	sha.Read(h[:])
   500  	return h
   501  }
   502  
   503  // prefixedRlpHash writes the prefix into the hasher before rlp-encoding x.
   504  // It's used for typed transactions.
   505  func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) {
   506  	sha := hasherPool.Get().(crypto.KeccakState)
   507  	defer hasherPool.Put(sha)
   508  	sha.Reset()
   509  	sha.Write([]byte{prefix})
   510  	rlp.Encode(sha, x)
   511  	sha.Read(h[:])
   512  	return h
   513  }