Skip to content

Commit

Permalink
WIP Implement endpoints with db operations and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ozankaymak committed Aug 22, 2024
1 parent 85fd149 commit b9be24e
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 6 deletions.
63 changes: 63 additions & 0 deletions core/src/database/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,39 @@ impl Database {
None => Ok(None),
}
}

pub async fn save_kickoff_root(
&self,
deposit_outpoint: OutPoint,
kickoff_root: [u8; 32],
) -> Result<(), BridgeError> {
sqlx::query(
"INSERT INTO kickoff_roots (deposit_outpoint, kickoff_merkle_root) VALUES ($1, $2);",
)
.bind(OutPointDB(deposit_outpoint))
.bind(hex::encode(kickoff_root))
.execute(&self.connection)
.await?;

Ok(())
}

pub async fn get_kickoff_root(
&self,
deposit_outpoint: OutPoint,
) -> Result<Option<[u8; 32]>, BridgeError> {
let qr: Option<String> = sqlx::query_scalar(
"SELECT kickoff_merkle_root FROM kickoff_roots WHERE deposit_outpoint = $1;",
)
.bind(OutPointDB(deposit_outpoint))
.fetch_optional(&self.connection)
.await?;

match qr {
Some(root) => Ok(Some(hex::decode(root)?.try_into()?)),
None => Ok(None),
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -868,6 +901,36 @@ mod tests {
let res = db.get_deposit_kickoff_generator_tx(txid).await.unwrap();
assert!(res.is_none());
}

#[tokio::test]
async fn test_kickoff_root_1() {
let config = create_test_config_with_thread_name!("test_config.toml");
let db = Database::new(config).await.unwrap();

let outpoint = OutPoint {
txid: Txid::from_byte_array([1u8; 32]),
vout: 1,
};
let root = [1u8; 32];
db.save_kickoff_root(outpoint, root).await.unwrap();
let db_root = db.get_kickoff_root(outpoint).await.unwrap().unwrap();

// Sanity check
assert_eq!(db_root, root);
}

#[tokio::test]
async fn test_kickoff_root_2() {
let config = create_test_config_with_thread_name!("test_config.toml");
let db = Database::new(config).await.unwrap();

let outpoint = OutPoint {
txid: Txid::from_byte_array([1u8; 32]),
vout: 1,
};
let res = db.get_kickoff_root(outpoint).await.unwrap();
assert!(res.is_none());
}
}

#[cfg(poc)]
Expand Down
18 changes: 18 additions & 0 deletions core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ pub enum BridgeError {
KickoffOutpointsNotFound,
#[error("DepositInfoNotFound")]
DepositInfoNotFound,

#[error("FromHexError: {0}")]
FromHexError(hex::FromHexError),

#[error("FromSliceError: {0}")]
FromSliceError(bitcoin::hashes::FromSliceError),
}

impl Into<ErrorObject<'static>> for BridgeError {
Expand Down Expand Up @@ -261,3 +267,15 @@ impl From<musig2::errors::VerifyError> for BridgeError {
BridgeError::MuSig2VerifyError(err)
}
}

impl From<hex::FromHexError> for BridgeError {
fn from(err: hex::FromHexError) -> Self {
BridgeError::FromHexError(err)
}
}

impl From<bitcoin::hashes::FromSliceError> for BridgeError {
fn from(err: bitcoin::hashes::FromSliceError) -> Self {
BridgeError::FromSliceError(err)
}
}
9 changes: 9 additions & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ pub struct UTXO {
pub txout: bitcoin::TxOut,
}

impl UTXO {
fn to_vec(&self) -> Vec<u8> {
let outpoint_hex = bitcoin::consensus::encode::serialize_hex(&self.outpoint);
let txout_hex = bitcoin::consensus::encode::serialize_hex(&self.txout);
let all = format!("{}{}", outpoint_hex, txout_hex);
hex::decode(all).unwrap()
}
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, sqlx::Type)]
#[sqlx(type_name = "bytea")]
pub struct ByteArray66(#[serde(with = "hex::serde")] pub [u8; 66]);
17 changes: 17 additions & 0 deletions core/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,14 @@ where
let final_txid = self.rpc.send_raw_transaction(&signed_tx)?;
Ok(Some(final_txid))
}

async fn withdrawal_proved_on_citrea(
&self,
withdrawal_idx: usize,
kickoff_merkle_root: [u8; 32],
) -> Result<(), BridgeError> {
Ok(())
}
}

#[async_trait]
Expand Down Expand Up @@ -303,4 +311,13 @@ where
self.new_withdrawal_sig(withdrawal_idx, user_sig, input_utxo, output_txout)
.await
}

async fn withdrawal_proved_on_citrea_rpc(
&self,
withdrawal_idx: usize,
kickoff_merkle_root: [u8; 32],
) -> Result<(), BridgeError> {
self.withdrawal_proved_on_citrea(withdrawal_idx, kickoff_merkle_root)
.await
}
}
11 changes: 6 additions & 5 deletions core/src/traits/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ pub trait OperatorRpc {
output_txout: TxOut,
) -> Result<Option<Txid>, BridgeError>;

// #[method(name = "withdrawal_proved_on_citrea")]
// async fn withdrawal_proved_on_citrea_rpc(
// &self,
// withdrawal_idx: usize,
// ) -> Result<(), BridgeError>;
#[method(name = "withdrawal_proved_on_citrea")]
async fn withdrawal_proved_on_citrea_rpc(
&self,
withdrawal_idx: usize,
kickoff_merkle_root: [u8; 32],
) -> Result<(), BridgeError>;

// #[method(name = "operator_take_sendable")]
// async fn operator_take_sendable_rpc(&self, withdrawal_idx: usize) -> Result<(), BridgeError>;
Expand Down
16 changes: 15 additions & 1 deletion core/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ use crate::config::BridgeConfig;
use crate::database::verifier::VerifierDB;
use crate::errors::BridgeError;
use crate::extended_rpc::ExtendedRpc;
use crate::merkle::MerkleTree;
use crate::musig2::{self, MuSigAggNonce, MuSigPartialSignature, MuSigPubNonce};
use crate::traits::rpc::VerifierRpcServer;
use crate::transaction_builder::{TransactionBuilder, TxHandler};
use crate::{utils, EVMAddress, UTXO};
use ::musig2::secp::Point;
use bitcoin::address::NetworkUnchecked;
use bitcoin::hashes::Hash;
use bitcoin::Address;
use bitcoin::{merkle_tree, Address};
use bitcoin::{secp256k1, OutPoint};
use bitcoin_mock_rpc::RpcApiWrapper;
use clementine_circuits::constants::BRIDGE_AMOUNT_SATS;
use clementine_circuits::incremental_merkle::IncrementalMerkleTree;
use clementine_circuits::sha256_hash;
use jsonrpsee::core::async_trait;
use secp256k1::{rand, schnorr};
Expand Down Expand Up @@ -153,6 +155,14 @@ where
)?;
}

let root: bitcoin::hashes::sha256::Hash = bitcoin::merkle_tree::calculate_root(
kickoff_utxos
.iter()
.map(|utxo| Hash::from_byte_array(sha256_hash!(utxo.to_vec().as_slice()))),
)
.unwrap();
let root_bytes: [u8; 32] = *root.as_byte_array();

self.db
.save_agg_nonces(deposit_outpoint, &agg_nonces)
.await?;
Expand All @@ -161,6 +171,10 @@ where
.save_kickoff_utxos(deposit_outpoint, &kickoff_utxos)
.await?;

self.db
.save_kickoff_root(deposit_outpoint, root_bytes)
.await?;

// TODO: Sign burn txs
Ok(vec![])
}
Expand Down
7 changes: 7 additions & 0 deletions scripts/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,11 @@ create table funding_utxos (
created_at timestamp not null default now()
);

-- Verifier table for kickoff merkle roots for deposits
create table kickoff_roots (
deposit_outpoint text primary key not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'),
kickoff_merkle_root text not null check (kickoff_merkle_root ~ '^[a-fA-F0-9]{64}'),
created_at timestamp not null default now()
);

COMMIT;

0 comments on commit b9be24e

Please sign in to comment.