Module 0x1::decryption
This module provides a decryption key unique to every block. This resource is updated in every block prologue. The decryption key is the key used to decrypt the encrypted transactions in the block.
- Resource
PerBlockDecryptionKey - Resource
PerEpochEncryptionKey - Resource
PerBlockDecryptionKeyV2 - Function
initialize - Function
on_new_block - Function
on_new_block_v2 - Function
set_for_next_epoch - Function
on_new_epoch
use 0x1::config_buffer;
use 0x1::option;
use 0x1::system_addresses;
Resource PerBlockDecryptionKey
Decryption key unique to every block. This resource is updated in every block prologue.
Superseded by PerBlockDecryptionKeyV2: once that resource exists,
blocks run block_prologue_ext_v3 and only V2 is updated, so this
resource freezes at the last block of the legacy mode. Kept for
chains that predate the upgrade (testnet has committed blocks
updating it via block_prologue_ext_v2).
struct PerBlockDecryptionKey has drop, key
Fields
-
epoch: u64 -
round: u64 -
decryption_key: option::Option<vector<u8>>
Resource PerEpochEncryptionKey
Encryption key derived from the DKG result, valid for one epoch.
struct PerEpochEncryptionKey has drop, store, key
Fields
-
epoch: u64 -
encryption_key: option::Option<vector<u8>>
Resource PerBlockDecryptionKeyV2
PerBlockDecryptionKey plus the dense decryption-round tracking that
decouples trusted-setup capacity from the consensus round.
Its existence marks that round tracking is active: validators emit
BlockMetadataExt::V3 (updating this resource via
block_prologue_ext_v3) iff the resource exists at the epoch root.
Created at genesis on fresh chains and lazily in on_new_epoch on
upgraded chains.
Invariant: decryption_key.is_some() == decryption_round.is_some() —
both describe the current block and arrive paired from the prologue.
struct PerBlockDecryptionKeyV2 has drop, key
Fields
-
epoch: u64 -
block_round: u64 - Current block's consensus round.
-
decryption_key: option::Option<vector<u8>> -
Current block's decryption key.
none()when the block carried no encrypted transactions (or decryption failed). -
decryption_round: option::Option<u64> -
Current block's decryption round.
none()when the block did not produce a key. -
next_decryption_round: u64 -
Next decryption round any future key-producing block will consume.
Bumped by one each time a key block hits
on_new_block_v2. Reset to 0 on epoch boundaries.
Function initialize
Called during genesis initialization.
public fun initialize(framework: &signer)
Implementation
public fun initialize(framework: &signer) {
system_addresses::assert_aptos_framework(framework);
if (!exists<PerBlockDecryptionKey>(@aptos_framework)) {
move_to(
framework,
PerBlockDecryptionKey { epoch: 0, round: 0, decryption_key: option::none() }
);
};
if (!exists<PerEpochEncryptionKey>(@aptos_framework)) {
move_to(
framework,
PerEpochEncryptionKey { epoch: 0, encryption_key: option::none() }
);
};
if (!exists<PerBlockDecryptionKeyV2>(@aptos_framework)) {
move_to(
framework,
PerBlockDecryptionKeyV2 {
epoch: 0,
block_round: 0,
decryption_key: option::none(),
decryption_round: option::none(),
next_decryption_round: 0
}
);
}
}
Function on_new_block
Invoked in block prologues to update the block decryption key.
public(friend) fun on_new_block(vm: &signer, epoch: u64, round: u64, decryption_key_for_new_block: option::Option<vector<u8>>)
Implementation
public(friend) fun on_new_block(
vm: &signer,
epoch: u64,
round: u64,
decryption_key_for_new_block: Option<vector<u8>>
) acquires PerBlockDecryptionKey {
system_addresses::assert_vm(vm);
if (exists<PerBlockDecryptionKey>(@aptos_framework)) {
let decryption_key =
borrow_global_mut<PerBlockDecryptionKey>(@aptos_framework);
decryption_key.epoch = epoch;
decryption_key.round = round;
decryption_key.decryption_key = decryption_key_for_new_block;
}
}
Function on_new_block_v2
Invoked in block_prologue_ext_v3. block_round advances every
block; next_decryption_round is sticky and only bumps when the
pipeline sends a key (paired with the round it consumed).
public(friend) fun on_new_block_v2(vm: &signer, epoch: u64, round: u64, decryption_key_for_new_block: option::Option<vector<u8>>, decryption_round: option::Option<u64>)
Implementation
public(friend) fun on_new_block_v2(
vm: &signer,
epoch: u64,
round: u64,
decryption_key_for_new_block: Option<vector<u8>>,
decryption_round: Option<u64>
) acquires PerBlockDecryptionKeyV2 {
system_addresses::assert_vm(vm);
if (exists<PerBlockDecryptionKeyV2>(@aptos_framework)) {
let r = borrow_global_mut<PerBlockDecryptionKeyV2>(@aptos_framework);
r.epoch = epoch;
r.block_round = round;
r.decryption_key = decryption_key_for_new_block;
r.decryption_round = decryption_round;
if (option::is_some(&decryption_round)) {
r.next_decryption_round = *option::borrow(&decryption_round) + 1;
}
}
}
Function set_for_next_epoch
Buffer the encryption key for the next epoch.
public(friend) fun set_for_next_epoch(epoch: u64, encryption_key: vector<u8>)
Implementation
public(friend) fun set_for_next_epoch(epoch: u64, encryption_key: vector<u8>) {
config_buffer::upsert(PerEpochEncryptionKey {
epoch,
encryption_key: option::some(encryption_key)
});
}
Function on_new_epoch
Apply buffered PerEpochEncryptionKey and reset PerBlockDecryptionKeyV2, creating the latter on chains that predate it.
public(friend) fun on_new_epoch(framework: &signer, new_epoch: u64)
Implementation
public(friend) fun on_new_epoch(
framework: &signer, new_epoch: u64
) acquires PerEpochEncryptionKey, PerBlockDecryptionKeyV2 {
system_addresses::assert_aptos_framework(framework);
if (config_buffer::does_exist<PerEpochEncryptionKey>()) {
let new_key = config_buffer::extract_v2<PerEpochEncryptionKey>();
if (exists<PerEpochEncryptionKey>(@aptos_framework)) {
*borrow_global_mut<PerEpochEncryptionKey>(@aptos_framework) = new_key;
} else {
move_to(framework, new_key);
}
};
let fresh = PerBlockDecryptionKeyV2 {
epoch: new_epoch,
block_round: 0,
decryption_key: option::none(),
decryption_round: option::none(),
next_decryption_round: 0
};
if (exists<PerBlockDecryptionKeyV2>(@aptos_framework)) {
*borrow_global_mut<PerBlockDecryptionKeyV2>(@aptos_framework) = fresh;
} else {
move_to(framework, fresh);
}
}