Skip to content

Commit 35d56ce

Browse files
authored
Merge pull request #5438 from onflow/fxamacker/improve-payload-file
Add version, partial state indicator, and checksum to payload file (intermediate migration file)
2 parents 49aabc9 + 583caba commit 35d56ce

File tree

9 files changed

+537
-247
lines changed

9 files changed

+537
-247
lines changed

cmd/util/cmd/execution-state-extract/cmd.go

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,29 @@ import (
1313
runtimeCommon "github.com/onflow/cadence/runtime/common"
1414

1515
"github.com/onflow/flow-go/cmd/util/cmd/common"
16+
"github.com/onflow/flow-go/cmd/util/ledger/util"
1617
"github.com/onflow/flow-go/model/bootstrap"
1718
"github.com/onflow/flow-go/model/flow"
1819
"github.com/onflow/flow-go/module/metrics"
1920
"github.com/onflow/flow-go/storage/badger"
2021
)
2122

2223
var (
23-
flagExecutionStateDir string
24-
flagOutputDir string
25-
flagBlockHash string
26-
flagStateCommitment string
27-
flagDatadir string
28-
flagChain string
29-
flagNWorker int
30-
flagNoMigration bool
31-
flagNoReport bool
32-
flagValidateMigration bool
33-
flagLogVerboseValidationError bool
34-
flagInputPayloadFileName string
35-
flagOutputPayloadFileName string
36-
flagOutputPayloadByAddresses string
24+
flagExecutionStateDir string
25+
flagOutputDir string
26+
flagBlockHash string
27+
flagStateCommitment string
28+
flagDatadir string
29+
flagChain string
30+
flagNWorker int
31+
flagNoMigration bool
32+
flagNoReport bool
33+
flagValidateMigration bool
34+
flagLogVerboseValidationError bool
35+
flagAllowPartialStateFromPayloads bool
36+
flagInputPayloadFileName string
37+
flagOutputPayloadFileName string
38+
flagOutputPayloadByAddresses string
3739
)
3840

3941
var Cmd = &cobra.Command{
@@ -76,6 +78,9 @@ func init() {
7678
Cmd.Flags().BoolVar(&flagLogVerboseValidationError, "log-verbose-validation-error", false,
7779
"log entire Cadence values on validation error (atree migration)")
7880

81+
Cmd.Flags().BoolVar(&flagAllowPartialStateFromPayloads, "allow-partial-state-from-payload-file", false,
82+
"allow input payload file containing partial state (e.g. not all accounts)")
83+
7984
// If specified, the state will consist of payloads from the given input payload file.
8085
// If not specified, then the state will be extracted from the latest checkpoint file.
8186
// This flag can be used to reduce total duration of migrations when state extraction involves
@@ -166,6 +171,29 @@ func run(*cobra.Command, []string) {
166171
if _, err := os.Stat(flagInputPayloadFileName); os.IsNotExist(err) {
167172
log.Fatal().Msgf("payload input file %s doesn't exist", flagInputPayloadFileName)
168173
}
174+
175+
partialState, err := util.IsPayloadFilePartialState(flagInputPayloadFileName)
176+
if err != nil {
177+
log.Fatal().Err(err).Msgf("cannot get flag from payload input file %s", flagInputPayloadFileName)
178+
}
179+
180+
// Check if payload file contains partial state and is allowed by --allow-partial-state-from-payload-file.
181+
if !flagAllowPartialStateFromPayloads && partialState {
182+
log.Fatal().Msgf("payload input file %s contains partial state, please specify --allow-partial-state-from-payload-file", flagInputPayloadFileName)
183+
}
184+
185+
msg := "input payloads represent "
186+
if partialState {
187+
msg += "partial state"
188+
} else {
189+
msg += "complete state"
190+
}
191+
if flagAllowPartialStateFromPayloads {
192+
msg += ", and --allow-partial-state-from-payload-file is specified"
193+
} else {
194+
msg += ", and --allow-partial-state-from-payload-file is NOT specified"
195+
}
196+
log.Info().Msg(msg)
169197
}
170198

171199
if len(flagOutputPayloadFileName) > 0 {

cmd/util/cmd/execution-state-extract/execution_state_extract.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,22 @@ func extractExecutionState(
120120
if exportPayloads {
121121
payloads := newTrie.AllPayloads()
122122

123+
log.Info().Msgf("sorting %d payloads", len(payloads))
124+
125+
// Sort payloads to produce deterministic payload file with
126+
// same sequence of payloads inside.
127+
payloads = util.SortPayloadsByAddress(payloads, nWorker)
128+
129+
log.Info().Msgf("sorted %d payloads", len(payloads))
130+
131+
log.Info().Msgf("creating payloads file %s", outputPayloadFile)
132+
123133
exportedPayloadCount, err := util.CreatePayloadFile(
124134
log,
125135
outputPayloadFile,
126136
payloads,
127137
exportPayloadsByAddresses,
138+
false, // payloads represents entire state.
128139
)
129140
if err != nil {
130141
return fmt.Errorf("cannot generate payloads file: %w", err)
@@ -204,7 +215,7 @@ func extractExecutionStateFromPayloads(
204215
exportPayloadsByAddresses []common.Address,
205216
) error {
206217

207-
payloads, err := util.ReadPayloadFile(log, inputPayloadFile)
218+
inputPayloadsFromPartialState, payloads, err := util.ReadPayloadFile(log, inputPayloadFile)
208219
if err != nil {
209220
return err
210221
}
@@ -220,11 +231,23 @@ func extractExecutionStateFromPayloads(
220231

221232
exportPayloads := len(outputPayloadFile) > 0
222233
if exportPayloads {
234+
235+
log.Info().Msgf("sorting %d payloads", len(payloads))
236+
237+
// Sort payloads to produce deterministic payload file with
238+
// same sequence of payloads inside.
239+
payloads = util.SortPayloadsByAddress(payloads, nWorker)
240+
241+
log.Info().Msgf("sorted %d payloads", len(payloads))
242+
243+
log.Info().Msgf("creating payloads file %s", outputPayloadFile)
244+
223245
exportedPayloadCount, err := util.CreatePayloadFile(
224246
log,
225247
outputPayloadFile,
226248
payloads,
227249
exportPayloadsByAddresses,
250+
inputPayloadsFromPartialState,
228251
)
229252
if err != nil {
230253
return fmt.Errorf("cannot generate payloads file: %w", err)

cmd/util/cmd/execution-state-extract/execution_state_extract_test.go

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,10 @@ func TestExtractPayloadsFromExecutionState(t *testing.T) {
286286
require.NoError(t, err)
287287

288288
// Verify exported payloads.
289-
payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
289+
partialState, payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
290290
require.NoError(t, err)
291291
require.Equal(t, len(keysValues), len(payloadsFromFile))
292+
require.False(t, partialState)
292293

293294
for _, payloadFromFile := range payloadsFromFile {
294295
k, err := payloadFromFile.Key()
@@ -392,9 +393,10 @@ func TestExtractPayloadsFromExecutionState(t *testing.T) {
392393
require.NoError(t, err)
393394

394395
// Verify exported payloads.
395-
payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
396+
partialState, payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
396397
require.NoError(t, err)
397398
require.Equal(t, len(selectedKeysValues), len(payloadsFromFile))
399+
require.True(t, partialState)
398400

399401
for _, payloadFromFile := range payloadsFromFile {
400402
k, err := payloadFromFile.Key()
@@ -441,6 +443,7 @@ func TestExtractStateFromPayloads(t *testing.T) {
441443
inputPayloadFileName,
442444
payloads,
443445
nil,
446+
false,
444447
)
445448
require.NoError(t, err)
446449
require.Equal(t, len(payloads), numOfPayloadWritten)
@@ -511,6 +514,7 @@ func TestExtractStateFromPayloads(t *testing.T) {
511514
inputPayloadFileName,
512515
payloads,
513516
nil,
517+
false,
514518
)
515519
require.NoError(t, err)
516520
require.Equal(t, len(payloads), numOfPayloadWritten)
@@ -531,9 +535,79 @@ func TestExtractStateFromPayloads(t *testing.T) {
531535
require.NoError(t, err)
532536

533537
// Verify exported payloads.
534-
payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
538+
partialState, payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
539+
require.NoError(t, err)
540+
require.Equal(t, len(keysValues), len(payloadsFromFile))
541+
require.False(t, partialState)
542+
543+
for _, payloadFromFile := range payloadsFromFile {
544+
k, err := payloadFromFile.Key()
545+
require.NoError(t, err)
546+
547+
kv, exist := keysValues[k.String()]
548+
require.True(t, exist)
549+
550+
require.Equal(t, kv.value, payloadFromFile.Value())
551+
}
552+
})
553+
})
554+
555+
t.Run("input is partial state", func(t *testing.T) {
556+
withDirs(t, func(_, execdir, outdir string) {
557+
size := 10
558+
559+
inputPayloadFileName := filepath.Join(execdir, payloadFileName)
560+
outputPayloadFileName := filepath.Join(outdir, "selected.payload")
561+
562+
// Generate some data
563+
keysValues := make(map[string]keyPair)
564+
var payloads []*ledger.Payload
565+
566+
for i := 0; i < size; i++ {
567+
keys, values := getSampleKeyValues(i)
568+
569+
for j, key := range keys {
570+
keysValues[key.String()] = keyPair{
571+
key: key,
572+
value: values[j],
573+
}
574+
575+
payloads = append(payloads, ledger.NewPayload(key, values[j]))
576+
}
577+
}
578+
579+
// Create input payload file that represents partial state
580+
numOfPayloadWritten, err := util.CreatePayloadFile(
581+
zerolog.Nop(),
582+
inputPayloadFileName,
583+
payloads,
584+
nil,
585+
true,
586+
)
587+
require.NoError(t, err)
588+
require.Equal(t, len(payloads), numOfPayloadWritten)
589+
590+
// Since input payload file is partial state, --allow-partial-state-from-payload-file must be specified.
591+
Cmd.SetArgs([]string{
592+
"--execution-state-dir", execdir,
593+
"--output-dir", outdir,
594+
"--no-migration",
595+
"--no-report",
596+
"--state-commitment", "",
597+
"--input-payload-filename", inputPayloadFileName,
598+
"--output-payload-filename", outputPayloadFileName,
599+
"--extract-payloads-by-address", "",
600+
"--allow-partial-state-from-payload-file",
601+
"--chain", flow.Emulator.Chain().String()})
602+
603+
err = Cmd.Execute()
604+
require.NoError(t, err)
605+
606+
// Verify exported payloads.
607+
partialState, payloadsFromFile, err := util.ReadPayloadFile(zerolog.Nop(), outputPayloadFileName)
535608
require.NoError(t, err)
536609
require.Equal(t, len(keysValues), len(payloadsFromFile))
610+
require.True(t, partialState)
537611

538612
for _, payloadFromFile := range payloadsFromFile {
539613
k, err := payloadFromFile.Key()

0 commit comments

Comments
 (0)