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 }