github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/fork/terminals.go (about)

     1  package fork
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/flow-go/model/flow"
     7  	"github.com/onflow/flow-go/storage"
     8  )
     9  
    10  // IncludingBlock returns a Terminal implementation where we explicitly
    11  // specify the ID of the lowest block that should be visited
    12  type IncludingBlock flow.Identifier
    13  
    14  // LowestHeightToVisit computes the height of the lowest block that should be visited
    15  func (t IncludingBlock) LowestHeightToVisit(headers storage.Headers) (uint64, error) {
    16  	terminalHeader, err := headers.ByBlockID(flow.Identifier(t))
    17  	if err != nil {
    18  		return 0, fmt.Errorf("failed to retrieve header of terminal block %x: %w", flow.Identifier(t), err)
    19  	}
    20  	return terminalHeader.Height, nil
    21  }
    22  
    23  // ConfirmTerminalReached is a self-consistency check that the lowest visited block is
    24  // in fact the expected terminal.
    25  func (t IncludingBlock) ConfirmTerminalReached(headers storage.Headers, lowestVisitedBlock *flow.Header) error {
    26  	if lowestVisitedBlock.ID() != flow.Identifier(t) {
    27  		return fmt.Errorf("last visited block has ID %x but expecting %x", lowestVisitedBlock.ID(), flow.Identifier(t))
    28  	}
    29  	return nil
    30  }
    31  
    32  // ExcludingBlock returns a Terminal implementation where we explicitly
    33  // specify the ID of the lowest block that should _not_ be visited anymore
    34  type ExcludingBlock flow.Identifier
    35  
    36  // LowestHeightToVisit computes the height of the lowest block that should be visited
    37  func (t ExcludingBlock) LowestHeightToVisit(headers storage.Headers) (uint64, error) {
    38  	id := flow.Identifier(t)
    39  	terminalHeader, err := headers.ByBlockID(id)
    40  	if err != nil {
    41  		return 0, fmt.Errorf("failed to retrieve header of terminal block %x: %w", id, err)
    42  	}
    43  	return terminalHeader.Height + 1, nil
    44  }
    45  
    46  // ConfirmTerminalReached is a self-consistency check that the lowest visited block is
    47  // in fact the expected terminal.
    48  func (t ExcludingBlock) ConfirmTerminalReached(headers storage.Headers, lowestVisitedBlock *flow.Header) error {
    49  	if lowestVisitedBlock.ParentID != flow.Identifier(t) {
    50  		return fmt.Errorf("parent of last visited block has ID %x but expecting %x", lowestVisitedBlock.ParentID, flow.Identifier(t))
    51  	}
    52  	return nil
    53  }
    54  
    55  // IncludingHeight returns a Terminal implementation where we
    56  // specify the height of the lowest block that should be visited
    57  type IncludingHeight uint64
    58  
    59  // LowestHeightToVisit computes the height of the lowest block that should be visited
    60  func (t IncludingHeight) LowestHeightToVisit(storage.Headers) (uint64, error) {
    61  	return uint64(t), nil
    62  }
    63  
    64  // ConfirmTerminalReached is a self-consistency check that the lowest visited block is
    65  // in fact the expected terminal.
    66  func (t IncludingHeight) ConfirmTerminalReached(headers storage.Headers, lowestVisitedBlock *flow.Header) error {
    67  	if lowestVisitedBlock.Height != uint64(t) {
    68  		return fmt.Errorf("expecting terminal block with height %d but got %d", uint64(t), lowestVisitedBlock.Height)
    69  	}
    70  	return nil
    71  }
    72  
    73  // ExcludingHeight returns a Terminal implementation where we
    74  // specify the Height of the lowest block that should _not_ be visited anymore
    75  type ExcludingHeight uint64
    76  
    77  // LowestHeightToVisit computes the height of the lowest block that should be visited
    78  func (t ExcludingHeight) LowestHeightToVisit(storage.Headers) (uint64, error) {
    79  	return uint64(t) + 1, nil
    80  }
    81  
    82  // ConfirmTerminalReached is a self-consistency check that the lowest visited block is
    83  // in fact the expected terminal.
    84  func (t ExcludingHeight) ConfirmTerminalReached(headers storage.Headers, lowestVisitedBlock *flow.Header) error {
    85  	if lowestVisitedBlock.Height != uint64(t)+1 {
    86  		return fmt.Errorf("expecting terminal block with height %d but got %d", uint64(t)+1, lowestVisitedBlock.Height)
    87  	}
    88  	return nil
    89  }