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

     1  package flow
     2  
     3  import "encoding/json"
     4  
     5  // A Seal is produced when an Execution Result (referenced by `ResultID`) for
     6  // particular block (referenced by `BlockID`) is committed into the chain.
     7  // A Seal for a block B can be included in the payload B's descendants. Only
     8  // in the respective fork where the seal for B is included, the referenced
     9  // result is considered committed. Different forks might contain different
    10  // seals for the same result (or in edge cases, even for different results).
    11  //
    12  // NOTES
    13  // (1) As Seals are (currently) included in the payload, they are not strictly
    14  // entities. (Entities can be sent between nodes as self-contained messages
    15  // whose integrity is protected by a signature). By itself, a seal does
    16  // _not_ contain enough information to determine its validity (verifier
    17  // assignment cannot be computed) and its integrity is not protected by a
    18  // signature of a node that is authorized to generate it. A seal should only
    19  // be processed in the context of the block, which contains it.
    20  //
    21  // (2) Even though seals are not strictly entities, they still implement the
    22  // Entity interface. This allows us to store and retrieve seals individually.
    23  // CAUTION: As seals are part of the block payload, their _exact_ content must
    24  // be preserved by the storage system. This includes the exact list of approval
    25  // signatures (incl. order). While it is possible to construct different valid
    26  // seals for the same result (using different subsets of assigned verifiers),
    27  // they cannot be treated as equivalent for the following reason:
    28  //
    29  //   - Swapping a seal in a block with a different once changes the binary
    30  //     representation of the block payload containing the seal.
    31  //   - Changing the binary block representation would invalidate the block
    32  //     proposer's signature.
    33  //
    34  // Therefore, to retrieve valid blocks from storage, it is required that
    35  // the Seal.ID includes all fields with independent degrees of freedom
    36  // (such as AggregatedApprovalSigs).
    37  type Seal struct {
    38  	BlockID                Identifier
    39  	ResultID               Identifier
    40  	FinalState             StateCommitment
    41  	AggregatedApprovalSigs []AggregatedSignature // one AggregatedSignature per chunk
    42  }
    43  
    44  func (s Seal) Body() interface{} {
    45  	return struct {
    46  		BlockID                Identifier
    47  		ResultID               Identifier
    48  		FinalState             StateCommitment
    49  		AggregatedApprovalSigs []AggregatedSignature
    50  	}{
    51  		BlockID:                s.BlockID,
    52  		ResultID:               s.ResultID,
    53  		FinalState:             s.FinalState,
    54  		AggregatedApprovalSigs: s.AggregatedApprovalSigs,
    55  	}
    56  }
    57  
    58  func (s Seal) ID() Identifier {
    59  	return MakeID(s.Body())
    60  }
    61  
    62  func (s Seal) Checksum() Identifier {
    63  	return MakeID(s)
    64  }
    65  
    66  func (s Seal) MarshalJSON() ([]byte, error) {
    67  	type Alias Seal
    68  	return json.Marshal(struct {
    69  		Alias
    70  		ID string
    71  	}{
    72  		Alias: Alias(s),
    73  		ID:    s.ID().String(),
    74  	})
    75  }