github.com/klaytn/klaytn@v1.12.1/node/sc/main_bridge_handler.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package sc 18 19 import ( 20 "math/big" 21 22 "github.com/klaytn/klaytn/blockchain/types" 23 "github.com/klaytn/klaytn/common" 24 "github.com/klaytn/klaytn/datasync/downloader" 25 "github.com/klaytn/klaytn/networks/p2p" 26 "github.com/klaytn/klaytn/params" 27 "github.com/klaytn/klaytn/rlp" 28 "github.com/pkg/errors" 29 ) 30 31 var ErrRPCDecode = errors.New("failed to decode mainbridge rpc call message") 32 33 type MainBridgeHandler struct { 34 mainbridge *MainBridge 35 // childChainID is the first received chainID from child chain peer. 36 childChainIDs map[common.Address]*big.Int 37 } 38 39 func NewMainBridgeHandler(scc *SCConfig, main *MainBridge) (*MainBridgeHandler, error) { 40 return &MainBridgeHandler{ 41 mainbridge: main, 42 childChainIDs: make(map[common.Address]*big.Int), 43 }, nil 44 } 45 46 func (mbh *MainBridgeHandler) HandleSubMsg(p BridgePeer, msg p2p.Msg) error { 47 logger.Trace("mainbridge handle sub message", "msg.Code", msg.Code) 48 49 // Handle the message depending on its contents 50 switch msg.Code { 51 case ServiceChainCall: 52 if err := mbh.handleCallMsg(p, msg); err != nil { 53 return err 54 } 55 return nil 56 case StatusMsg: 57 return nil 58 case ServiceChainTxsMsg: 59 logger.Trace("received ServiceChainTxsMsg") 60 // TODO-Klaytn how to check acceptTxs 61 // Transactions arrived, make sure we have a valid and fresh chain to handle them 62 //if atomic.LoadUint32(&pm.acceptTxs) == 0 { 63 // break 64 //} 65 if err := mbh.handleServiceChainTxDataMsg(p, msg); err != nil { 66 return err 67 } 68 case ServiceChainParentChainInfoRequestMsg: 69 logger.Debug("received ServiceChainParentChainInfoRequestMsg") 70 if err := mbh.handleServiceChainParentChainInfoRequestMsg(p, msg); err != nil { 71 return err 72 } 73 case ServiceChainReceiptRequestMsg: 74 logger.Debug("received ServiceChainReceiptRequestMsg") 75 if err := mbh.handleServiceChainReceiptRequestMsg(p, msg); err != nil { 76 return err 77 } 78 default: 79 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 80 } 81 return nil 82 } 83 84 func (mbh *MainBridgeHandler) handleCallMsg(p BridgePeer, msg p2p.Msg) error { 85 logger.Trace("mainbridge writes the rpc call message to rpc server", "msg.Size", msg.Size, "msg", msg) 86 data := make([]byte, msg.Size) 87 err := msg.Decode(&data) 88 if err != nil { 89 logger.Error("error in mainbridge message handler", "err", err) 90 return err 91 } 92 93 // Write to RPC server pipe 94 _, err = mbh.mainbridge.rpcConn.Write(data) 95 if err != nil { 96 logger.Error("failed to write to the rpc server pipe", "err", err) 97 return err 98 } 99 return nil 100 } 101 102 // handleServiceChainTxDataMsg handles service chain transactions from child chain. 103 // It will return an error if given tx is not TxTypeChainDataAnchoring type. 104 func (mbh *MainBridgeHandler) handleServiceChainTxDataMsg(p BridgePeer, msg p2p.Msg) error { 105 // pm.txMsgLock.Lock() 106 // Transactions can be processed, parse all of them and deliver to the pool 107 var txs []*types.Transaction 108 if err := msg.Decode(&txs); err != nil { 109 return errResp(ErrDecode, "msg %v: %v", msg, err) 110 } 111 112 // Only valid txs should be pushed into the pool. 113 // Invalid txs found are sent to child chain for further action. 114 invalidTxs := make([]InvalidParentChainTx, 0) 115 for _, tx := range txs { 116 if tx == nil { 117 invalidTxs = append(invalidTxs, InvalidParentChainTx{tx.Hash(), errResp(ErrDecode, "tx is nil").Error()}) 118 continue 119 } 120 if err := mbh.mainbridge.txPool.AddRemote(tx); err != nil { 121 txHash := tx.Hash() 122 logger.Trace("Invalid tx found", 123 "txType", tx.Type(), "txNonce", tx.Nonce(), "txHash", txHash.String(), "err", err) 124 invalidTxs = append(invalidTxs, InvalidParentChainTx{txHash, err.Error()}) 125 } 126 } 127 if len(invalidTxs) > 0 { 128 return p.SendServiceChainInvalidTxResponse(invalidTxs) 129 } 130 return nil 131 } 132 133 // handleServiceChainParentChainInfoRequestMsg handles parent chain info request message from child chain. 134 // It will send the nonce of the account and its gas price to the child chain peer who requested. 135 func (mbh *MainBridgeHandler) handleServiceChainParentChainInfoRequestMsg(p BridgePeer, msg p2p.Msg) error { 136 var addr common.Address 137 if err := msg.Decode(&addr); err != nil { 138 return errResp(ErrDecode, "msg %v: %v", msg, err) 139 } 140 nonce := mbh.mainbridge.txPool.GetPendingNonce(addr) 141 chainCfg := mbh.mainbridge.blockchain.Config() 142 pcInfo := parentChainInfo{ 143 nonce, 144 mbh.mainbridge.txPool.GasPrice().Uint64(), 145 params.KIP71Config{ 146 LowerBoundBaseFee: chainCfg.Governance.KIP71.LowerBoundBaseFee, 147 UpperBoundBaseFee: chainCfg.Governance.KIP71.UpperBoundBaseFee, 148 GasTarget: chainCfg.Governance.KIP71.GasTarget, 149 MaxBlockGasUsedForBaseFee: chainCfg.Governance.KIP71.MaxBlockGasUsedForBaseFee, 150 BaseFeeDenominator: chainCfg.Governance.KIP71.BaseFeeDenominator, 151 }, 152 chainCfg.IsMagmaForkEnabled(mbh.mainbridge.blockchain.CurrentBlock().Number()), 153 } 154 p.SendServiceChainInfoResponse(&pcInfo) 155 logger.Info("SendServiceChainInfoResponse", "pBridgeAccoount", addr, 156 "nonce", pcInfo.Nonce, "gasPrice", pcInfo.GasPrice, 157 "LowerBoundBaseFee", pcInfo.KIP71Config.LowerBoundBaseFee, 158 "UpperBoundBaseFee", pcInfo.KIP71Config.UpperBoundBaseFee, 159 "GasTarget", pcInfo.KIP71Config.GasTarget, 160 "MaxBlockGasUsedForBaseFee", pcInfo.KIP71Config.MaxBlockGasUsedForBaseFee, 161 "BaseFeeDenominator", pcInfo.KIP71Config.BaseFeeDenominator, 162 ) 163 return nil 164 } 165 166 // handleServiceChainReceiptRequestMsg handles receipt request message from child chain. 167 // It will find and send corresponding receipts with given transaction hashes. 168 func (mbh *MainBridgeHandler) handleServiceChainReceiptRequestMsg(p BridgePeer, msg p2p.Msg) error { 169 // Decode the retrieval message 170 msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) 171 if _, err := msgStream.List(); err != nil { 172 return err 173 } 174 // Gather state data until the fetch or network limits is reached 175 var ( 176 hash common.Hash 177 receiptsForStorage []*types.ReceiptForStorage 178 ) 179 for len(receiptsForStorage) < downloader.MaxReceiptFetch { 180 // Retrieve the hash of the next block 181 if err := msgStream.Decode(&hash); err == rlp.EOL { 182 break 183 } else if err != nil { 184 return errResp(ErrDecode, "msg %v: %v", msg, err) 185 } 186 // Retrieve the receipt of requested service chain tx, skip if unknown. 187 receipt := mbh.mainbridge.blockchain.GetReceiptByTxHash(hash) 188 if receipt == nil { 189 continue 190 } 191 192 receiptsForStorage = append(receiptsForStorage, (*types.ReceiptForStorage)(receipt)) 193 } 194 if len(receiptsForStorage) == 0 { 195 return nil 196 } 197 return p.SendServiceChainReceiptResponse(receiptsForStorage) 198 }