diff --git a/coordinator/tributary-sdk/Cargo.toml b/coordinator/tributary-sdk/Cargo.toml index 219d3b49..65cd7bec 100644 --- a/coordinator/tributary-sdk/Cargo.toml +++ b/coordinator/tributary-sdk/Cargo.toml @@ -36,7 +36,7 @@ log = { version = "0.4", default-features = false, features = ["std"] } serai-db = { path = "../../common/db", version = "0.1" } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std", "derive"] } +borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } futures-util = { version = "0.3", default-features = false, features = ["std", "sink", "channel"] } futures-channel = { version = "0.3", default-features = false, features = ["std", "sink"] } tendermint = { package = "tendermint-machine", path = "./tendermint", version = "0.2" } diff --git a/coordinator/tributary-sdk/src/blockchain.rs b/coordinator/tributary-sdk/src/blockchain.rs index 682e8472..beec066e 100644 --- a/coordinator/tributary-sdk/src/blockchain.rs +++ b/coordinator/tributary-sdk/src/blockchain.rs @@ -5,7 +5,7 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite}; use serai_db::{Get, DbTxn, Db}; -use scale::Decode; +use borsh::BorshDeserialize; use tendermint::ext::{Network, Commit}; @@ -62,7 +62,7 @@ impl Blockchain { D::key( b"tributary_blockchain", b"next_nonce", - [genesis.as_ref(), signer.to_bytes().as_ref(), order].concat(), + [genesis.as_slice(), signer.to_bytes().as_slice(), order].concat(), ) } @@ -106,7 +106,7 @@ impl Blockchain { pub(crate) fn block_from_db(db: &D, genesis: [u8; 32], block: &[u8; 32]) -> Option> { db.get(Self::block_key(&genesis, block)) - .map(|bytes| Block::::read::<&[u8]>(&mut bytes.as_ref()).unwrap()) + .map(|bytes| Block::::read::<&[u8]>(&mut bytes.as_slice()).unwrap()) } pub(crate) fn commit_from_db(db: &D, genesis: [u8; 32], block: &[u8; 32]) -> Option> { @@ -166,7 +166,7 @@ impl Blockchain { // we must have a commit per valid hash let commit = Self::commit_from_db(db, genesis, &hash).unwrap(); // commit has to be valid if it is coming from our db - Some(Commit::::decode(&mut commit.as_ref()).unwrap()) + Some(Commit::::deserialize_reader(&mut commit.as_slice()).unwrap()) }; let unsigned_in_chain = |hash: [u8; 32]| db.get(Self::unsigned_included_key(&self.genesis, &hash)).is_some(); @@ -241,7 +241,7 @@ impl Blockchain { let commit = |block: u64| -> Option> { let commit = self.commit_by_block_number(block)?; // commit has to be valid if it is coming from our db - Some(Commit::::decode(&mut commit.as_ref()).unwrap()) + Some(Commit::::deserialize_reader(&mut commit.as_slice()).unwrap()) }; let mut txn_db = db.clone(); diff --git a/coordinator/tributary-sdk/src/lib.rs b/coordinator/tributary-sdk/src/lib.rs index 0f45482e..6cd3a5e5 100644 --- a/coordinator/tributary-sdk/src/lib.rs +++ b/coordinator/tributary-sdk/src/lib.rs @@ -3,10 +3,11 @@ use std::{sync::Arc, io}; use zeroize::Zeroizing; +use borsh::BorshDeserialize; + use ciphersuite::Ciphersuite; use dalek_ff_group::Ristretto; -use scale::Decode; use futures_channel::mpsc::UnboundedReceiver; use futures_util::{StreamExt, SinkExt}; use ::tendermint::{ @@ -177,7 +178,7 @@ impl Tributary { let block_number = BlockNumber(blockchain.block_number()); let start_time = if let Some(commit) = blockchain.commit(&blockchain.tip()) { - Commit::::decode(&mut commit.as_ref()).unwrap().end_time + Commit::::deserialize_reader(&mut commit.as_slice()).unwrap().end_time } else { start_time }; @@ -276,8 +277,8 @@ impl Tributary { } let block = TendermintBlock(block.serialize()); - let mut commit_ref = commit.as_ref(); - let Ok(commit) = Commit::>::decode(&mut commit_ref) else { + let mut commit_ref = commit.as_slice(); + let Ok(commit) = Commit::>::deserialize_reader(&mut commit_ref) else { log::error!("sent an invalidly serialized commit"); return false; }; @@ -327,7 +328,7 @@ impl Tributary { Some(&TENDERMINT_MESSAGE) => { let Ok(msg) = - SignedMessageFor::>::decode::<&[u8]>(&mut &msg[1 ..]) + SignedMessageFor::>::deserialize_reader(&mut &msg[1 ..]) else { log::error!("received invalid tendermint message"); return false; @@ -367,15 +368,17 @@ impl TributaryReader { Blockchain::::commit_from_db(&self.0, self.1, hash) } pub fn parsed_commit(&self, hash: &[u8; 32]) -> Option> { - self.commit(hash).map(|commit| Commit::::decode(&mut commit.as_ref()).unwrap()) + self + .commit(hash) + .map(|commit| Commit::::deserialize_reader(&mut commit.as_slice()).unwrap()) } pub fn block_after(&self, hash: &[u8; 32]) -> Option<[u8; 32]> { Blockchain::::block_after(&self.0, self.1, hash) } pub fn time_of_block(&self, hash: &[u8; 32]) -> Option { - self - .commit(hash) - .map(|commit| Commit::::decode(&mut commit.as_ref()).unwrap().end_time) + self.commit(hash).map(|commit| { + Commit::::deserialize_reader(&mut commit.as_slice()).unwrap().end_time + }) } pub fn locally_provided_txs_in_block(&self, hash: &[u8; 32], order: &str) -> bool { diff --git a/coordinator/tributary-sdk/src/tendermint/mod.rs b/coordinator/tributary-sdk/src/tendermint/mod.rs index 373aacff..c1bb607f 100644 --- a/coordinator/tributary-sdk/src/tendermint/mod.rs +++ b/coordinator/tributary-sdk/src/tendermint/mod.rs @@ -24,7 +24,7 @@ use schnorr::{ use serai_db::Db; -use scale::{Encode, Decode}; +use borsh::{BorshSerialize, BorshDeserialize}; use tendermint::{ SignedMessageFor, ext::{ @@ -249,7 +249,7 @@ impl Weights for Validators { } } -#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub struct TendermintBlock(pub Vec); impl BlockTrait for TendermintBlock { type Id = [u8; 32]; @@ -301,7 +301,7 @@ impl Network for TendermintNetwork fn broadcast(&mut self, msg: SignedMessageFor) -> impl Send + Future { async move { let mut to_broadcast = vec![TENDERMINT_MESSAGE]; - to_broadcast.extend(msg.encode()); + msg.serialize(&mut to_broadcast).unwrap(); self.p2p.broadcast(self.genesis, to_broadcast).await } } @@ -391,7 +391,7 @@ impl Network for TendermintNetwork return invalid_block(); }; - let encoded_commit = commit.encode(); + let encoded_commit = borsh::to_vec(&commit).unwrap(); loop { let block_res = self.blockchain.write().await.add_block::( &block, diff --git a/coordinator/tributary-sdk/src/tendermint/tx.rs b/coordinator/tributary-sdk/src/tendermint/tx.rs index 61d2e21a..016aaad8 100644 --- a/coordinator/tributary-sdk/src/tendermint/tx.rs +++ b/coordinator/tributary-sdk/src/tendermint/tx.rs @@ -1,6 +1,6 @@ use std::io; -use scale::{Encode, Decode, IoReader}; +use borsh::BorshDeserialize; use blake2::{Digest, Blake2s256}; @@ -27,14 +27,14 @@ pub enum TendermintTx { impl ReadWrite for TendermintTx { fn read(reader: &mut R) -> io::Result { - Evidence::decode(&mut IoReader(reader)) + Evidence::deserialize_reader(reader) .map(TendermintTx::SlashEvidence) .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid evidence format")) } fn write(&self, writer: &mut W) -> io::Result<()> { match self { - TendermintTx::SlashEvidence(ev) => writer.write_all(&ev.encode()), + TendermintTx::SlashEvidence(ev) => writer.write_all(&borsh::to_vec(&ev).unwrap()), } } } diff --git a/coordinator/tributary-sdk/src/tests/transaction/mod.rs b/coordinator/tributary-sdk/src/tests/transaction/mod.rs index 26fb0dac..ab897ab5 100644 --- a/coordinator/tributary-sdk/src/tests/transaction/mod.rs +++ b/coordinator/tributary-sdk/src/tests/transaction/mod.rs @@ -13,8 +13,6 @@ use ciphersuite::{ }; use schnorr::SchnorrSignature; -use scale::Encode; - use ::tendermint::{ ext::{Network, Signer as SignerTrait, SignatureScheme, BlockNumber, RoundNumber}, SignedMessageFor, DataFor, Message, SignedMessage, Data, Evidence, @@ -204,7 +202,7 @@ pub async fn signed_from_data( round: RoundNumber(round_number), data, }; - let sig = signer.sign(&msg.encode()).await; + let sig = signer.sign(&borsh::to_vec(&msg).unwrap()).await; SignedMessage { msg, sig } } @@ -217,5 +215,5 @@ pub async fn random_evidence_tx( let data = Data::Proposal(Some(RoundNumber(0)), b); let signer_id = signer.validator_id().await.unwrap(); let signed = signed_from_data::(signer, signer_id, 0, 0, data).await; - TendermintTx::SlashEvidence(Evidence::InvalidValidRound(signed.encode())) + TendermintTx::SlashEvidence(Evidence::InvalidValidRound(borsh::to_vec(&signed).unwrap())) } diff --git a/coordinator/tributary-sdk/src/tests/transaction/tendermint.rs b/coordinator/tributary-sdk/src/tests/transaction/tendermint.rs index ca7decc0..a40b0909 100644 --- a/coordinator/tributary-sdk/src/tests/transaction/tendermint.rs +++ b/coordinator/tributary-sdk/src/tests/transaction/tendermint.rs @@ -6,8 +6,6 @@ use rand::{RngCore, rngs::OsRng}; use dalek_ff_group::Ristretto; use ciphersuite::{Ciphersuite, group::ff::Field}; -use scale::Encode; - use tendermint::{ time::CanonicalInstant, round::RoundData, @@ -52,7 +50,10 @@ async fn invalid_valid_round() { async move { let data = Data::Proposal(valid_round, TendermintBlock(vec![])); let signed = signed_from_data::(signer.clone().into(), signer_id, 0, 0, data).await; - (signed.clone(), TendermintTx::SlashEvidence(Evidence::InvalidValidRound(signed.encode()))) + ( + signed.clone(), + TendermintTx::SlashEvidence(Evidence::InvalidValidRound(borsh::to_vec(&signed).unwrap())), + ) } }; @@ -70,7 +71,8 @@ async fn invalid_valid_round() { let mut random_sig = [0u8; 64]; OsRng.fill_bytes(&mut random_sig); signed.sig = random_sig; - let tx = TendermintTx::SlashEvidence(Evidence::InvalidValidRound(signed.encode())); + let tx = + TendermintTx::SlashEvidence(Evidence::InvalidValidRound(borsh::to_vec(&signed).unwrap())); // should fail assert!(verify_tendermint_tx::(&tx, &validators, commit).is_err()); @@ -90,7 +92,10 @@ async fn invalid_precommit_signature() { let signed = signed_from_data::(signer.clone().into(), signer_id, 1, 0, Data::Precommit(precommit)) .await; - (signed.clone(), TendermintTx::SlashEvidence(Evidence::InvalidPrecommit(signed.encode()))) + ( + signed.clone(), + TendermintTx::SlashEvidence(Evidence::InvalidPrecommit(borsh::to_vec(&signed).unwrap())), + ) } }; @@ -120,7 +125,8 @@ async fn invalid_precommit_signature() { let mut random_sig = [0u8; 64]; OsRng.fill_bytes(&mut random_sig); signed.sig = random_sig; - let tx = TendermintTx::SlashEvidence(Evidence::InvalidPrecommit(signed.encode())); + let tx = + TendermintTx::SlashEvidence(Evidence::InvalidPrecommit(borsh::to_vec(&signed).unwrap())); assert!(verify_tendermint_tx::(&tx, &validators, commit).is_err()); } } @@ -138,24 +144,32 @@ async fn evidence_with_prevote() { // it should fail for all reasons. let mut txs = vec![]; txs.push(TendermintTx::SlashEvidence(Evidence::InvalidPrecommit( - signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) - .await - .encode(), + borsh::to_vec( + &&signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) + .await, + ) + .unwrap(), ))); txs.push(TendermintTx::SlashEvidence(Evidence::InvalidValidRound( - signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) - .await - .encode(), + borsh::to_vec( + &signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) + .await, + ) + .unwrap(), ))); // Since these require a second message, provide this one again // ConflictingMessages can be fired for actually conflicting Prevotes however txs.push(TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) - .await - .encode(), - signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) - .await - .encode(), + borsh::to_vec( + &signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) + .await, + ) + .unwrap(), + borsh::to_vec( + &signed_from_data::(signer.clone().into(), signer_id, 0, 0, Data::Prevote(block_id)) + .await, + ) + .unwrap(), ))); txs } @@ -189,16 +203,16 @@ async fn conflicting_msgs_evidence_tx() { // non-conflicting data should fail let signed_1 = signed_for_b_r(0, 0, Data::Proposal(None, TendermintBlock(vec![0x11]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_1.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_1).unwrap(), )); assert!(verify_tendermint_tx::(&tx, &validators, commit).is_err()); // conflicting data should pass let signed_2 = signed_for_b_r(0, 0, Data::Proposal(None, TendermintBlock(vec![0x22]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); verify_tendermint_tx::(&tx, &validators, commit).unwrap(); @@ -206,16 +220,16 @@ async fn conflicting_msgs_evidence_tx() { // (except for Precommit) let signed_2 = signed_for_b_r(0, 1, Data::Proposal(None, TendermintBlock(vec![0x22]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); verify_tendermint_tx::(&tx, &validators, commit).unwrap_err(); // Proposals for different block numbers should also fail as evidence let signed_2 = signed_for_b_r(1, 0, Data::Proposal(None, TendermintBlock(vec![0x22]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); verify_tendermint_tx::(&tx, &validators, commit).unwrap_err(); } @@ -225,16 +239,16 @@ async fn conflicting_msgs_evidence_tx() { // non-conflicting data should fail let signed_1 = signed_for_b_r(0, 0, Data::Prevote(Some([0x11; 32]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_1.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_1).unwrap(), )); assert!(verify_tendermint_tx::(&tx, &validators, commit).is_err()); // conflicting data should pass let signed_2 = signed_for_b_r(0, 0, Data::Prevote(Some([0x22; 32]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); verify_tendermint_tx::(&tx, &validators, commit).unwrap(); @@ -242,16 +256,16 @@ async fn conflicting_msgs_evidence_tx() { // (except for Precommit) let signed_2 = signed_for_b_r(0, 1, Data::Prevote(Some([0x22; 32]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); verify_tendermint_tx::(&tx, &validators, commit).unwrap_err(); // Proposals for different block numbers should also fail as evidence let signed_2 = signed_for_b_r(1, 0, Data::Prevote(Some([0x22; 32]))).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); verify_tendermint_tx::(&tx, &validators, commit).unwrap_err(); } @@ -273,8 +287,8 @@ async fn conflicting_msgs_evidence_tx() { .await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); // update schema so that we don't fail due to invalid signature @@ -293,8 +307,8 @@ async fn conflicting_msgs_evidence_tx() { let signed_1 = signed_for_b_r(0, 0, Data::Proposal(None, TendermintBlock(vec![]))).await; let signed_2 = signed_for_b_r(0, 0, Data::Prevote(None)).await; let tx = TendermintTx::SlashEvidence(Evidence::ConflictingMessages( - signed_1.encode(), - signed_2.encode(), + borsh::to_vec(&signed_1).unwrap(), + borsh::to_vec(&signed_2).unwrap(), )); assert!(verify_tendermint_tx::(&tx, &validators, commit).is_err()); } diff --git a/coordinator/tributary-sdk/tendermint/Cargo.toml b/coordinator/tributary-sdk/tendermint/Cargo.toml index 86a69d35..b1fa41c0 100644 --- a/coordinator/tributary-sdk/tendermint/Cargo.toml +++ b/coordinator/tributary-sdk/tendermint/Cargo.toml @@ -21,7 +21,7 @@ thiserror = { version = "2", default-features = false, features = ["std"] } hex = { version = "0.4", default-features = false, features = ["std"] } log = { version = "0.4", default-features = false, features = ["std"] } -parity-scale-codec = { version = "3", default-features = false, features = ["std", "derive"] } +borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } futures-util = { version = "0.3", default-features = false, features = ["std", "async-await-macro", "sink", "channel"] } futures-channel = { version = "0.3", default-features = false, features = ["std", "sink"] } diff --git a/coordinator/tributary-sdk/tendermint/src/ext.rs b/coordinator/tributary-sdk/tendermint/src/ext.rs index 3e3460b4..dc824fa5 100644 --- a/coordinator/tributary-sdk/tendermint/src/ext.rs +++ b/coordinator/tributary-sdk/tendermint/src/ext.rs @@ -3,33 +3,41 @@ use std::{sync::Arc, collections::HashSet}; use thiserror::Error; -use parity_scale_codec::{Encode, Decode}; +use borsh::{BorshSerialize, BorshDeserialize}; use crate::{SignedMessageFor, SlashEvent, commit_msg}; /// An alias for a series of traits required for a type to be usable as a validator ID, /// automatically implemented for all types satisfying those traits. pub trait ValidatorId: - Send + Sync + Clone + Copy + PartialEq + Eq + Hash + Debug + Encode + Decode + Send + Sync + Clone + Copy + PartialEq + Eq + Hash + Debug + BorshSerialize + BorshDeserialize { } -impl ValidatorId - for V +#[rustfmt::skip] +impl< + V: Send + Sync + Clone + Copy + PartialEq + Eq + Hash + Debug + BorshSerialize + BorshDeserialize, + > ValidatorId for V { } /// An alias for a series of traits required for a type to be usable as a signature, /// automatically implemented for all types satisfying those traits. -pub trait Signature: Send + Sync + Clone + PartialEq + Eq + Debug + Encode + Decode {} -impl Signature for S {} +pub trait Signature: + Send + Sync + Clone + PartialEq + Eq + Debug + BorshSerialize + BorshDeserialize +{ +} +impl Signature + for S +{ +} // Type aliases which are distinct according to the type system /// A struct containing a Block Number, wrapped to have a distinct type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, BorshSerialize, BorshDeserialize)] pub struct BlockNumber(pub u64); /// A struct containing a round number, wrapped to have a distinct type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, BorshSerialize, BorshDeserialize)] pub struct RoundNumber(pub u32); /// A signer for a validator. @@ -127,7 +135,7 @@ impl SignatureScheme for Arc { /// A commit for a specific block. /// /// The list of validators have weight exceeding the threshold for a valid commit. -#[derive(PartialEq, Debug, Encode, Decode)] +#[derive(PartialEq, Debug, BorshSerialize, BorshDeserialize)] pub struct Commit { /// End time of the round which created this commit, used as the start time of the next block. pub end_time: u64, @@ -185,7 +193,7 @@ impl Weights for Arc { } /// Simplified error enum representing a block's validity. -#[derive(Clone, Copy, PartialEq, Eq, Debug, Error, Encode, Decode)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Error, BorshSerialize, BorshDeserialize)] pub enum BlockError { /// Malformed block which is wholly invalid. #[error("invalid block")] @@ -197,9 +205,20 @@ pub enum BlockError { } /// Trait representing a Block. -pub trait Block: Send + Sync + Clone + PartialEq + Eq + Debug + Encode + Decode { +pub trait Block: + Send + Sync + Clone + PartialEq + Eq + Debug + BorshSerialize + BorshDeserialize +{ // Type used to identify blocks. Presumably a cryptographic hash of the block. - type Id: Send + Sync + Copy + Clone + PartialEq + Eq + AsRef<[u8]> + Debug + Encode + Decode; + type Id: Send + + Sync + + Copy + + Clone + + PartialEq + + Eq + + AsRef<[u8]> + + Debug + + BorshSerialize + + BorshDeserialize; /// Return the deterministic, unique ID for this block. fn id(&self) -> Self::Id; diff --git a/coordinator/tributary-sdk/tendermint/src/lib.rs b/coordinator/tributary-sdk/tendermint/src/lib.rs index 10f1fccf..fd5a3759 100644 --- a/coordinator/tributary-sdk/tendermint/src/lib.rs +++ b/coordinator/tributary-sdk/tendermint/src/lib.rs @@ -6,7 +6,7 @@ use std::{ collections::{VecDeque, HashMap}, }; -use parity_scale_codec::{Encode, Decode, IoReader}; +use borsh::{BorshSerialize, BorshDeserialize}; use futures_channel::mpsc; use futures_util::{ @@ -41,14 +41,14 @@ pub fn commit_msg(end_time: u64, id: &[u8]) -> Vec { [&end_time.to_le_bytes(), id].concat() } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, BorshSerialize, BorshDeserialize)] pub enum Step { Propose, Prevote, Precommit, } -#[derive(Clone, Eq, Debug, Encode, Decode)] +#[derive(Clone, Eq, Debug, BorshSerialize, BorshDeserialize)] pub enum Data { Proposal(Option, B), Prevote(Option), @@ -90,7 +90,7 @@ impl Data { } } -#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub struct Message { pub sender: V, pub block: BlockNumber, @@ -100,7 +100,7 @@ pub struct Message { } /// A signed Tendermint consensus message to be broadcast to the other validators. -#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub struct SignedMessage { pub msg: Message, pub sig: S, @@ -117,18 +117,18 @@ impl SignedMessage { &self, signer: &Scheme, ) -> bool { - signer.verify(self.msg.sender, &self.msg.encode(), &self.sig) + signer.verify(self.msg.sender, &borsh::to_vec(&self.msg).unwrap(), &self.sig) } } -#[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub enum SlashReason { FailToPropose, InvalidBlock, InvalidProposer, } -#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub enum Evidence { ConflictingMessages(Vec, Vec), InvalidPrecommit(Vec), @@ -159,7 +159,7 @@ pub type SignedMessageFor = SignedMessage< >; pub fn decode_signed_message(mut data: &[u8]) -> Option> { - SignedMessageFor::::decode(&mut data).ok() + SignedMessageFor::::deserialize_reader(&mut data).ok() } fn decode_and_verify_signed_message( @@ -339,7 +339,7 @@ impl TendermintMachine { target: "tendermint", "proposer for block {}, round {round:?} was {} (me: {res})", self.block.number.0, - hex::encode(proposer.encode()), + hex::encode(borsh::to_vec(&proposer).unwrap()), ); res } @@ -420,7 +420,11 @@ impl TendermintMachine { // TODO: If the new slash event has evidence, emit to prevent a low-importance slash from // cancelling emission of high-importance slashes if !self.block.slashes.contains(&validator) { - log::info!(target: "tendermint", "Slashing validator {}", hex::encode(validator.encode())); + log::info!( + target: "tendermint", + "Slashing validator {}", + hex::encode(borsh::to_vec(&validator).unwrap()), + ); self.block.slashes.insert(validator); self.network.slash(validator, slash_event).await; } @@ -670,7 +674,7 @@ impl TendermintMachine { self .slash( msg.sender, - SlashEvent::WithEvidence(Evidence::InvalidPrecommit(signed.encode())), + SlashEvent::WithEvidence(Evidence::InvalidPrecommit(borsh::to_vec(&signed).unwrap())), ) .await; Err(TendermintError::Malicious)?; @@ -741,7 +745,10 @@ impl TendermintMachine { self.broadcast(Data::Prevote(None)); } self - .slash(msg.sender, SlashEvent::WithEvidence(Evidence::InvalidValidRound(msg.encode()))) + .slash( + msg.sender, + SlashEvent::WithEvidence(Evidence::InvalidValidRound(borsh::to_vec(&msg).unwrap())), + ) .await; Err(TendermintError::Malicious)?; } @@ -1032,7 +1039,7 @@ impl TendermintMachine { while !messages.is_empty() { self.network.broadcast( - SignedMessageFor::::decode(&mut IoReader(&mut messages)) + SignedMessageFor::::deserialize_reader(&mut messages) .expect("saved invalid message to DB") ).await; } @@ -1057,7 +1064,7 @@ impl TendermintMachine { } { if our_message { assert!(sig.is_none()); - sig = Some(self.signer.sign(&msg.encode()).await); + sig = Some(self.signer.sign(&borsh::to_vec(&msg).unwrap()).await); } let sig = sig.unwrap(); @@ -1077,7 +1084,7 @@ impl TendermintMachine { let message_tape_key = message_tape_key(self.genesis); let mut txn = self.db.txn(); let mut message_tape = txn.get(&message_tape_key).unwrap_or(vec![]); - message_tape.extend(signed_msg.encode()); + signed_msg.serialize(&mut message_tape).unwrap(); txn.put(&message_tape_key, message_tape); txn.commit(); } diff --git a/coordinator/tributary-sdk/tendermint/src/message_log.rs b/coordinator/tributary-sdk/tendermint/src/message_log.rs index c6d172c4..b9aacea3 100644 --- a/coordinator/tributary-sdk/tendermint/src/message_log.rs +++ b/coordinator/tributary-sdk/tendermint/src/message_log.rs @@ -1,7 +1,5 @@ use std::{sync::Arc, collections::HashMap}; -use parity_scale_codec::Encode; - use crate::{ext::*, RoundNumber, Step, DataFor, SignedMessageFor, Evidence}; type RoundLog = HashMap<::ValidatorId, HashMap>>; @@ -39,7 +37,10 @@ impl MessageLog { target: "tendermint", "Validator sent multiple messages for the same block + round + step" ); - Err(Evidence::ConflictingMessages(existing.encode(), signed.encode()))?; + Err(Evidence::ConflictingMessages( + borsh::to_vec(&existing).unwrap(), + borsh::to_vec(&signed).unwrap(), + ))?; } return Ok(false); } diff --git a/coordinator/tributary-sdk/tendermint/tests/ext.rs b/coordinator/tributary-sdk/tendermint/tests/ext.rs index d6da9b38..e13c2a9f 100644 --- a/coordinator/tributary-sdk/tendermint/tests/ext.rs +++ b/coordinator/tributary-sdk/tendermint/tests/ext.rs @@ -4,7 +4,7 @@ use std::{ time::{UNIX_EPOCH, SystemTime, Duration}, }; -use parity_scale_codec::{Encode, Decode}; +use borsh::{BorshSerialize, BorshDeserialize}; use futures_util::sink::SinkExt; use tokio::{sync::RwLock, time::sleep}; @@ -89,7 +89,7 @@ impl Weights for TestWeights { } } -#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] struct TestBlock { id: TestBlockId, valid: Result<(), BlockError>,