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 }