Skip to content

Commit 95b5b10

Browse files
authored
Merge pull request #7766 from onflow/tim/malleability-sync-master-2025-08-25
Sync master to malleability branch
2 parents 32bd006 + dcd096d commit 95b5b10

38 files changed

+428
-313
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,6 @@ jobs:
295295
runs-on: buildjet-16vcpu-ubuntu-2204
296296
env:
297297
CADENCE_DEPLOY_KEY: ${{ secrets.CADENCE_DEPLOY_KEY }}
298-
# Set the environment based on the author association of the pull request.
299-
# This is used to determine whether the build should be run in an internal or external environment.
300-
# If the author is a member or collaborator, use the internal environment; otherwise, use the external environment that will require approval
301-
environment: ${{ (github.event_name == 'merge_group' || (github.event.pull_request && (github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR'))) && 'internal-ci' || 'external-ci' }}
302298
steps:
303299
- name: Checkout repo
304300
uses: actions/checkout@v4

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,12 @@ tools/custom-gcl: tools/structwrite .custom-gcl.yml
250250
.PHONY: lint
251251
lint: tidy tools/custom-gcl
252252
# revive -config revive.toml -exclude storage/ledger/trie ./...
253-
./tools/custom-gcl run -v ./...
253+
./tools/custom-gcl run -v $(or $(LINT_PATH),./...)
254254

255255
.PHONY: fix-lint
256256
fix-lint:
257257
# revive -config revive.toml -exclude storage/ledger/trie ./...
258-
./tools/custom-gcl run -v --fix ./...
258+
./tools/custom-gcl run -v --fix $(or $(LINT_PATH),./...)
259259

260260
# Runs unit tests with different list of packages as passed by CI so they run in parallel
261261
.PHONY: ci

cmd/bootstrap/transit/cmd/crypto_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@ import (
1414
const nodeID string = "0000000000000000000000000000000000000000000000000000000000000001"
1515

1616
func TestEndToEnd(t *testing.T) {
17-
1817
// Create a temp directory to work as "bootstrap"
1918
bootdir := t.TempDir()
2019

2120
t.Logf("Created dir %s", bootdir)
2221

2322
// Create test files
24-
//bootcmd.WriteText(filepath.Join(bootdir, bootstrap.PathNodeId), []byte(nodeID)
2523
randomBeaconPath := filepath.Join(bootdir, fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID))
2624
err := os.MkdirAll(filepath.Dir(randomBeaconPath), 0755)
2725
if err != nil {
@@ -46,9 +44,13 @@ func TestEndToEnd(t *testing.T) {
4644
t.Fatalf("Error wrapping files: %s", err)
4745
}
4846

47+
unWrappedFilePath := filepath.Join(
48+
bootdir,
49+
fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID),
50+
)
4951
// Client:
5052
// Unwrap files
51-
err = unWrapFile(bootdir, nodeID)
53+
err = unWrapFile(bootdir, nodeID, bootdir, unWrappedFilePath)
5254
if err != nil {
5355
t.Fatalf("Error unwrapping response: %s", err)
5456
}

cmd/bootstrap/transit/cmd/flags.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ var (
1111
flagTimeout time.Duration
1212
flagConcurrency int64
1313

14-
flagWrapID string // wrap ID
15-
flagVoteFile string
16-
flagNodeID string
17-
flagOutputDir string
14+
flagWrapID string // wrap ID
15+
flagVoteFile string
16+
flagVoteFilePath string
17+
flagNodeID string
18+
flagOutputDir string
1819
)

cmd/bootstrap/transit/cmd/generate_root_block_vote.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ var generateVoteCmd = &cobra.Command{
2626

2727
func init() {
2828
rootCmd.AddCommand(generateVoteCmd)
29+
addGenerateVoteCmdFlags()
30+
}
31+
32+
func addGenerateVoteCmdFlags() {
33+
generateVoteCmd.Flags().StringVarP(&flagOutputDir, "outputDir", "o", "", "ouput directory for vote files; if not set defaults to bootstrap directory")
2934
}
3035

3136
func generateVote(c *cobra.Command, args []string) {
@@ -47,8 +52,13 @@ func generateVote(c *cobra.Command, args []string) {
4752
}
4853

4954
// load DKG private key
50-
path := fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID)
51-
data, err := io.ReadFile(filepath.Join(flagBootDir, path))
55+
path := filepath.Join(flagBootDir, fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID))
56+
// If output directory is specified, use it for the root-block.json
57+
if flagOutputDir != "" {
58+
path = filepath.Join(flagOutputDir, bootstrap.FilenameRandomBeaconPriv)
59+
}
60+
61+
data, err := io.ReadFile(path)
5262
if err != nil {
5363
log.Fatal().Err(err).Msg("could not read DKG private key file")
5464
}
@@ -78,6 +88,12 @@ func generateVote(c *cobra.Command, args []string) {
7888
signer := verification.NewCombinedSigner(me, beaconKeyStore)
7989

8090
path = filepath.Join(flagBootDir, bootstrap.PathRootBlockData)
91+
92+
// If output directory is specified, use it for the root-block.json
93+
if flagOutputDir != "" {
94+
path = filepath.Join(flagOutputDir, "root-block.json")
95+
}
96+
8197
data, err = io.ReadFile(path)
8298
if err != nil {
8399
log.Fatal().Err(err).Msg("could not read root block file")
@@ -96,7 +112,15 @@ func generateVote(c *cobra.Command, args []string) {
96112

97113
voteFile := fmt.Sprintf(bootstrap.PathNodeRootBlockVote, nodeID)
98114

99-
if err = io.WriteJSON(filepath.Join(flagBootDir, voteFile), vote); err != nil {
115+
// By default, use the bootstrap directory for storing the vote file
116+
voteFilePath := filepath.Join(flagBootDir, voteFile)
117+
118+
// If output directory is specified, use it for the vote file path
119+
if flagOutputDir != "" {
120+
voteFilePath = filepath.Join(flagOutputDir, "root-block-vote.json")
121+
}
122+
123+
if err = io.WriteJSON(voteFilePath, vote); err != nil {
100124
log.Fatal().Err(err).Msg("could not write vote to file")
101125
}
102126

cmd/bootstrap/transit/cmd/pull.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/onflow/flow-go/cmd/bootstrap/gcs"
1717
"github.com/onflow/flow-go/cmd/bootstrap/utils"
18+
"github.com/onflow/flow-go/model/bootstrap"
1819
model "github.com/onflow/flow-go/model/bootstrap"
1920
"github.com/onflow/flow-go/model/flow"
2021
)
@@ -156,7 +157,8 @@ func pull(cmd *cobra.Command, args []string) {
156157

157158
// unwrap consensus node role files
158159
if role == flow.RoleConsensus {
159-
err = unWrapFile(flagBootDir, nodeID)
160+
unWrappedFilePath := filepath.Join(flagBootDir, fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID))
161+
err = unWrapFile(flagBootDir, nodeID, flagBootDir, unWrappedFilePath)
160162
if err != nil {
161163
log.Fatal().Err(err).Msg("failed to pull")
162164
}

cmd/bootstrap/transit/cmd/pull_root_block.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func init() {
2626
func addPullRootBlockCmdFlags() {
2727
pullRootBlockCmd.Flags().StringVarP(&flagToken, "token", "t", "", "token provided by the Flow team to access the Transit server")
2828
pullRootBlockCmd.Flags().StringVarP(&flagBucketName, "bucket-name", "g", "flow-genesis-bootstrap", `bucket for pulling root block`)
29+
pullRootBlockCmd.Flags().StringVarP(&flagOutputDir, "outputDir", "o", "", "output directory for root block file; if not set defaults to bootstrap directory")
2930
_ = pullRootBlockCmd.MarkFlagRequired("token")
3031
}
3132

@@ -51,28 +52,45 @@ func pullRootBlock(c *cobra.Command, args []string) {
5152
log.Info().Msg("downloading root block")
5253

5354
rootBlockFile := filepath.Join(flagToken, bootstrap.PathRootBlockData)
54-
fullOutpath := filepath.Join(flagBootDir, bootstrap.PathRootBlockData)
55+
fullRootBlockPath := filepath.Join(flagBootDir, bootstrap.PathRootBlockData)
56+
if flagOutputDir != "" {
57+
fullRootBlockPath = filepath.Join(flagOutputDir, "root-block.json")
58+
}
5559

56-
log.Info().Str("source", rootBlockFile).Str("dest", fullOutpath).Msgf("downloading root block file from transit servers")
57-
err = bucket.DownloadFile(ctx, client, fullOutpath, rootBlockFile)
60+
log.Info().Str("source", rootBlockFile).Str("dest", fullRootBlockPath).Msgf("downloading root block file from transit servers")
61+
err = bucket.DownloadFile(ctx, client, fullRootBlockPath, rootBlockFile)
5862
if err != nil {
5963
log.Fatal().Err(err).Msgf("could not download google bucket file")
6064
}
6165

62-
objectName := filepath.Join(flagToken, fmt.Sprintf(FilenameRandomBeaconCipher, nodeID))
63-
fullOutpath = filepath.Join(flagBootDir, filepath.Base(objectName))
66+
log.Info().Msg("successfully downloaded root block ")
6467

65-
log.Info().Msgf("downloading random beacon key: %s", objectName)
68+
objectName := filepath.Join(flagToken, fmt.Sprintf(FilenameRandomBeaconCipher, nodeID))
6669

67-
err = bucket.DownloadFile(ctx, client, fullOutpath, objectName)
68-
if err != nil {
69-
log.Fatal().Err(err).Msg("could not download file from google bucket")
70+
// By default, use the bootstrap directory for the random beacon download & unwrapping
71+
fullRandomBeaconPath := filepath.Join(flagBootDir, filepath.Base(objectName))
72+
unWrappedRandomBeaconPath := filepath.Join(
73+
flagBootDir,
74+
fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID),
75+
)
76+
77+
// If output directory is specified, use it for the random beacon path
78+
// this will set the path used to download the random beacon file and unwrap it
79+
if flagOutputDir != "" {
80+
fullRandomBeaconPath = filepath.Join(flagOutputDir, filepath.Base(objectName))
81+
unWrappedRandomBeaconPath = filepath.Join(flagOutputDir, bootstrap.FilenameRandomBeaconPriv)
7082
}
7183

72-
err = unWrapFile(flagBootDir, nodeID)
84+
log.Info().Msgf("downloading random beacon key: %s", objectName)
85+
86+
err = bucket.DownloadFile(ctx, client, fullRandomBeaconPath, objectName)
7387
if err != nil {
74-
log.Fatal().Err(err).Msg("could not unwrap random beacon file")
88+
log.Fatal().Err(err).Msg("could not download random beacon key file from google bucket")
89+
} else {
90+
err = unWrapFile(flagBootDir, nodeID, flagOutputDir, unWrappedRandomBeaconPath)
91+
if err != nil {
92+
log.Fatal().Err(err).Msg("could not unwrap random beacon file")
93+
}
94+
log.Info().Msg("successfully downloaded and unwrapped random beacon private key")
7595
}
76-
77-
log.Info().Msg("successfully downloaded root block and random beacon key")
7896
}

cmd/bootstrap/transit/cmd/push_root_block_vote.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ func addPushVoteCmdFlags() {
2828
defaultVoteFilePath := fmt.Sprintf(bootstrap.PathNodeRootBlockVote, "<node_id>")
2929
pushVoteCmd.Flags().StringVarP(&flagToken, "token", "t", "", "token provided by the Flow team to access the Transit server")
3030
pushVoteCmd.Flags().StringVarP(&flagVoteFile, "vote-file", "v", "", fmt.Sprintf("path under bootstrap directory of the vote file to upload (default: %s)", defaultVoteFilePath))
31+
pushVoteCmd.Flags().StringVarP(&flagVoteFilePath, "vote-file-dir", "d", "", "directory for vote file to upload, ONLY for vote files outside the bootstrap directory")
3132
pushVoteCmd.Flags().StringVarP(&flagBucketName, "bucket-name", "g", "flow-genesis-bootstrap", `bucket for pushing root block vote files`)
3233

3334
_ = pushVoteCmd.MarkFlagRequired("token")
35+
pushVoteCmd.MarkFlagsMutuallyExclusive("vote-file", "vote-file-dir")
3436
}
3537

3638
func pushVote(c *cobra.Command, args []string) {
@@ -45,12 +47,22 @@ func pushVote(c *cobra.Command, args []string) {
4547
}
4648

4749
voteFile := flagVoteFile
50+
51+
// If --vote-file-dir is not specified, use the bootstrap directory
52+
voteFilePath := filepath.Join(flagBootDir, voteFile)
53+
54+
// if --vote-file is not specified, use default file name within bootstrap directory
4855
if voteFile == "" {
4956
voteFile = fmt.Sprintf(bootstrap.PathNodeRootBlockVote, nodeID)
57+
voteFilePath = filepath.Join(flagBootDir, voteFile)
58+
}
59+
60+
// If vote-file-dir is specified, use it to construct the full path to the vote file (with default file name)
61+
if flagVoteFilePath != "" {
62+
voteFilePath = filepath.Join(flagVoteFilePath, "root-block-vote.json")
5063
}
5164

5265
destination := filepath.Join(flagToken, fmt.Sprintf(bootstrap.FilenameRootBlockVote, nodeID))
53-
source := filepath.Join(flagBootDir, voteFile)
5466

5567
log.Info().Msg("pushing root block vote")
5668

@@ -67,7 +79,7 @@ func pushVote(c *cobra.Command, args []string) {
6779
}
6880
defer client.Close()
6981

70-
err = bucket.UploadFile(ctx, client, destination, source)
82+
err = bucket.UploadFile(ctx, client, destination, voteFilePath)
7183
if err != nil {
7284
log.Fatal().Err(err).Msg("failed to upload vote file")
7385
}

cmd/bootstrap/transit/cmd/utils.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ func getFileSHA256(file string) (string, error) {
7575

7676
// moveFile moves a file from source to destination where src and dst are full paths including the filename
7777
func moveFile(src, dst string) error {
78-
7978
// check if source file exist
8079
if !ioutils.FileExists(src) {
8180
return fmt.Errorf("file not found: %s", src)
@@ -153,14 +152,12 @@ func moveFile(src, dst string) error {
153152
return nil
154153
}
155154

156-
func unWrapFile(bootDir string, nodeID string) error {
157-
155+
func unWrapFile(bootDir, nodeID, cipherTextDir, plaintextPath string) error {
158156
log.Info().Msg("decrypting Random Beacon key")
159157

160158
pubKeyPath := filepath.Join(bootDir, fmt.Sprintf(FilenameTransitKeyPub, nodeID))
161159
privKeyPath := filepath.Join(bootDir, fmt.Sprintf(FilenameTransitKeyPriv, nodeID))
162-
ciphertextPath := filepath.Join(bootDir, fmt.Sprintf(FilenameRandomBeaconCipher, nodeID))
163-
plaintextPath := filepath.Join(bootDir, fmt.Sprintf(bootstrap.PathRandomBeaconPriv, nodeID))
160+
ciphertextPath := filepath.Join(cipherTextDir, fmt.Sprintf(FilenameRandomBeaconCipher, nodeID))
164161

165162
ciphertext, err := ioutils.ReadFile(ciphertextPath)
166163
if err != nil {
@@ -231,7 +228,6 @@ func wrapFile(bootDir string, nodeID string) error {
231228

232229
// generateKeys creates the transit keypair and writes them to disk for later
233230
func generateKeys(bootDir string, nodeID string) error {
234-
235231
privPath := filepath.Join(bootDir, fmt.Sprintf(FilenameTransitKeyPriv, nodeID))
236232
pubPath := filepath.Join(bootDir, fmt.Sprintf(FilenameTransitKeyPub, nodeID))
237233

cmd/util/ledger/migrations/add_key_migration.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ func (m *AddKeyMigration) MigrateAccount(
149149

150150
flowAddress := flow.ConvertAddress(address)
151151

152-
keyIndex, err := migrationRuntime.Accounts.GetPublicKeyCount(flowAddress)
152+
keyIndex, err := migrationRuntime.Accounts.GetAccountPublicKeyCount(flowAddress)
153153
if err != nil {
154154
return fmt.Errorf("failed to get public key count: %w", err)
155155
}
156156

157-
err = migrationRuntime.Accounts.AppendPublicKey(flowAddress, key)
157+
err = migrationRuntime.Accounts.AppendAccountPublicKey(flowAddress, key)
158158
if err != nil {
159159
return fmt.Errorf("failed to append public key: %w", err)
160160
}

0 commit comments

Comments
 (0)