github.com/datachainlab/burrow@v0.25.0/execution/state/events.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/hyperledger/burrow/execution/exec" 8 ) 9 10 func (ws *writeState) AddBlock(be *exec.BlockExecution) error { 11 tree, err := ws.forest.Writer(keys.Event.Prefix()) 12 if err != nil { 13 return err 14 } 15 txHashTree, err := ws.forest.Writer(keys.TxHash.Prefix()) 16 if err != nil { 17 return err 18 } 19 // Index transactions so they can be retrieved by their TxHash 20 for index, ev := range be.StreamEvents() { 21 // Store with prefix for scanning later 22 key := keys.Event.KeyNoPrefix(be.Height, uint64(index)) 23 bs, err := ev.Encode() 24 if err != nil { 25 return err 26 } 27 // Set StreamEvent itself 28 tree.Set(key, bs) 29 if ev.BeginTx != nil { 30 // Set reference to TxExecution 31 txHashTree.Set(keys.TxHash.KeyNoPrefix(ev.BeginTx.TxHeader.TxHash), key) 32 } 33 } 34 return nil 35 } 36 37 func (s *ReadState) IterateStreamEvents(start, end *exec.StreamKey, consumer func(*exec.StreamEvent) error) error { 38 tree, err := s.Forest.Reader(keys.Event.Prefix()) 39 if err != nil { 40 return err 41 } 42 var startKey, endKey []byte 43 if start != nil { 44 startKey = keys.Event.KeyNoPrefix(start.Height, start.Index) 45 } 46 if end != nil { 47 endKey = keys.Event.KeyNoPrefix(end.Height, end.Index) 48 } 49 return tree.Iterate(startKey, endKey, true, func(_, value []byte) error { 50 txe, err := exec.DecodeStreamEvent(value) 51 if err != nil { 52 return fmt.Errorf("error unmarshalling BlockExecution in GetBlocks: %v", err) 53 } 54 return consumer(txe) 55 }) 56 } 57 58 func (s *ReadState) TxsAtHeight(height uint64) ([]*exec.TxExecution, error) { 59 var stack exec.TxStack 60 var txExecutions []*exec.TxExecution 61 err := s.IterateStreamEvents(&exec.StreamKey{Height: height}, &exec.StreamKey{Height: height + 1}, 62 func(ev *exec.StreamEvent) error { 63 // Keep trying to consume TxExecutions at from events at this height 64 txe := stack.Consume(ev) 65 if txe != nil { 66 txExecutions = append(txExecutions, txe) 67 } 68 return nil 69 }) 70 if err != nil && err != io.EOF { 71 return nil, err 72 } 73 return txExecutions, nil 74 } 75 76 func (s *ReadState) StreamEvent(height, index uint64) (*exec.StreamEvent, error) { 77 tree, err := s.Forest.Reader(keys.Event.Prefix()) 78 if err != nil { 79 return nil, err 80 } 81 // Note: stored with prefix for scanning 82 bs := tree.Get(keys.Event.KeyNoPrefix(height, index)) 83 if len(bs) == 0 { 84 return nil, nil 85 } 86 return exec.DecodeStreamEvent(bs) 87 } 88 89 func (s *ReadState) TxByHash(txHash []byte) (*exec.TxExecution, error) { 90 const errHeader = "TxByHash():" 91 eventKeyByTxHashTree, err := s.Forest.Reader(keys.TxHash.Prefix()) 92 if err != nil { 93 return nil, err 94 } 95 eventKey := eventKeyByTxHashTree.Get(keys.TxHash.KeyNoPrefix(txHash)) 96 if len(eventKey) == 0 { 97 return nil, nil 98 } 99 eventTree, err := s.Forest.Reader(keys.Event.Prefix()) 100 if err != nil { 101 return nil, err 102 } 103 bs := eventTree.Get(eventKey) 104 if len(bs) == 0 { 105 return nil, fmt.Errorf("%s could not retieve transaction with TxHash %X despite finding reference", 106 errHeader, txHash) 107 } 108 ev, err := exec.DecodeStreamEvent(bs) 109 if err != nil { 110 return nil, err 111 } 112 if ev.BeginTx == nil { 113 return nil, fmt.Errorf("%s StreamEvent %v is not a transaction despite being indexed as such", 114 errHeader, ev) 115 } 116 117 start := new(exec.StreamKey) 118 // Scan out position in storage 119 err = keys.Event.ScanNoPrefix(eventKey, &start.Height, &start.Index) 120 if err != nil { 121 return nil, fmt.Errorf("%s could not scan height and index from tx key %X: %v", errHeader, eventKey, err) 122 } 123 // Iterate to end of block - we will break the iteration once we have scanned the tx so this is an upper bound 124 end := &exec.StreamKey{Height: start.Height + 1} 125 126 // Establish iteration state 127 var stack exec.TxStack 128 var txe *exec.TxExecution 129 err = s.IterateStreamEvents(start, end, func(ev *exec.StreamEvent) error { 130 txe = stack.Consume(ev) 131 if txe != nil { 132 return io.EOF 133 } 134 return nil 135 }) 136 if err != nil && err != io.EOF { 137 return nil, fmt.Errorf("%s error iterating over stream events %v", errHeader, err) 138 } 139 // Possibly nil if not found 140 return txe, nil 141 }