github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/chunks/chunkFaults.go (about)

     1  package chunks
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/onflow/flow-go/model/flow"
     9  )
    10  
    11  // ChunkFaultError holds information about a fault that is found while
    12  // verifying a chunk
    13  type ChunkFaultError interface {
    14  	error
    15  	ChunkIndex() uint64
    16  	ExecutionResultID() flow.Identifier
    17  	String() string
    18  }
    19  
    20  func IsChunkFaultError(err error) bool {
    21  	var cfErr ChunkFaultError
    22  	return errors.As(err, &cfErr)
    23  }
    24  
    25  // CFMissingRegisterTouch is returned when a register touch is missing (read or update)
    26  type CFMissingRegisterTouch struct {
    27  	regsterIDs []string
    28  	chunkIndex uint64
    29  	execResID  flow.Identifier
    30  	txID       flow.Identifier // very first transaction inside the chunk that required this register
    31  }
    32  
    33  var _ ChunkFaultError = (*CFMissingRegisterTouch)(nil)
    34  
    35  func (cf CFMissingRegisterTouch) String() string {
    36  	hexStrings := make([]string, len(cf.regsterIDs))
    37  	for i, s := range cf.regsterIDs {
    38  		hexStrings[i] = hex.EncodeToString([]byte(s))
    39  	}
    40  
    41  	return fmt.Sprintf("at least one register touch was missing inside the chunk data package that was needed while running transactions of chunk %d of result %s (tx hash of one of them: %s), hex-encoded register ids: %s", cf.chunkIndex, cf.execResID.String(), cf.txID.String(), hexStrings)
    42  }
    43  
    44  func (cf CFMissingRegisterTouch) Error() string {
    45  	return cf.String()
    46  }
    47  
    48  // ChunkIndex returns chunk index of the faulty chunk
    49  func (cf CFMissingRegisterTouch) ChunkIndex() uint64 {
    50  	return cf.chunkIndex
    51  }
    52  
    53  // ExecutionResultID returns the execution result identifier including the faulty chunk
    54  func (cf CFMissingRegisterTouch) ExecutionResultID() flow.Identifier {
    55  	return cf.execResID
    56  }
    57  
    58  // NewCFMissingRegisterTouch creates a new instance of Chunk Fault (MissingRegisterTouch)
    59  func NewCFMissingRegisterTouch(regsterIDs []string, chInx uint64, execResID flow.Identifier, txID flow.Identifier) *CFMissingRegisterTouch {
    60  	return &CFMissingRegisterTouch{regsterIDs: regsterIDs,
    61  		chunkIndex: chInx,
    62  		execResID:  execResID,
    63  		txID:       txID}
    64  }
    65  
    66  // CFNonMatchingFinalState is returned when the computed final state commitment
    67  // (applying chunk register updates to the partial trie) doesn't match the one provided by the chunk
    68  type CFNonMatchingFinalState struct {
    69  	expected   flow.StateCommitment
    70  	computed   flow.StateCommitment
    71  	chunkIndex uint64
    72  	execResID  flow.Identifier
    73  }
    74  
    75  var _ ChunkFaultError = (*CFNonMatchingFinalState)(nil)
    76  
    77  func (cf CFNonMatchingFinalState) String() string {
    78  	return fmt.Sprintf("final state commitment doesn't match, expected [%x] but computed [%x]", cf.expected, cf.computed)
    79  }
    80  
    81  func (cf CFNonMatchingFinalState) Error() string {
    82  	return cf.String()
    83  }
    84  
    85  // ChunkIndex returns chunk index of the faulty chunk
    86  func (cf CFNonMatchingFinalState) ChunkIndex() uint64 {
    87  	return cf.chunkIndex
    88  }
    89  
    90  // ExecutionResultID returns the execution result identifier including the faulty chunk
    91  func (cf CFNonMatchingFinalState) ExecutionResultID() flow.Identifier {
    92  	return cf.execResID
    93  }
    94  
    95  // NewCFNonMatchingFinalState creates a new instance of Chunk Fault (NonMatchingFinalState)
    96  func NewCFNonMatchingFinalState(expected flow.StateCommitment, computed flow.StateCommitment, chInx uint64, execResID flow.Identifier) *CFNonMatchingFinalState {
    97  	return &CFNonMatchingFinalState{expected: expected,
    98  		computed:   computed,
    99  		chunkIndex: chInx,
   100  		execResID:  execResID}
   101  }
   102  
   103  // CFInvalidEventsCollection is returned when computed events collection hash is different from the chunk's one
   104  type CFInvalidEventsCollection struct {
   105  	expected   flow.Identifier
   106  	computed   flow.Identifier
   107  	chunkIndex uint64
   108  	resultID   flow.Identifier
   109  	eventIDs   flow.IdentifierList
   110  }
   111  
   112  var _ ChunkFaultError = (*CFInvalidEventsCollection)(nil)
   113  
   114  func NewCFInvalidEventsCollection(expected flow.Identifier, computed flow.Identifier, chInx uint64, execResID flow.Identifier, events flow.EventsList) *CFInvalidEventsCollection {
   115  	return &CFInvalidEventsCollection{
   116  		expected:   expected,
   117  		computed:   computed,
   118  		chunkIndex: chInx,
   119  		resultID:   execResID,
   120  		eventIDs:   flow.GetIDs(events),
   121  	}
   122  }
   123  
   124  func (c *CFInvalidEventsCollection) ChunkIndex() uint64 {
   125  	return c.chunkIndex
   126  }
   127  
   128  func (c *CFInvalidEventsCollection) ExecutionResultID() flow.Identifier {
   129  	return c.resultID
   130  }
   131  
   132  func (c *CFInvalidEventsCollection) String() string {
   133  	return fmt.Sprintf("events collection hash differs, got %x expected %x for chunk %d with result ID %s, events IDs: %v", c.computed, c.expected,
   134  		c.chunkIndex, c.resultID, c.eventIDs)
   135  }
   136  
   137  func (cf CFInvalidEventsCollection) Error() string {
   138  	return cf.String()
   139  }
   140  
   141  // CFInvalidServiceEventsEmitted is returned when service events are different from the chunk's one
   142  type CFInvalidServiceEventsEmitted struct {
   143  	expected   flow.ServiceEventList
   144  	computed   flow.ServiceEventList
   145  	chunkIndex uint64
   146  	resultID   flow.Identifier
   147  }
   148  
   149  var _ ChunkFaultError = (*CFInvalidServiceEventsEmitted)(nil)
   150  
   151  func CFInvalidServiceSystemEventsEmitted(expected flow.ServiceEventList, computed flow.ServiceEventList, chInx uint64, execResID flow.Identifier) *CFInvalidServiceEventsEmitted {
   152  	return &CFInvalidServiceEventsEmitted{
   153  		expected:   expected,
   154  		computed:   computed,
   155  		chunkIndex: chInx,
   156  		resultID:   execResID,
   157  	}
   158  }
   159  
   160  func (c *CFInvalidServiceEventsEmitted) ChunkIndex() uint64 {
   161  	return c.chunkIndex
   162  }
   163  
   164  func (c *CFInvalidServiceEventsEmitted) ExecutionResultID() flow.Identifier {
   165  	return c.resultID
   166  }
   167  
   168  func (c *CFInvalidServiceEventsEmitted) String() string {
   169  	return fmt.Sprintf("service events differs, got [%s] expected [%s] for chunk %d with result ID %s", c.computed, c.expected, c.chunkIndex, c.resultID)
   170  }
   171  
   172  func (cf CFInvalidServiceEventsEmitted) Error() string {
   173  	return cf.String()
   174  }
   175  
   176  // CFInvalidVerifiableChunk is returned when a verifiable chunk is invalid
   177  // this includes cases that code fails to construct a partial trie,
   178  // collection hashes doesn't match
   179  // TODO break this into more detailed ones as we progress
   180  type CFInvalidVerifiableChunk struct {
   181  	reason     string
   182  	details    error
   183  	chunkIndex uint64
   184  	execResID  flow.Identifier
   185  }
   186  
   187  var _ ChunkFaultError = (*CFInvalidVerifiableChunk)(nil)
   188  
   189  func (cf CFInvalidVerifiableChunk) String() string {
   190  	return fmt.Sprint("invalid verifiable chunk due to ", cf.reason, cf.details.Error())
   191  }
   192  
   193  func (cf CFInvalidVerifiableChunk) Error() string {
   194  	return cf.String()
   195  }
   196  
   197  // ChunkIndex returns chunk index of the faulty chunk
   198  func (cf CFInvalidVerifiableChunk) ChunkIndex() uint64 {
   199  	return cf.chunkIndex
   200  }
   201  
   202  // ExecutionResultID returns the execution result identifier including the faulty chunk
   203  func (cf CFInvalidVerifiableChunk) ExecutionResultID() flow.Identifier {
   204  	return cf.execResID
   205  }
   206  
   207  // NewCFInvalidVerifiableChunk creates a new instance of Chunk Fault (InvalidVerifiableChunk)
   208  func NewCFInvalidVerifiableChunk(reason string, err error, chInx uint64, execResID flow.Identifier) *CFInvalidVerifiableChunk {
   209  	return &CFInvalidVerifiableChunk{reason: reason,
   210  		details:    err,
   211  		chunkIndex: chInx,
   212  		execResID:  execResID}
   213  }
   214  
   215  // CFSystemChunkIncludedCollection is returned when a system chunk includes a collection
   216  type CFSystemChunkIncludedCollection struct {
   217  	chunkIndex uint64
   218  	execResID  flow.Identifier
   219  }
   220  
   221  var _ ChunkFaultError = (*CFSystemChunkIncludedCollection)(nil)
   222  
   223  func (cf CFSystemChunkIncludedCollection) String() string {
   224  	return fmt.Sprintf("system chunk data pack must not include a collection but did for chunk %d with result ID %s", cf.chunkIndex, cf.execResID)
   225  }
   226  
   227  func (cf CFSystemChunkIncludedCollection) Error() string {
   228  	return cf.String()
   229  }
   230  
   231  // ChunkIndex returns chunk index of the faulty chunk
   232  func (cf CFSystemChunkIncludedCollection) ChunkIndex() uint64 {
   233  	return cf.chunkIndex
   234  }
   235  
   236  // ExecutionResultID returns the execution result identifier including the faulty chunk
   237  func (cf CFSystemChunkIncludedCollection) ExecutionResultID() flow.Identifier {
   238  	return cf.execResID
   239  }
   240  
   241  // NewCFSystemChunkIncludedCollection creates a new instance of Chunk Fault (SystemChunkIncludedCollection)
   242  func NewCFSystemChunkIncludedCollection(chInx uint64, execResID flow.Identifier) *CFSystemChunkIncludedCollection {
   243  	return &CFSystemChunkIncludedCollection{
   244  		chunkIndex: chInx,
   245  		execResID:  execResID,
   246  	}
   247  }