github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/vent/service/abi_provider.go (about) 1 package service 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/hyperledger/burrow/crypto" 8 "github.com/hyperledger/burrow/execution/evm/abi" 9 "github.com/hyperledger/burrow/logging" 10 "github.com/hyperledger/burrow/vent/chain" 11 ) 12 13 type EventSpecGetter func(abi.EventID, crypto.Address) (*abi.EventSpec, error) 14 15 // AbiProvider provides a method for loading ABIs from disk, and retrieving them from burrow on-demand 16 type AbiProvider struct { 17 abiSpec *abi.Spec 18 chain chain.Chain 19 logger *logging.Logger 20 } 21 22 // NewAbiProvider loads ABIs from the filesystem. A set of zero or more files or directories can be passed in the path 23 // argument. If an event is encountered for which no ABI is known, it is retrieved from burrow 24 func NewAbiProvider(paths []string, chain chain.Chain, logger *logging.Logger) (provider *AbiProvider, err error) { 25 abiSpec := abi.NewSpec() 26 if len(paths) > 0 { 27 abiSpec, err = abi.LoadPath(paths...) 28 if err != nil { 29 return nil, err 30 } 31 } 32 33 provider = &AbiProvider{ 34 abiSpec: abiSpec, 35 chain: chain, 36 logger: logger.WithScope("NewAbiProvider"), 37 } 38 return 39 } 40 41 // GetEventAbi get the ABI for a particular eventID. If it is not known, it is retrieved from the burrow node via 42 // the address for the contract 43 func (p *AbiProvider) GetEventAbi(eventID abi.EventID, address crypto.Address) (*abi.EventSpec, error) { 44 evAbi, ok := p.abiSpec.EventsByID[eventID] 45 if !ok { 46 metadata, err := p.chain.GetABI(context.Background(), address) 47 if err != nil { 48 p.logger.InfoMsg("Error retrieving abi for event", "address", address.String(), "eventid", eventID.String(), "error", err) 49 return nil, err 50 } 51 if metadata == "" { 52 p.logger.InfoMsg("ABI not found for contract", "address", address.String(), "eventid", eventID.String()) 53 return nil, fmt.Errorf("No ABI present for contract at address %v", address) 54 } 55 a, err := abi.ReadSpec([]byte(metadata)) 56 if err != nil { 57 p.logger.InfoMsg("Failed to parse abi", "address", address.String(), "eventid", eventID.String(), "abi", metadata) 58 return nil, err 59 } 60 evAbi, ok = a.EventsByID[eventID] 61 if !ok { 62 p.logger.InfoMsg("Event missing from ABI spec for contract", "address", address.String(), "eventid", eventID.String(), "abi", metadata) 63 return nil, fmt.Errorf("Event missing from ABI spec for contract") 64 } 65 66 p.abiSpec = abi.MergeSpec([]*abi.Spec{p.abiSpec, a}) 67 } 68 69 return evAbi, nil 70 }