github.com/koko1123/flow-go-1@v0.29.6/engine/execution/convert.go (about)

     1  package execution
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/koko1123/flow-go-1/model/convert"
     7  	"github.com/koko1123/flow-go-1/model/flow"
     8  	"github.com/koko1123/flow-go-1/module"
     9  )
    10  
    11  func GenerateExecutionResultAndChunkDataPacks(
    12  	metrics module.ExecutionMetrics,
    13  	prevResultId flow.Identifier,
    14  	startState flow.StateCommitment,
    15  	result *ComputationResult) (
    16  	endState flow.StateCommitment,
    17  	chdps []*flow.ChunkDataPack,
    18  	executionResult *flow.ExecutionResult,
    19  	err error,
    20  ) {
    21  
    22  	// no need to persist the state interactions, since they are used only by state
    23  	// syncing, which is currently disabled
    24  	block := result.ExecutableBlock.Block
    25  	blockID := block.ID()
    26  
    27  	chunks := make([]*flow.Chunk, len(result.StateCommitments))
    28  	chdps = make([]*flow.ChunkDataPack, len(result.StateCommitments))
    29  
    30  	// TODO: check current state root == startState
    31  	endState = startState
    32  
    33  	for i := range result.StateCommitments {
    34  		// TODO: deltas should be applied to a particular state
    35  
    36  		endState = result.StateCommitments[i]
    37  		var chunk *flow.Chunk
    38  		// account for system chunk being last
    39  		if i < len(result.StateCommitments)-1 {
    40  			// non-system chunks
    41  			collectionGuarantee := result.ExecutableBlock.Block.Payload.Guarantees[i]
    42  			completeCollection := result.ExecutableBlock.CompleteCollections[collectionGuarantee.ID()]
    43  			collection := completeCollection.Collection()
    44  			chunk = GenerateChunk(i, startState, endState, blockID, result.EventsHashes[i], uint64(len(completeCollection.Transactions)))
    45  			chdps[i] = GenerateChunkDataPack(chunk.ID(), startState, &collection, result.Proofs[i])
    46  			metrics.ExecutionChunkDataPackGenerated(len(result.Proofs[i]), len(completeCollection.Transactions))
    47  
    48  		} else {
    49  			// system chunk
    50  			// note that system chunk does not have a collection.
    51  			// also, number of transactions is one for system chunk.
    52  			chunk = GenerateChunk(i, startState, endState, blockID, result.EventsHashes[i], 1)
    53  			// system chunk has a nil collection.
    54  			chdps[i] = GenerateChunkDataPack(chunk.ID(), startState, nil, result.Proofs[i])
    55  			metrics.ExecutionChunkDataPackGenerated(len(result.Proofs[i]), 1)
    56  		}
    57  
    58  		// TODO use view.SpockSecret() as an input to spock generator
    59  		chunks[i] = chunk
    60  		startState = endState
    61  	}
    62  
    63  	executionResult, err = GenerateExecutionResultForBlock(prevResultId, block, chunks, result.ServiceEvents, result.ExecutionDataID)
    64  	if err != nil {
    65  		return flow.DummyStateCommitment, nil, nil, fmt.Errorf("could not generate execution result: %w", err)
    66  	}
    67  
    68  	return endState, chdps, executionResult, nil
    69  }
    70  
    71  // GenerateExecutionResultForBlock creates new ExecutionResult for a block from
    72  // the provided chunk results.
    73  func GenerateExecutionResultForBlock(
    74  	previousErID flow.Identifier,
    75  	block *flow.Block,
    76  	chunks []*flow.Chunk,
    77  	serviceEvents []flow.Event,
    78  	executionDataID flow.Identifier,
    79  ) (*flow.ExecutionResult, error) {
    80  
    81  	// convert Cadence service event representation to flow-go representation
    82  	convertedServiceEvents := make([]flow.ServiceEvent, 0, len(serviceEvents))
    83  	for _, event := range serviceEvents {
    84  		converted, err := convert.ServiceEvent(block.Header.ChainID, event)
    85  		if err != nil {
    86  			return nil, fmt.Errorf("could not convert service event: %w", err)
    87  		}
    88  		convertedServiceEvents = append(convertedServiceEvents, *converted)
    89  	}
    90  
    91  	er := &flow.ExecutionResult{
    92  		PreviousResultID: previousErID,
    93  		BlockID:          block.ID(),
    94  		Chunks:           chunks,
    95  		ServiceEvents:    convertedServiceEvents,
    96  		ExecutionDataID:  executionDataID,
    97  	}
    98  
    99  	return er, nil
   100  }
   101  
   102  // GenerateChunk creates a chunk from the provided computation data.
   103  func GenerateChunk(colIndex int,
   104  	startState, endState flow.StateCommitment,
   105  	blockID, eventsCollection flow.Identifier, txNumber uint64) *flow.Chunk {
   106  	return &flow.Chunk{
   107  		ChunkBody: flow.ChunkBody{
   108  			CollectionIndex: uint(colIndex),
   109  			StartState:      startState,
   110  			EventCollection: eventsCollection,
   111  			BlockID:         blockID,
   112  			// TODO: record gas used
   113  			TotalComputationUsed: 0,
   114  			NumberOfTransactions: txNumber,
   115  		},
   116  		Index:    uint64(colIndex),
   117  		EndState: endState,
   118  	}
   119  }
   120  
   121  func GenerateChunkDataPack(
   122  	chunkID flow.Identifier,
   123  	startState flow.StateCommitment,
   124  	collection *flow.Collection,
   125  	proof flow.StorageProof,
   126  ) *flow.ChunkDataPack {
   127  	return &flow.ChunkDataPack{
   128  		ChunkID:    chunkID,
   129  		StartState: startState,
   130  		Proof:      proof,
   131  		Collection: collection,
   132  	}
   133  }