github.com/nnlgsakib/mind-dpos@v0.0.0-20230606105614-f3c8ca06f808/consensus/alien/cross_chain.go (about)

     1  // Copyright 2018 The gttc Authors
     2  // This file is part of the gttc library.
     3  //
     4  // The gttc 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 gttc 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 gttc library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package alien implements the delegated-proof-of-stake consensus engine.
    18  package alien
    19  
    20  import (
    21  	"context"
    22  	"errors"
    23  	"math/big"
    24  	"time"
    25  
    26  	"github.com/TTCECO/gttc/common"
    27  	"github.com/TTCECO/gttc/common/hexutil"
    28  	"github.com/TTCECO/gttc/consensus"
    29  	"github.com/TTCECO/gttc/core/types"
    30  	"github.com/TTCECO/gttc/rlp"
    31  )
    32  
    33  const (
    34  	mainchainRPCTimeout = 300 // Number of millisecond mainchain rpc connect timeout
    35  )
    36  
    37  var (
    38  	// errNotSideChain is returned if main chain try to get main chain client
    39  	errNotSideChain = errors.New("not side chain")
    40  
    41  	// errMCRPCCLientEmpty is returned if Side chain not have main chain rpc client
    42  	errMCRPCClientEmpty = errors.New("main chain rpc client empty")
    43  
    44  	// errMCPeriodMissing is returned if period from main chain snapshot is zero
    45  	errMCPeriodMissing = errors.New("main chain period is missing")
    46  
    47  	// errMCGasChargingInvalid is returned if gas charging info on main chain and side chain header are different
    48  	errMCGasChargingInvalid = errors.New("gas charging info is invalid")
    49  )
    50  
    51  // getMainChainSnapshotByTime return snapshot by header time of side chain
    52  // the rpc api will return the snapshot with the same header time (not loopStartTime)
    53  func (a *Alien) getMainChainSnapshotByTime(chain consensus.ChainReader, headerTime uint64, scHash common.Hash) (*Snapshot, error) {
    54  	if !chain.Config().Alien.SideChain {
    55  		return nil, errNotSideChain
    56  	}
    57  	if chain.Config().Alien.MCRPCClient == nil {
    58  		return nil, errMCRPCClientEmpty
    59  	}
    60  	ctx, cancel := context.WithTimeout(context.Background(), mainchainRPCTimeout*time.Millisecond)
    61  	defer cancel()
    62  
    63  	var ms *Snapshot
    64  	if err := chain.Config().Alien.MCRPCClient.CallContext(ctx, &ms, "alien_getSnapshotByHeaderTime", headerTime, scHash); err != nil {
    65  		return nil, err
    66  	} else if ms.Period == 0 {
    67  		return nil, errMCPeriodMissing
    68  	}
    69  	return ms, nil
    70  }
    71  
    72  // sendTransactionToMainChain
    73  // transaction send to main chain by rpc api, usually is the transaction for notify or confirm seal new block.
    74  func (a *Alien) sendTransactionToMainChain(chain consensus.ChainReader, tx *types.Transaction) (common.Hash, error) {
    75  	if !chain.Config().Alien.SideChain {
    76  		return common.Hash{}, errNotSideChain
    77  	}
    78  	if chain.Config().Alien.MCRPCClient == nil {
    79  		return common.Hash{}, errMCRPCClientEmpty
    80  	}
    81  	ctx, cancel := context.WithTimeout(context.Background(), mainchainRPCTimeout*time.Millisecond)
    82  	defer cancel()
    83  
    84  	data, err := rlp.EncodeToBytes(tx)
    85  	if err != nil {
    86  		return common.Hash{}, err
    87  	}
    88  	var hash common.Hash
    89  	if err := chain.Config().Alien.MCRPCClient.CallContext(ctx, &hash, "eth_sendRawTransaction", common.ToHex(data)); err != nil {
    90  		return common.Hash{}, err
    91  	}
    92  	return hash, nil
    93  }
    94  
    95  // getTransactionCountFromMainChain
    96  // get nonce from main chain for sendTransactionToMainChain
    97  func (a *Alien) getTransactionCountFromMainChain(chain consensus.ChainReader, account common.Address) (uint64, error) {
    98  	if !chain.Config().Alien.SideChain {
    99  		return 0, errNotSideChain
   100  	}
   101  	if chain.Config().Alien.MCRPCClient == nil {
   102  		return 0, errMCRPCClientEmpty
   103  	}
   104  	ctx, cancel := context.WithTimeout(context.Background(), mainchainRPCTimeout*time.Millisecond)
   105  	defer cancel()
   106  
   107  	var result hexutil.Uint64
   108  	if err := chain.Config().Alien.MCRPCClient.CallContext(ctx, &result, "eth_getTransactionCount", account.Hex(), "latest"); err != nil {
   109  		return 0, err
   110  	}
   111  	return uint64(result), nil
   112  }
   113  
   114  // getNetVersionFromMainChain
   115  // get network id
   116  func (a *Alien) getNetVersionFromMainChain(chain consensus.ChainReader) (uint64, error) {
   117  	if !chain.Config().Alien.SideChain {
   118  		return 0, errNotSideChain
   119  	}
   120  	if chain.Config().Alien.MCRPCClient == nil {
   121  		return 0, errMCRPCClientEmpty
   122  	}
   123  	ctx, cancel := context.WithTimeout(context.Background(), mainchainRPCTimeout*time.Millisecond)
   124  	defer cancel()
   125  
   126  	var result string
   127  	if err := chain.Config().Alien.MCRPCClient.CallContext(ctx, &result, "net_version", "latest"); err != nil {
   128  		return 0, err
   129  	}
   130  
   131  	netVersion := new(big.Int)
   132  	err := netVersion.UnmarshalText([]byte(result))
   133  	if err != nil {
   134  		return 0, err
   135  	}
   136  	return netVersion.Uint64(), nil
   137  }