github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/vent/service/block_consumer.go (about) 1 package service 2 3 import ( 4 "io" 5 6 "github.com/hyperledger/burrow/event/query" 7 "github.com/hyperledger/burrow/execution/exec" 8 "github.com/hyperledger/burrow/logging" 9 "github.com/hyperledger/burrow/logging/structure" 10 "github.com/hyperledger/burrow/vent/chain" 11 "github.com/hyperledger/burrow/vent/sqlsol" 12 "github.com/hyperledger/burrow/vent/types" 13 "github.com/pkg/errors" 14 ) 15 16 func NewBlockConsumer(chainID string, projection *sqlsol.Projection, opt sqlsol.SpecOpt, getEventSpec EventSpecGetter, 17 eventCh chan<- types.EventData, doneCh chan struct{}, logger *logging.Logger) func(block chain.Block) error { 18 19 logger = logger.WithScope("makeBlockConsumer") 20 21 var blockHeight uint64 22 23 return func(block chain.Block) error { 24 if finished(doneCh) { 25 return io.EOF 26 } 27 28 // set new block number 29 blockHeight = block.GetHeight() 30 txs := block.GetTxs() 31 32 logger.TraceMsg("Block received", 33 "height", blockHeight, 34 "num_txs", len(txs)) 35 36 // create a fresh new structure to store block data at this height 37 blockData := sqlsol.NewBlockData(blockHeight) 38 39 if opt.Enabled(sqlsol.Block) { 40 blkRawData, err := buildBlkData(projection.Tables, block) 41 if err != nil { 42 return errors.Wrapf(err, "Error building block raw data") 43 } 44 // set row in structure 45 blockData.AddRow(tables.Block, blkRawData) 46 } 47 48 for _, txe := range txs { 49 events := txe.GetEvents() 50 logger.TraceMsg("Getting transaction", "TxHash", txe.GetHash(), "num_events", len(events)) 51 52 if opt.Enabled(sqlsol.Tx) { 53 txRawData, err := buildTxData(txe) 54 if err != nil { 55 return errors.Wrapf(err, "Error building tx raw data") 56 } 57 // set row in structure 58 blockData.AddRow(tables.Tx, txRawData) 59 } 60 61 // reverted transactions don't have to update event data tables 62 // so check that condition to filter them 63 if txe.GetException() == nil { 64 txOrigin := txe.GetOrigin() 65 if txOrigin == nil { 66 // This is an original transaction from the current chain so we build its origin from context 67 txOrigin = &chain.Origin{ 68 ChainID: chainID, 69 Height: block.GetHeight(), 70 Index: txe.GetIndex(), 71 } 72 } 73 74 for _, event := range events { 75 var tagged query.Tagged = event 76 eventID := exec.SolidityEventID(event.GetTopics()) 77 eventSpec, eventSpecErr := getEventSpec(eventID, event.GetAddress()) 78 if eventSpecErr != nil { 79 logger.InfoMsg("could not get ABI for solidity event", 80 structure.ErrorKey, eventSpecErr, 81 "event_id", eventID, 82 "address", event.GetAddress()) 83 } else { 84 // Since we have the event ABI we will allow matching on ABI fields 85 tagged = query.TagsFor(event, query.TaggedPrefix("Event", eventSpec)) 86 } 87 88 // see which spec filter matches with the one in event data 89 for _, eventClass := range projection.Spec { 90 qry, err := eventClass.Query() 91 92 if err != nil { 93 return errors.Wrapf(err, "Error parsing query from filter string") 94 } 95 96 // there's a matching filter, add data to the rows 97 if qry.Matches(tagged) { 98 if eventSpecErr != nil { 99 return errors.Wrapf(eventSpecErr, "could not get ABI for solidity event matching "+ 100 "projection filter \"%s\" with id %v at address %v", 101 eventClass.Filter, eventID, event.GetAddress()) 102 } 103 104 logger.InfoMsg("Matched event", "event_id", eventID, "filter", eventClass.Filter) 105 106 // unpack, decode & build event data 107 eventData, err := buildEventData(projection, eventClass, event, txOrigin, eventSpec, logger) 108 if err != nil { 109 return errors.Wrapf(err, "Error building event data") 110 } 111 112 // set row in structure 113 blockData.AddRow(eventClass.TableName, eventData) 114 } 115 } 116 } 117 } 118 } 119 120 // upsert rows in specific SQL event tables and update block number 121 // store block data in SQL tables (if any) 122 for name, rows := range blockData.Data.Tables { 123 logger.InfoMsg("Upserting rows in SQL table", "height", blockHeight, "table", name, "action", "UPSERT", "rows", rows) 124 } 125 126 eventCh <- blockData.Data 127 return nil 128 } 129 }