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

Merge ozan/kickoff-root-operations into withdrawal #231

Merged
merged 8 commits into from
Aug 26, 2024
Merged
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
4 changes: 2 additions & 2 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ name = "user_deposit"
path = "src/bin/user_deposit.rs"

[[bin]]
name = "operator_and_verifiers"
path = "src/bin/operator_and_verifiers.rs"
name = "operators_and_verifiers"
path = "src/bin/operators_and_verifiers.rs"

[[bin]]
name = "config_generator"
Expand Down
16 changes: 8 additions & 8 deletions core/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,20 @@ impl Actor {

pub fn sign_taproot_script_spend_tx_new_tweaked(
&self,
tx: &mut TxHandler,
tx_handler: &mut TxHandler,
txin_index: usize,
script_index: usize,
) -> Result<schnorr::Signature, BridgeError> {
// TODO: if sighash_cache exists in the TxHandler, use it
// else create a new one and save it to the TxHandler

let mut sighash_cache: SighashCache<&mut bitcoin::Transaction> =
SighashCache::new(&mut tx.tx);
SighashCache::new(&mut tx_handler.tx);
let sig_hash = sighash_cache.taproot_script_spend_signature_hash(
txin_index,
&bitcoin::sighash::Prevouts::All(&tx.prevouts),
&bitcoin::sighash::Prevouts::All(&tx_handler.prevouts),
TapLeafHash::from_script(
&tx.scripts[txin_index][script_index],
&tx_handler.scripts[txin_index][script_index],
LeafVersion::TapScript,
),
bitcoin::sighash::TapSighashType::Default,
Expand All @@ -182,17 +182,17 @@ impl Actor {
}

pub fn convert_tx_to_sighash_script_spend(
tx: &mut TxHandler,
tx_handler: &mut TxHandler,
txin_index: usize,
script_index: usize,
) -> Result<TapSighash, BridgeError> {
let mut sighash_cache: SighashCache<&mut bitcoin::Transaction> =
SighashCache::new(&mut tx.tx);
SighashCache::new(&mut tx_handler.tx);
let sig_hash = sighash_cache.taproot_script_spend_signature_hash(
txin_index,
&bitcoin::sighash::Prevouts::All(&tx.prevouts),
&bitcoin::sighash::Prevouts::All(&tx_handler.prevouts),
TapLeafHash::from_script(
&tx.scripts[txin_index][script_index],
&tx_handler.scripts[txin_index][script_index],
LeafVersion::TapScript,
),
bitcoin::sighash::TapSighashType::Default,
Expand Down
33 changes: 0 additions & 33 deletions core/src/bin/operator_and_verifiers.rs

This file was deleted.

41 changes: 41 additions & 0 deletions core/src/bin/operators_and_verifiers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use clementine_core::{cli, extended_rpc::ExtendedRpc, servers::create_verifiers_and_operators};

/// ```bash
/// curl -X POST http://127.0.0.1:3434 -H "Content-Type: application/json" -d '{
/// "jsonrpc": "2.0",
/// "method": "operator_new_deposit",
/// "params": {
/// "start_utxo": "2964713fecf26d6eec7df4420bed1e09de1bdab2cacd24a1c8c0afd70c8a5371:3",
/// "recovery_taproot_address": "781990d7e2118cc361a93a6fcc54ce611d6df38168d6b1edfb556535f2200c4b",
/// "evm_address": "0101010101010101010101010101010101010101"
/// },
/// "id": 1
/// }'
/// ```
#[tokio::main]
async fn main() {
let config = cli::get_configuration();
let rpc = ExtendedRpc::<bitcoincore_rpc::Client>::new(
config.bitcoin_rpc_url.clone(),
config.bitcoin_rpc_user.clone(),
config.bitcoin_rpc_password.clone(),
);

let (operator_clients, verifier_clients) = create_verifiers_and_operators(config, rpc).await;

println!("Operator servers started: {:?}", operator_clients);
println!("Verifier servers started: {:?}", verifier_clients);
println!("Number of operator clients: {}", operator_clients.len());
println!("Number of verifier clients: {}", verifier_clients.len());

// Stop all servers
for (_, handle, _) in operator_clients {
handle.clone().stopped().await;
}

for (_, handle, _) in verifier_clients {
handle.clone().stopped().await;
}

println!("All servers stopped");
}
68 changes: 66 additions & 2 deletions core/src/database/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,17 @@ impl Database {
config: BridgeConfig,
database_name: &str,
) -> Result<BridgeConfig, BridgeError> {
println!("Creating database: {}", database_name);
let url = "postgresql://".to_owned()
+ config.db_user.as_str()
+ ":"
+ config.db_password.as_str()
+ "@"
+ config.db_host.as_str();
println!("url: {}", url);
let conn = sqlx::PgPool::connect(url.as_str()).await?;

Database::drop_database(config.clone(), database_name).await?;

println!("Dropped database");
let query = format!(
"CREATE DATABASE {} WITH OWNER {}",
database_name, config.db_user
Expand Down Expand Up @@ -442,6 +443,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 +902,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),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to manually implement From if you use this syntax.

Suggested change
FromHexError(hex::FromHexError),
FromHexError(#[from] 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]);
36 changes: 32 additions & 4 deletions core/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ where
signer: Actor,
config: BridgeConfig,
nofn_xonly_pk: secp256k1::XOnlyPublicKey,
idx: usize,
}

impl<R> Operator<R>
Expand All @@ -43,7 +44,7 @@ where
{
/// Creates a new `Operator`.
pub async fn new(config: BridgeConfig, rpc: ExtendedRpc<R>) -> Result<Self, BridgeError> {
let num_verifiers = config.verifiers_public_keys.len();
// let num_verifiers = config.verifiers_public_keys.len();

let signer = Actor::new(config.secret_key, config.network);

Expand All @@ -53,13 +54,19 @@ where
musig2::create_key_agg_ctx(config.verifiers_public_keys.clone(), None)?;
let agg_point: Point = key_agg_context.aggregated_pubkey_untweaked();
let nofn_xonly_pk = secp256k1::XOnlyPublicKey::from_slice(&agg_point.serialize_xonly())?;
let idx = config
.operators_xonly_pks
.iter()
.position(|xonly_pk| xonly_pk == &signer.xonly_public_key)
.unwrap();

Ok(Self {
rpc,
db,
signer,
config,
nofn_xonly_pk,
idx,
})
}

Expand Down Expand Up @@ -134,8 +141,12 @@ where
));
}

let kickoff_tx_handler =
TransactionBuilder::create_kickoff_tx(&funding_utxo, &self.signer.address);
let kickoff_tx_handler = TransactionBuilder::create_kickoff_utxo_tx(
&funding_utxo,
&self.nofn_xonly_pk,
&self.signer.xonly_public_key,
self.config.network,
);

let change_utxo = UTXO {
outpoint: OutPoint {
Expand Down Expand Up @@ -240,7 +251,7 @@ where
&Message::from_digest_slice(sighash.as_byte_array()).expect("should be hash"),
&user_xonly_pk,
)?;
let op_return_txout = script_builder::op_return_txout(5u32.to_be_bytes()); // TODO: Instead of 5u32 use the index of the operator.
let op_return_txout = script_builder::op_return_txout(self.idx.to_be_bytes());
tx.output.push(op_return_txout.clone());
let funded_tx = self
.rpc
Expand Down Expand Up @@ -272,6 +283,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 +322,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
}
}
Loading