Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom transaction extensions #5

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ heed = { git = "https://github.com/meilisearch/heed", tag = "v0.12.4", version =
hex = "0.4.3"
http = "0.2.9"
jsonrpsee = { version = "0.19.0", features = ["client", "macros"] }
never-type = "0.1.1"
quinn = "0.10.1"
rayon = "1.7.0"
rcgen = "0.11.1"
Expand Down
28 changes: 20 additions & 8 deletions src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@ use heed::types::*;
use heed::{Database, RoTxn, RwTxn};
use serde::{Deserialize, Serialize};

type ArchiveBodies<A, CustomTxExtension, CustomTxOutput> =
Database<OwnedType<[u8; 4]>, SerdeBincode<Body<A, CustomTxExtension, CustomTxOutput>>>;

#[derive(Clone)]
pub struct Archive<A, C> {
pub struct Archive<
A,
CustomTxExtension = DefaultTxExtension,
CustomTxOutput = DefaultCustomTxOutput,
> {
// Block height to header.
headers: Database<OwnedType<[u8; 4]>, SerdeBincode<Header>>,
bodies: Database<OwnedType<[u8; 4]>, SerdeBincode<Body<A, C>>>,
bodies: ArchiveBodies<A, CustomTxExtension, CustomTxOutput>,
hash_to_height: Database<OwnedType<[u8; 32]>, OwnedType<[u8; 4]>>,
}

impl<
A: Serialize + for<'de> Deserialize<'de> + 'static,
C: Clone + Serialize + for<'de> Deserialize<'de> + GetValue + 'static,
> Archive<A, C>
impl<A, CustomTxExtension, CustomTxOutput> Archive<A, CustomTxExtension, CustomTxOutput>
where
A: Serialize + for<'de> Deserialize<'de> + 'static,
CustomTxExtension: Serialize + for<'de> Deserialize<'de> + 'static,
CustomTxOutput: Clone + Serialize + for<'de> Deserialize<'de> + GetValue + 'static,
{
pub const NUM_DBS: u32 = 3;

Expand All @@ -37,7 +45,11 @@ impl<
Ok(header)
}

pub fn get_body(&self, txn: &RoTxn, height: u32) -> Result<Option<Body<A, C>>, Error> {
pub fn get_body(
&self,
txn: &RoTxn,
height: u32,
) -> Result<Option<Body<A, CustomTxExtension, CustomTxOutput>>, Error> {
let height = height.to_be_bytes();
let header = self.bodies.get(txn, &height)?;
Ok(header)
Expand All @@ -63,7 +75,7 @@ impl<
&self,
txn: &mut RwTxn,
header: &Header,
body: &Body<A, C>,
body: &Body<A, CustomTxExtension, CustomTxOutput>,
) -> Result<(), Error> {
if header.merkle_root != body.compute_merkle_root() {
return Err(Error::InvalidMerkleRoot);
Expand Down
92 changes: 53 additions & 39 deletions src/authorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,13 @@ impl GetAddress for Authorization {
}
}

impl<C: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync> Verify<C> for Authorization {
type Error = Error;
fn verify_transaction(transaction: &AuthorizedTransaction<Self, C>) -> Result<(), Self::Error>
where
Self: Sized,
{
verify_authorized_transaction(transaction)?;
Ok(())
}

fn verify_body(body: &Body<Self, C>) -> Result<(), Self::Error>
where
Self: Sized,
{
verify_authorizations(body)?;
Ok(())
}
}

pub fn get_address(public_key: &PublicKey) -> Address {
let mut hasher = blake3::Hasher::new();
let mut reader = hasher.update(&public_key.to_bytes()).finalize_xof();
let mut output: [u8; 20] = [0; 20];
reader.fill(&mut output);
Address(output)
}

struct Package<'a> {
messages: Vec<&'a [u8]>,
signatures: Vec<Signature>,
public_keys: Vec<PublicKey>,
}

pub fn verify_authorized_transaction<C: Clone + Serialize + Sync>(
transaction: &AuthorizedTransaction<Authorization, C>,
) -> Result<(), Error> {
pub fn verify_authorized_transaction<CustomTxExtension, CustomTxOutput>(
transaction: &AuthorizedTransaction<Authorization, CustomTxExtension, CustomTxOutput>,
) -> Result<(), Error>
where
CustomTxExtension: Serialize,
CustomTxOutput: Clone + Serialize + Sync,
{
let serialized_transaction = bincode::serialize(&transaction.transaction)?;
let messages: Vec<_> = std::iter::repeat(serialized_transaction.as_slice())
.take(transaction.authorizations.len())
Expand All @@ -70,9 +41,13 @@ pub fn verify_authorized_transaction<C: Clone + Serialize + Sync>(
Ok(())
}

pub fn verify_authorizations<C: Clone + Serialize + Sync>(
body: &Body<Authorization, C>,
) -> Result<(), Error> {
pub fn verify_authorizations<CustomTxExtension, CustomTxOutput>(
body: &Body<Authorization, CustomTxExtension, CustomTxOutput>,
) -> Result<(), Error>
where
CustomTxExtension: Serialize + Sync,
CustomTxOutput: Clone + Serialize + Sync,
{
let input_numbers = body
.transactions
.iter()
Expand Down Expand Up @@ -134,6 +109,45 @@ pub fn verify_authorizations<C: Clone + Serialize + Sync>(
Ok(())
}

impl<CustomTxExtension, CustomTxOutput> Verify<CustomTxExtension, CustomTxOutput> for Authorization
where
CustomTxExtension: Serialize + Send + Sync,
CustomTxOutput: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync,
{
type Error = Error;
fn verify_transaction(
transaction: &AuthorizedTransaction<Self, CustomTxExtension, CustomTxOutput>,
) -> Result<(), Self::Error>
where
Self: Sized,
{
verify_authorized_transaction(transaction)?;
Ok(())
}

fn verify_body(body: &Body<Self, CustomTxExtension, CustomTxOutput>) -> Result<(), Self::Error>
where
Self: Sized,
{
verify_authorizations(body)?;
Ok(())
}
}

pub fn get_address(public_key: &PublicKey) -> Address {
let mut hasher = blake3::Hasher::new();
let mut reader = hasher.update(&public_key.to_bytes()).finalize_xof();
let mut output: [u8; 20] = [0; 20];
reader.fill(&mut output);
Address(output)
}

struct Package<'a> {
messages: Vec<&'a [u8]>,
signatures: Vec<Signature>,
public_keys: Vec<PublicKey>,
}

pub fn sign<C: Clone + Serialize>(
keypair: &Keypair,
transaction: &Transaction<C>,
Expand Down
21 changes: 16 additions & 5 deletions src/drivechain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ use std::net::SocketAddr;
use std::{collections::HashMap, marker::PhantomData};

#[derive(Clone)]
pub struct Drivechain<C> {
pub struct Drivechain<
CustomTxExtension = DefaultTxExtension,
CustomTxOutput = DefaultCustomTxOutput,
> {
pub sidechain_number: u8,
pub client: HttpClient,
pub _content: PhantomData<C>,
pub _content: PhantomData<CustomTxOutput>,
pub _tx_extension: PhantomData<CustomTxExtension>,
}

impl<C> Drivechain<C> {
impl<CustomTxExtension, CustomTxOutput> Drivechain<CustomTxExtension, CustomTxOutput> {
pub async fn verify_bmm(&self, header: &Header) -> Result<(), Error> {
let prev_main_hash = header.prev_main_hash;
let block_hash = self
Expand All @@ -37,7 +41,7 @@ impl<C> Drivechain<C> {
&self,
end: bitcoin::BlockHash,
start: Option<bitcoin::BlockHash>,
) -> Result<TwoWayPegData<C>, Error> {
) -> Result<TwoWayPegData<CustomTxOutput>, Error> {
let (deposits, deposit_block_hash) = self.get_deposit_outputs(end, start).await?;
let bundle_statuses = self.get_withdrawal_bundle_statuses().await?;
let two_way_peg_data = TwoWayPegData {
Expand Down Expand Up @@ -65,7 +69,13 @@ impl<C> Drivechain<C> {
&self,
end: bitcoin::BlockHash,
start: Option<bitcoin::BlockHash>,
) -> Result<(HashMap<OutPoint, Output<C>>, Option<bitcoin::BlockHash>), Error> {
) -> Result<
(
HashMap<OutPoint, Output<CustomTxOutput>>,
Option<bitcoin::BlockHash>,
),
Error,
> {
let deposits = self
.client
.listsidechaindepositsbyblock(self.sidechain_number, Some(end), start)
Expand Down Expand Up @@ -141,6 +151,7 @@ impl<C> Drivechain<C> {
sidechain_number,
client,
_content: PhantomData::default(),
_tx_extension: PhantomData::default(),
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use jsonrpsee;
pub fn format_deposit_address(str_dest: &str) -> String {
let this_sidechain = 0;
let deposit_address: String = format!("s{}_{}_", this_sidechain, str_dest);
let hash = sha256::digest(deposit_address.as_bytes()).to_string();
let hash = sha256::digest(deposit_address.as_bytes());
let hash: String = hash[..6].into();
format!("{}{}", deposit_address, hash)
}
37 changes: 26 additions & 11 deletions src/mempool.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
use crate::types::{AuthorizedTransaction, OutPoint, Txid};
use crate::types::{
AuthorizedTransaction, DefaultCustomTxOutput, DefaultTxExtension, OutPoint, Txid,
};
use heed::types::*;
use heed::{Database, RoTxn, RwTxn};
use serde::{Deserialize, Serialize};

type MemPoolTransactions<A, CustomTxExtension, CustomTxOutput> = Database<
OwnedType<[u8; 32]>,
SerdeBincode<AuthorizedTransaction<A, CustomTxExtension, CustomTxOutput>>,
>;

#[derive(Clone)]
pub struct MemPool<A, C> {
pub transactions: Database<OwnedType<[u8; 32]>, SerdeBincode<AuthorizedTransaction<A, C>>>,
pub struct MemPool<
A,
CustomTxExtension = DefaultTxExtension,
CustomTxOutput = DefaultCustomTxOutput,
> {
pub transactions: MemPoolTransactions<A, CustomTxExtension, CustomTxOutput>,
pub spent_utxos: Database<SerdeBincode<OutPoint>, Unit>,
}

impl<
A: Serialize + for<'de> Deserialize<'de> + 'static,
C: Serialize + for<'de> Deserialize<'de> + 'static,
> MemPool<A, C>
impl<A, CustomTxExtension, CustomTxOutput> MemPool<A, CustomTxExtension, CustomTxOutput>
where
A: Serialize + for<'de> Deserialize<'de> + 'static,
CustomTxExtension: Serialize + for<'de> Deserialize<'de> + 'static,
CustomTxOutput: Serialize + for<'de> Deserialize<'de> + 'static,
{
pub const NUM_DBS: u32 = 1;

Expand All @@ -28,7 +40,7 @@ impl<
pub fn put(
&self,
txn: &mut RwTxn,
transaction: &AuthorizedTransaction<A, C>,
transaction: &AuthorizedTransaction<A, CustomTxExtension, CustomTxOutput>,
) -> Result<(), Error> {
println!(
"adding transaction {} to mempool",
Expand All @@ -41,7 +53,7 @@ impl<
self.spent_utxos.put(txn, input, &())?;
}
self.transactions
.put(txn, &transaction.transaction.txid().into(), &transaction)?;
.put(txn, &transaction.transaction.txid().into(), transaction)?;
Ok(())
}

Expand All @@ -54,7 +66,7 @@ impl<
&self,
txn: &RoTxn,
number: usize,
) -> Result<Vec<AuthorizedTransaction<A, C>>, Error> {
) -> Result<Vec<AuthorizedTransaction<A, CustomTxExtension, CustomTxOutput>>, Error> {
let mut transactions = vec![];
for item in self.transactions.iter(txn)?.take(number) {
let (_, transaction) = item?;
Expand All @@ -63,7 +75,10 @@ impl<
Ok(transactions)
}

pub fn take_all(&self, txn: &RoTxn) -> Result<Vec<AuthorizedTransaction<A, C>>, Error> {
pub fn take_all(
&self,
txn: &RoTxn,
) -> Result<Vec<AuthorizedTransaction<A, CustomTxExtension, CustomTxOutput>>, Error> {
let mut transactions = vec![];
for item in self.transactions.iter(txn)? {
let (_, transaction) = item?;
Expand Down
20 changes: 14 additions & 6 deletions src/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ use std::str::FromStr as _;
pub use crate::drivechain::MainClient;

#[derive(Clone)]
pub struct Miner<A, C> {
pub drivechain: Drivechain<C>,
block: Option<(Header, Body<A, C>)>,
pub struct Miner<A, CustomTxExtension = DefaultTxExtension, CustomTxOutput = DefaultCustomTxOutput>
{
pub drivechain: Drivechain<CustomTxExtension, CustomTxOutput>,
block: Option<(Header, Body<A, CustomTxExtension, CustomTxOutput>)>,
sidechain_number: u8,
}

impl<A: Clone, C: Clone + GetValue + Serialize> Miner<A, C> {
impl<A, CustomTxExtension, CustomTxOutput> Miner<A, CustomTxExtension, CustomTxOutput>
where
A: Clone,
CustomTxExtension: Clone + Serialize,
CustomTxOutput: Clone + GetValue + Serialize,
{
pub fn new(sidechain_number: u8, main_addr: SocketAddr) -> Result<Self, Error> {
let drivechain = Drivechain::new(sidechain_number, main_addr)?;
Ok(Self {
Expand All @@ -38,7 +44,7 @@ impl<A: Clone, C: Clone + GetValue + Serialize> Miner<A, C> {
amount: u64,
height: u32,
header: Header,
body: Body<A, C>,
body: Body<A, CustomTxExtension, CustomTxOutput>,
) -> Result<(), Error> {
let str_hash_prev = header.prev_main_hash.to_string();
let critical_hash: [u8; 32] = header.hash().into();
Expand All @@ -62,7 +68,9 @@ impl<A: Clone, C: Clone + GetValue + Serialize> Miner<A, C> {
Ok(())
}

pub async fn confirm_bmm(&mut self) -> Result<Option<(Header, Body<A, C>)>, Error> {
pub async fn confirm_bmm(
&mut self,
) -> Result<Option<(Header, Body<A, CustomTxExtension, CustomTxOutput>)>, Error> {
if let Some((header, body)) = self.block.clone() {
self.drivechain.verify_bmm(&header).await?;
self.block = None;
Expand Down
Loading