mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-16 17:07:35 +00:00
Use an actual, cryptographically-binding ID for batches in SignId
The intent system expected one.
This commit is contained in:
parent
61418b4e9f
commit
67109c648c
2 changed files with 49 additions and 18 deletions
|
@ -4,6 +4,7 @@ use std::collections::{VecDeque, HashMap};
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
|
|
||||||
use scale::Encode;
|
use scale::Encode;
|
||||||
|
use transcript::{Transcript, RecommendedTranscript};
|
||||||
|
|
||||||
use ciphersuite::group::GroupEncoding;
|
use ciphersuite::group::GroupEncoding;
|
||||||
use frost::{
|
use frost::{
|
||||||
|
@ -36,11 +37,21 @@ impl<D: Db> SubstrateSignerDb<D> {
|
||||||
D::key(b"SUBSTRATE_SIGNER", dst, key)
|
D::key(b"SUBSTRATE_SIGNER", dst, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sign_id_key(id: u32) -> Vec<u8> {
|
||||||
|
Self::sign_key(b"sign_id", id.to_le_bytes())
|
||||||
|
}
|
||||||
|
fn save_sign_id(txn: &mut D::Transaction<'_>, id: u32, sign_id: [u8; 32]) {
|
||||||
|
txn.put(Self::sign_id_key(id), sign_id);
|
||||||
|
}
|
||||||
|
fn sign_id(txn: &mut D::Transaction<'_>, id: u32) -> [u8; 32] {
|
||||||
|
txn.get(Self::sign_id_key(id)).expect("completing a batch we never started").try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn completed_key(id: [u8; 32]) -> Vec<u8> {
|
fn completed_key(id: [u8; 32]) -> Vec<u8> {
|
||||||
Self::sign_key(b"completed", id)
|
Self::sign_key(b"completed", id)
|
||||||
}
|
}
|
||||||
fn complete(txn: &mut D::Transaction<'_>, id: [u8; 32]) {
|
fn complete(txn: &mut D::Transaction<'_>, id: [u8; 32]) {
|
||||||
txn.put(Self::completed_key(id), [1]);
|
txn.put(Self::completed_key(id), []);
|
||||||
}
|
}
|
||||||
fn completed<G: Get>(getter: &G, id: [u8; 32]) -> bool {
|
fn completed<G: Get>(getter: &G, id: [u8; 32]) -> bool {
|
||||||
getter.get(Self::completed_key(id)).is_some()
|
getter.get(Self::completed_key(id)).is_some()
|
||||||
|
@ -203,9 +214,27 @@ impl<D: Db> SubstrateSigner<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sign(&mut self, txn: &mut D::Transaction<'_>, batch: Batch) {
|
pub async fn sign(&mut self, txn: &mut D::Transaction<'_>, batch: Batch) {
|
||||||
// Use the batch id as the ID
|
// Generate a unique ID to sign with
|
||||||
let mut id = [0u8; 32];
|
let id = {
|
||||||
id[.. 4].copy_from_slice(&batch.id.to_le_bytes());
|
// TODO: Add this to in-instructions primitives
|
||||||
|
let mut transcript = RecommendedTranscript::new(b"Serai Processor Batch ID");
|
||||||
|
transcript.domain_separate(b"header");
|
||||||
|
transcript.append_message(b"network", batch.network.encode());
|
||||||
|
transcript.append_message(b"id", batch.id.to_le_bytes());
|
||||||
|
transcript.append_message(b"block", batch.block.0);
|
||||||
|
|
||||||
|
transcript.domain_separate(b"instructions");
|
||||||
|
for instruction in &batch.instructions {
|
||||||
|
// TODO: Either properly transcript this or simply encode the entire batch (since SCALE is
|
||||||
|
// canonical)
|
||||||
|
transcript.append_message(b"instruction", instruction.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = [0; 32];
|
||||||
|
res.copy_from_slice(&transcript.challenge(b"id")[.. 32]);
|
||||||
|
res
|
||||||
|
};
|
||||||
|
SubstrateSignerDb::<D>::save_sign_id(txn, batch.id, id);
|
||||||
|
|
||||||
if SubstrateSignerDb::<D>::completed(txn, id) {
|
if SubstrateSignerDb::<D>::completed(txn, id) {
|
||||||
debug!("Sign batch order for ID we've already completed signing");
|
debug!("Sign batch order for ID we've already completed signing");
|
||||||
|
@ -336,19 +365,20 @@ impl<D: Db> SubstrateSigner<D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn batch_signed(&mut self, txn: &mut D::Transaction<'_>, batch_id: u32) {
|
pub fn batch_signed(&mut self, txn: &mut D::Transaction<'_>, id: u32) {
|
||||||
// Convert into 32-byte ID
|
// Safe since SubstrateSigner won't be told of the completion until the Scanner recognizes the
|
||||||
// TODO: Add a BatchSignId so we don't have this inefficiency
|
// block behind it, which will trigger starting the Batch
|
||||||
let mut id = [0u8; 32];
|
// TODO: There is a race condition between the Scanner recognizing the block and the Batch
|
||||||
id[.. 4].copy_from_slice(&batch_id.to_le_bytes());
|
// having signing started
|
||||||
|
let sign_id = SubstrateSignerDb::<D>::sign_id(txn, id);
|
||||||
|
|
||||||
// Stop trying to sign for this batch
|
// Stop trying to sign for this batch
|
||||||
SubstrateSignerDb::<D>::complete(txn, id);
|
SubstrateSignerDb::<D>::complete(txn, sign_id);
|
||||||
|
|
||||||
self.signable.remove(&id);
|
self.signable.remove(&sign_id);
|
||||||
self.attempt.remove(&id);
|
self.attempt.remove(&sign_id);
|
||||||
self.preprocessing.remove(&id);
|
self.preprocessing.remove(&sign_id);
|
||||||
self.signing.remove(&id);
|
self.signing.remove(&sign_id);
|
||||||
|
|
||||||
// This doesn't emit SignedBatch because it doesn't have access to the SignedBatch
|
// This doesn't emit SignedBatch because it doesn't have access to the SignedBatch
|
||||||
// This function is expected to only be called once Substrate acknowledges this block,
|
// This function is expected to only be called once Substrate acknowledges this block,
|
||||||
|
|
|
@ -25,11 +25,9 @@ async fn test_substrate_signer() {
|
||||||
let participant_one = Participant::new(1).unwrap();
|
let participant_one = Participant::new(1).unwrap();
|
||||||
|
|
||||||
let id: u32 = 5;
|
let id: u32 = 5;
|
||||||
let mut id_arr = [0u8; 32];
|
|
||||||
id_arr[.. 4].copy_from_slice(&id.to_le_bytes());
|
|
||||||
let block = BlockHash([0xaa; 32]);
|
let block = BlockHash([0xaa; 32]);
|
||||||
let actual_id =
|
let mut actual_id =
|
||||||
SignId { key: keys[&participant_one].group_key().to_bytes().to_vec(), id: id_arr, attempt: 0 };
|
SignId { key: keys[&participant_one].group_key().to_bytes().to_vec(), id: [0; 32], attempt: 0 };
|
||||||
|
|
||||||
let batch = Batch {
|
let batch = Batch {
|
||||||
network: NetworkId::Monero,
|
network: NetworkId::Monero,
|
||||||
|
@ -88,6 +86,9 @@ async fn test_substrate_signer() {
|
||||||
preprocess,
|
preprocess,
|
||||||
}) = signers.get_mut(&i).unwrap().events.pop_front().unwrap()
|
}) = signers.get_mut(&i).unwrap().events.pop_front().unwrap()
|
||||||
{
|
{
|
||||||
|
if actual_id.id == [0; 32] {
|
||||||
|
actual_id.id = id.id;
|
||||||
|
}
|
||||||
assert_eq!(id, actual_id);
|
assert_eq!(id, actual_id);
|
||||||
assert_eq!(batch_block, block);
|
assert_eq!(batch_block, block);
|
||||||
if signing_set.contains(&i) {
|
if signing_set.contains(&i) {
|
||||||
|
|
Loading…
Reference in a new issue