Skip to content

Commit 8c55066

Browse files
authored
Merge branch 'master' into update_azle_template
2 parents 89d0298 + 0ca8ca0 commit 8c55066

File tree

6 files changed

+82
-9
lines changed

6 files changed

+82
-9
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
# UNRELEASED
44

5+
### fix: `dfx deploy --by-proposal` no longer sends chunk data in ProposeCommitBatch
6+
7+
Recently we made `dfx deploy` include some chunk data in CommitBatch, in order to streamline
8+
deploys for smaller projects. `dfx deploy` splits up larger change lists and submits them in
9+
smaller batches, in order to remain within message and compute limits.
10+
11+
This change also applied to `dfx deploy --by-proposal`, which submits all changes in a single
12+
message. This made it more likely that `dfx deploy --by-proposal` will fail due to exceeding
13+
message limits.
14+
15+
This fix makes it so `dfx deploy --by-proposal` never includes this chunk data in
16+
ProposeCommitBatch, which will allow for more changes before hitting message limits.
17+
518
### feat: `dfx start --pocketic` supports `--force` and shared networks.
619

720
`dfx start --pocketic` is now compatible with `--force` and shared networks.

e2e/tests-dfx/assetscanister.bash

+29
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,35 @@ check_permission_failure() {
187187
assert_contains "cache-control: max-age=888"
188188
}
189189

190+
@test "deploy --by-proposal lots of small assets should not overflow message limits" {
191+
assert_command dfx identity new controller --storage-mode plaintext
192+
assert_command dfx identity new prepare --storage-mode plaintext
193+
assert_command dfx identity new commit --storage-mode plaintext
194+
assert_command dfx identity use anonymous
195+
196+
CONTROLLER_PRINCIPAL=$(dfx identity get-principal --identity controller)
197+
PREPARE_PRINCIPAL=$(dfx identity get-principal --identity prepare)
198+
COMMIT_PRINCIPAL=$(dfx identity get-principal --identity commit)
199+
200+
dfx_start
201+
assert_command dfx deploy --identity controller
202+
203+
assert_command dfx canister call e2e_project_frontend grant_permission "(record { to_principal=principal \"$PREPARE_PRINCIPAL\"; permission = variant { Prepare }; })" --identity controller
204+
assert_command dfx canister call e2e_project_frontend grant_permission "(record { to_principal=principal \"$COMMIT_PRINCIPAL\"; permission = variant { Commit }; })" --identity controller
205+
206+
for a in $(seq 1 1400); do
207+
# 1400 files * ~1200 header bytes: 1,680,000 bytes
208+
# 1400 files * 650 content bytes = 910,000 bytes: small enough that chunk uploader won't upload before finalize
209+
# commit batch without content: 1,978,870 bytes
210+
# commit batch with content: 2,889,392 bytes
211+
# change finalize_upload to always pass MAX_CHUNK_SIZE/2 to see this fail
212+
dd if=/dev/random of=src/e2e_project_frontend/assets/"$a" bs=650 count=1
213+
done
214+
215+
assert_command dfx deploy e2e_project_frontend --by-proposal --identity prepare
216+
assert_match "Proposed commit of batch 2 with evidence [0-9a-z]*. Either commit it by proposal, or delete it."
217+
}
218+
190219
@test "deploy --by-proposal all assets" {
191220
assert_command dfx identity new controller --storage-mode plaintext
192221
assert_command dfx identity new prepare --storage-mode plaintext

src/canisters/frontend/ic-asset/src/batch_upload/plumbing.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ pub(crate) struct ProjectAsset {
5050
pub(crate) encodings: HashMap<String, ProjectAssetEncoding>,
5151
}
5252

53+
#[derive(Debug, PartialEq)]
54+
pub enum Mode {
55+
ByProposal,
56+
NormalDeploy,
57+
}
58+
5359
type IdMapping = BTreeMap<usize, Nat>;
5460
type UploadQueue = Vec<(usize, Vec<u8>)>;
5561
pub(crate) struct ChunkUploader<'agent> {
@@ -108,9 +114,17 @@ impl<'agent> ChunkUploader<'agent> {
108114
pub(crate) async fn finalize_upload(
109115
&self,
110116
semaphores: &Semaphores,
117+
mode: Mode,
111118
) -> Result<(), CreateChunkError> {
112-
// Crude estimate: If `MAX_CHUNK_SIZE / 2` bytes are added as data to the `commit_batch` args the message won't be above the message size limit.
113-
self.upload_chunks(MAX_CHUNK_SIZE / 2, semaphores).await
119+
let max_retained_bytes = if mode == Mode::ByProposal {
120+
// Never add data to the commit_batch args, because they have to fit in a single call.
121+
0
122+
} else {
123+
// Crude estimate: If `MAX_CHUNK_SIZE / 2` bytes are added as data to the `commit_batch` args the message won't be above the message size limit.
124+
MAX_CHUNK_SIZE / 2
125+
};
126+
127+
self.upload_chunks(max_retained_bytes, semaphores).await
114128
}
115129

116130
pub(crate) fn bytes(&self) -> usize {
@@ -412,6 +426,7 @@ pub(crate) async fn make_project_assets(
412426
chunk_upload_target: Option<&ChunkUploader<'_>>,
413427
asset_descriptors: Vec<AssetDescriptor>,
414428
canister_assets: &HashMap<String, AssetDetails>,
429+
mode: Mode,
415430
logger: &Logger,
416431
) -> Result<HashMap<String, ProjectAsset>, CreateProjectAssetError> {
417432
let semaphores = Semaphores::new();
@@ -430,11 +445,14 @@ pub(crate) async fn make_project_assets(
430445
.collect();
431446
let project_assets = try_join_all(project_asset_futures).await?;
432447
if let Some(uploader) = chunk_upload_target {
433-
uploader.finalize_upload(&semaphores).await.map_err(|err| {
434-
CreateProjectAssetError::CreateEncodingError(CreateEncodingError::CreateChunkFailed(
435-
err,
436-
))
437-
})?;
448+
uploader
449+
.finalize_upload(&semaphores, mode)
450+
.await
451+
.map_err(|err| {
452+
CreateProjectAssetError::CreateEncodingError(
453+
CreateEncodingError::CreateChunkFailed(err),
454+
)
455+
})?;
438456
}
439457

440458
let mut hm = HashMap::new();

src/canisters/frontend/ic-asset/src/evidence/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,14 @@ pub async fn compute_evidence(
5555
logger,
5656
"Computing evidence for batch operations for assets in the project.",
5757
);
58-
let project_assets =
59-
make_project_assets(None, asset_descriptors, &canister_assets, logger).await?;
58+
let project_assets = make_project_assets(
59+
None,
60+
asset_descriptors,
61+
&canister_assets,
62+
crate::batch_upload::plumbing::Mode::ByProposal,
63+
logger,
64+
)
65+
.await?;
6066

6167
let mut operations = assemble_batch_operations(
6268
None,

src/canisters/frontend/ic-asset/src/sync.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::asset::config::{
33
};
44
use crate::batch_upload::operations::BATCH_UPLOAD_API_VERSION;
55
use crate::batch_upload::plumbing::ChunkUploader;
6+
use crate::batch_upload::plumbing::Mode::{ByProposal, NormalDeploy};
67
use crate::batch_upload::{
78
self,
89
operations::AssetDeletionReason,
@@ -48,6 +49,7 @@ pub async fn upload_content_and_assemble_sync_operations(
4849
canister_api_version: u16,
4950
dirs: &[&Path],
5051
no_delete: bool,
52+
mode: batch_upload::plumbing::Mode,
5153
logger: &Logger,
5254
) -> Result<CommitBatchArguments, UploadContentError> {
5355
let asset_descriptors = gather_asset_descriptors(dirs, logger)?;
@@ -82,6 +84,7 @@ pub async fn upload_content_and_assemble_sync_operations(
8284
Some(&chunk_uploader),
8385
asset_descriptors,
8486
&canister_assets,
87+
mode,
8588
logger,
8689
)
8790
.await
@@ -133,6 +136,7 @@ pub async fn sync(
133136
canister_api_version,
134137
dirs,
135138
no_delete,
139+
NormalDeploy,
136140
logger,
137141
)
138142
.await?;
@@ -214,6 +218,7 @@ pub async fn prepare_sync_for_proposal(
214218
canister_api_version,
215219
dirs,
216220
false,
221+
ByProposal,
217222
logger,
218223
)
219224
.await?;

src/canisters/frontend/ic-asset/src/upload.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::asset::config::AssetConfig;
22
use crate::batch_upload::operations::BATCH_UPLOAD_API_VERSION;
3+
use crate::batch_upload::plumbing::Mode::NormalDeploy;
34
use crate::batch_upload::{
45
self,
56
operations::AssetDeletionReason,
@@ -49,6 +50,7 @@ pub async fn upload(
4950
Some(&chunk_upload_target),
5051
asset_descriptors,
5152
&canister_assets,
53+
NormalDeploy,
5254
logger,
5355
)
5456
.await?;

0 commit comments

Comments
 (0)