-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
dkg.rs
133 lines (120 loc) · 4.79 KB
/
dkg.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0
use crate::{
aptos_vm::get_or_vm_startup_failure,
errors::expect_only_successful_execution,
move_vm_ext::{AptosMoveResolver, SessionId},
system_module_names::{FINISH_WITH_DKG_RESULT, RECONFIGURATION_WITH_DKG_MODULE},
validator_txns::dkg::{
ExecutionFailure::{Expected, Unexpected},
ExpectedFailure::*,
},
AptosVM,
};
use aptos_types::{
dkg::{DKGState, DKGTrait, DKGTranscript, DefaultDKG},
fee_statement::FeeStatement,
move_utils::as_move_value::AsMoveValue,
on_chain_config::{ConfigurationResource, OnChainConfig},
transaction::{ExecutionStatus, TransactionStatus},
};
use aptos_vm_logging::log_schema::AdapterLogSchema;
use aptos_vm_types::output::VMOutput;
use move_core_types::{
account_address::AccountAddress,
value::{serialize_values, MoveValue},
vm_status::{AbortLocation, StatusCode, VMStatus},
};
use move_vm_types::gas::UnmeteredGasMeter;
#[derive(Debug)]
enum ExpectedFailure {
// Move equivalent: `errors::invalid_argument(*)`
EpochNotCurrent = 0x10001,
TranscriptDeserializationFailed = 0x10002,
TranscriptVerificationFailed = 0x10003,
// Move equivalent: `errors::invalid_state(*)`
MissingResourceDKGState = 0x30001,
MissingResourceInprogressDKGSession = 0x30002,
MissingResourceConfiguration = 0x30003,
}
enum ExecutionFailure {
Expected(ExpectedFailure),
Unexpected(VMStatus),
}
impl AptosVM {
pub(crate) fn process_dkg_result(
&self,
resolver: &impl AptosMoveResolver,
log_context: &AdapterLogSchema,
session_id: SessionId,
dkg_transcript: DKGTranscript,
) -> Result<(VMStatus, VMOutput), VMStatus> {
match self.process_dkg_result_inner(resolver, log_context, session_id, dkg_transcript) {
Ok((vm_status, vm_output)) => Ok((vm_status, vm_output)),
Err(Expected(failure)) => {
// Pretend we are inside Move, and expected failures are like Move aborts.
Ok((
VMStatus::MoveAbort(AbortLocation::Script, failure as u64),
VMOutput::empty_with_status(TransactionStatus::Discard(StatusCode::ABORTED)),
))
},
Err(Unexpected(vm_status)) => Err(vm_status),
}
}
fn process_dkg_result_inner(
&self,
resolver: &impl AptosMoveResolver,
log_context: &AdapterLogSchema,
session_id: SessionId,
dkg_node: DKGTranscript,
) -> Result<(VMStatus, VMOutput), ExecutionFailure> {
let dkg_state = OnChainConfig::fetch_config(resolver)
.ok_or_else(|| Expected(MissingResourceDKGState))?;
let config_resource = ConfigurationResource::fetch_config(resolver)
.ok_or_else(|| Expected(MissingResourceConfiguration))?;
let DKGState { in_progress, .. } = dkg_state;
let in_progress_session_state =
in_progress.ok_or_else(|| Expected(MissingResourceInprogressDKGSession))?;
// Check epoch number.
if dkg_node.metadata.epoch != config_resource.epoch() {
return Err(Expected(EpochNotCurrent));
}
// Deserialize transcript and verify it.
let pub_params = DefaultDKG::new_public_params(&in_progress_session_state.metadata);
let transcript = bcs::from_bytes::<<DefaultDKG as DKGTrait>::Transcript>(
dkg_node.transcript_bytes.as_slice(),
)
.map_err(|_| Expected(TranscriptDeserializationFailed))?;
DefaultDKG::verify_transcript(&pub_params, &transcript)
.map_err(|_| Expected(TranscriptVerificationFailed))?;
// All check passed, invoke VM to publish DKG result on chain.
let mut gas_meter = UnmeteredGasMeter;
let mut session = self.new_session(resolver, session_id);
let args = vec![
MoveValue::Signer(AccountAddress::ONE),
dkg_node.transcript_bytes.as_move_value(),
];
session
.execute_function_bypass_visibility(
&RECONFIGURATION_WITH_DKG_MODULE,
FINISH_WITH_DKG_RESULT,
vec![],
serialize_values(&args),
&mut gas_meter,
)
.map_err(|e| {
expect_only_successful_execution(e, FINISH_WITH_DKG_RESULT.as_str(), log_context)
})
.map_err(|r| Unexpected(r.unwrap_err()))?;
let output = crate::aptos_vm::get_system_transaction_output(
session,
FeeStatement::zero(),
ExecutionStatus::Success,
&get_or_vm_startup_failure(&self.storage_gas_params, log_context)
.map_err(Unexpected)?
.change_set_configs,
)
.map_err(Unexpected)?;
Ok((VMStatus::Executed, output))
}
}