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  }