github.com/ChainSafe/chainbridge-core@v1.4.2/chains/evm/executor/message-handler.go (about) 1 package executor 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "math/big" 8 9 "github.com/ChainSafe/chainbridge-core/chains/evm/executor/proposal" 10 "github.com/ChainSafe/chainbridge-core/relayer/message" 11 "github.com/ChainSafe/chainbridge-core/types" 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/rs/zerolog/log" 14 ) 15 16 type HandlerMatcher interface { 17 GetHandlerAddressForResourceID(resourceID types.ResourceID) (common.Address, error) 18 ContractAddress() *common.Address 19 } 20 21 type MessageHandlerFunc func(m *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) 22 23 // NewEVMMessageHandler creates an instance of EVMMessageHandler that contains 24 // message handler functions for converting deposit message into a chain specific 25 // proposal 26 func NewEVMMessageHandler(handlerMatcher HandlerMatcher) *EVMMessageHandler { 27 return &EVMMessageHandler{ 28 handlerMatcher: handlerMatcher, 29 } 30 } 31 32 type EVMMessageHandler struct { 33 handlerMatcher HandlerMatcher 34 handlers map[common.Address]MessageHandlerFunc 35 } 36 37 func (mh *EVMMessageHandler) HandleMessage(m *message.Message) (*proposal.Proposal, error) { 38 // Matching resource ID with handler. 39 addr, err := mh.handlerMatcher.GetHandlerAddressForResourceID(m.ResourceId) 40 if err != nil { 41 return nil, err 42 } 43 // Based on handler that registered on BridgeContract 44 handleMessage, err := mh.MatchAddressWithHandlerFunc(addr) 45 if err != nil { 46 return nil, err 47 } 48 log.Info().Str("type", string(m.Type)).Uint8("src", m.Source).Uint8("dst", m.Destination).Uint64("nonce", m.DepositNonce).Str("resourceID", fmt.Sprintf("%x", m.ResourceId)).Msg("Handling new message") 49 prop, err := handleMessage(m, addr, *mh.handlerMatcher.ContractAddress()) 50 if err != nil { 51 return nil, err 52 } 53 return prop, nil 54 } 55 56 func (mh *EVMMessageHandler) MatchAddressWithHandlerFunc(addr common.Address) (MessageHandlerFunc, error) { 57 h, ok := mh.handlers[addr] 58 if !ok { 59 return nil, fmt.Errorf("no corresponding message handler for this address %s exists", addr.Hex()) 60 } 61 return h, nil 62 } 63 64 // RegisterEventHandler registers an message handler by associating a handler function to a specified address 65 func (mh *EVMMessageHandler) RegisterMessageHandler(address string, handler MessageHandlerFunc) { 66 if address == "" { 67 return 68 } 69 if mh.handlers == nil { 70 mh.handlers = make(map[common.Address]MessageHandlerFunc) 71 } 72 73 log.Debug().Msgf("Registered message handler for address %s", address) 74 75 mh.handlers[common.HexToAddress(address)] = handler 76 } 77 78 func ERC20MessageHandler(m *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { 79 if len(m.Payload) != 2 { 80 return nil, errors.New("malformed payload. Len of payload should be 2") 81 } 82 amount, ok := m.Payload[0].([]byte) 83 if !ok { 84 return nil, errors.New("wrong payload amount format") 85 } 86 recipient, ok := m.Payload[1].([]byte) 87 if !ok { 88 return nil, errors.New("wrong payload recipient format") 89 } 90 var data []byte 91 data = append(data, common.LeftPadBytes(amount, 32)...) // amount (uint256) 92 recipientLen := big.NewInt(int64(len(recipient))).Bytes() 93 data = append(data, common.LeftPadBytes(recipientLen, 32)...) // length of recipient (uint256) 94 data = append(data, recipient...) // recipient ([]byte) 95 return proposal.NewProposal(m.Source, m.Destination, m.DepositNonce, m.ResourceId, data, handlerAddr, bridgeAddress, m.Metadata), nil 96 } 97 98 func ERC721MessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { 99 100 if len(msg.Payload) != 3 { 101 return nil, errors.New("malformed payload. Len of payload should be 3") 102 } 103 tokenID, ok := msg.Payload[0].([]byte) 104 if !ok { 105 return nil, errors.New("wrong payload tokenID format") 106 } 107 recipient, ok := msg.Payload[1].([]byte) 108 if !ok { 109 return nil, errors.New("wrong payload recipient format") 110 } 111 metadata, ok := msg.Payload[2].([]byte) 112 if !ok { 113 return nil, errors.New("wrong payload metadata format") 114 } 115 data := bytes.Buffer{} 116 data.Write(common.LeftPadBytes(tokenID, 32)) 117 recipientLen := big.NewInt(int64(len(recipient))).Bytes() 118 data.Write(common.LeftPadBytes(recipientLen, 32)) 119 data.Write(recipient) 120 metadataLen := big.NewInt(int64(len(metadata))).Bytes() 121 data.Write(common.LeftPadBytes(metadataLen, 32)) 122 data.Write(metadata) 123 return proposal.NewProposal(msg.Source, msg.Destination, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress, msg.Metadata), nil 124 } 125 126 func GenericMessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { 127 if len(msg.Payload) != 1 { 128 return nil, errors.New("malformed payload. Len of payload should be 1") 129 } 130 metadata, ok := msg.Payload[0].([]byte) 131 if !ok { 132 return nil, errors.New("wrong payload metadata format") 133 } 134 data := bytes.Buffer{} 135 metadataLen := big.NewInt(int64(len(metadata))).Bytes() 136 data.Write(common.LeftPadBytes(metadataLen, 32)) // length of metadata (uint256) 137 data.Write(metadata) 138 return proposal.NewProposal(msg.Source, msg.Destination, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress, msg.Metadata), nil 139 }