Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
Bitworkr supports
Browse files Browse the repository at this point in the history
  • Loading branch information
aurexav committed Jan 14, 2024
1 parent 3acad1f commit 5c2f0a9
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 93 deletions.
6 changes: 6 additions & 0 deletions src/electrumx/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@ use super::*;

#[tokio::test]
async fn get_by_ticker_should_work() {
tracing_subscriber::fmt::init();

ElectrumXBuilder::default().build().unwrap().get_by_ticker("quark").await.unwrap();
}

#[tokio::test]
async fn get_ft_info_should_work() {
tracing_subscriber::fmt::init();

let e = ElectrumXBuilder::default().build().unwrap();

e.get_ft_info(e.get_by_ticker("quark").await.unwrap().atomical_id).await.unwrap();
}

#[tokio::test]
async fn get_unspent_address_should_work() {
tracing_subscriber::fmt::init();

ElectrumXBuilder::default()
.build()
.unwrap()
Expand Down
5 changes: 2 additions & 3 deletions src/electrumx/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,10 @@ pub struct Ft {
pub subtype: String,
pub r#type: String,
}
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize)]
pub struct Bitwork {
pub bitworkc: String,
// TODO: Check the real type.
pub bitworkr: Option<()>,
pub bitworkr: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct TickerStatus {
Expand Down
238 changes: 158 additions & 80 deletions src/engine/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ use bitcoin::{
use serde::Serialize;
// atomicalsir
use crate::{
electrumx::{r#type::Utxo, Api, ElectrumX, ElectrumXBuilder},
electrumx::{
r#type::{Bitwork, Utxo},
Api, ElectrumX, ElectrumXBuilder,
},
prelude::*,
util,
wallet::Wallet as RawWallet,
Expand Down Expand Up @@ -74,7 +77,7 @@ impl Miner {
let Data {
secp,
satsbyte,
bitwork_info_commit,
bitwork,
additional_outputs,
reveal_script,
reveal_spend_info,
Expand Down Expand Up @@ -118,6 +121,7 @@ impl Miner {
value: Amount::from_sat(funding_utxo.value),
script_pubkey: funding_spk.clone(),
}];
let commit_hty = TapSighashType::Default;
let mut ts = <Vec<JoinHandle<Result<()>>>>::new();
let solution_found = Arc::new(AtomicBool::new(false));
let maybe_commit_tx = Arc::new(Mutex::new(None));
Expand All @@ -126,13 +130,12 @@ impl Miner {
tracing::info!("spawning thread {i} for sequence range {r:?}");

let secp = secp.clone();
let bitwork_info_commit = bitwork_info_commit.clone();
let bitworkc = bitwork.bitworkc.clone();
let funding_kp = wallet.funding.pair.tap_tweak(&secp, None).to_inner();
let funding_xpk = wallet.funding.x_only_public_key;
let input = commit_input.clone();
let output = commit_output.clone();
let prevouts = commit_prevouts.clone();
let hash_ty = TapSighashType::Default;
let solution_found = solution_found.clone();
let maybe_tx = maybe_commit_tx.clone();

Expand All @@ -159,11 +162,11 @@ impl Miner {
.taproot_key_spend_signature_hash(
0,
&Prevouts::All(&prevouts),
hash_ty,
commit_hty,
)?;
let m = Message::from_digest(h.to_byte_array());

Signature { sig: secp.sign_schnorr(&m, &funding_kp), hash_ty }
Signature { sig: secp.sign_schnorr(&m, &funding_kp), hash_ty: commit_hty }
};

psbt.inputs[0] = Input {
Expand All @@ -185,7 +188,7 @@ impl Miner {
let tx = psbt.extract_tx_unchecked_fee_rate();
let txid = tx.txid();

if txid.to_string().trim_start_matches("0x").starts_with(&bitwork_info_commit) {
if txid.to_string().trim_start_matches("0x").starts_with(&bitworkc) {
tracing::info!("solution found");
tracing::info!("sequence {s}");
tracing::info!("commit txid {txid}");
Expand Down Expand Up @@ -223,66 +226,160 @@ impl Miner {

assert_eq!(commit_txid, commit_txid_.parse()?);

// TODO: bitworkr.
let mut reveal_psbt = Psbt::from_unsigned_tx(Transaction {
version: Version::ONE,
lock_time: LockTime::ZERO,
input: vec![TxIn {
previous_output: OutPoint::new(commit_txid, 0),
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
..Default::default()
}],
output: additional_outputs,
// TODO: bitworkr.
// {
// let mut o = additional_outputs;
//
// o.push(TxOut { value: Amount::ZERO, script_pubkey: util::time_nonce_script() });
//
// o
// },
})?;
let reveal_st = TapSighashType::SinglePlusAnyoneCanPay;
let reveal_tks = {
let lh = reveal_script.tapscript_leaf_hash();
let h = SighashCache::new(&reveal_psbt.unsigned_tx)
.taproot_script_spend_signature_hash(
// TODO: Move common code to a single function.
let reveal_hty = TapSighashType::SinglePlusAnyoneCanPay;
let reveal_lh = reveal_script.tapscript_leaf_hash();
let reveal_tx = if let Some(bitworkr) = bitwork.bitworkr {
let psbt = Psbt::from_unsigned_tx(Transaction {
version: Version::ONE,
lock_time: LockTime::ZERO,
input: vec![TxIn {
previous_output: OutPoint::new(commit_txid, 0),
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
..Default::default()
}],
output: additional_outputs,
})?;
let mut ts = <Vec<JoinHandle<Result<()>>>>::new();
let solution_found = Arc::new(AtomicBool::new(false));
let must_tx = Arc::new(Mutex::new(None));

for i in 0..num_cpus::get() {
tracing::info!("spawning thread {i} for bitworkr worker");

let secp = secp.clone();
let bitworkr = bitworkr.clone();
let funding_kp = wallet.funding.pair;
let reveal_script = reveal_script.clone();
let reveal_spend_info = reveal_spend_info.clone();
let commit_output = commit_output.clone();
let psbt = psbt.clone();
let solution_found = solution_found.clone();
let must_tx = must_tx.clone();

ts.push(thread::spawn(move || {
loop {
if solution_found.load(Ordering::Relaxed) {
return Ok(());
}

let mut psbt = psbt.clone();

psbt.unsigned_tx.output.push(TxOut {
value: Amount::ZERO,
script_pubkey: util::time_nonce_script(),
});
psbt.outputs.push(Default::default());

let tap_key_sig = {
let h = SighashCache::new(&psbt.unsigned_tx)
.taproot_script_spend_signature_hash(
0,
&Prevouts::One(0, commit_output[0].clone()),
reveal_lh,
reveal_hty,
)?;
let m = Message::from_digest(h.to_byte_array());

Signature {
sig: secp.sign_schnorr(&m, &funding_kp),
hash_ty: reveal_hty,
}
};

psbt.inputs[0] = Input {
// TODO: Check.
witness_utxo: Some(commit_output[0].clone()),
tap_internal_key: Some(reveal_spend_info.internal_key()),
tap_merkle_root: reveal_spend_info.merkle_root(),
final_script_witness: {
let mut w = Witness::new();

w.push(tap_key_sig.to_vec());
w.push(reveal_script.as_bytes());
w.push(
reveal_spend_info
.control_block(&(
reveal_script.clone(),
LeafVersion::TapScript,
))
.unwrap()
.serialize(),
);

Some(w)
},
..Default::default()
};

let tx = psbt.extract_tx_unchecked_fee_rate();
let txid = tx.txid();

if txid.to_string().trim_start_matches("0x").starts_with(&bitworkr) {
solution_found.store(true, Ordering::Relaxed);
*must_tx.lock().unwrap() = Some(tx);

return Ok(());
}
}
}));
}
for t in ts {
t.join().unwrap()?;
}

let tx = must_tx.lock().unwrap().take().unwrap();

tx
} else {
let mut psbt = Psbt::from_unsigned_tx(Transaction {
version: Version::ONE,
lock_time: LockTime::ZERO,
input: vec![TxIn {
previous_output: OutPoint::new(commit_txid, 0),
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
..Default::default()
}],
output: additional_outputs,
})?;
let tap_key_sig = {
let h = SighashCache::new(&psbt.unsigned_tx).taproot_script_spend_signature_hash(
0,
&Prevouts::One(0, commit_output[0].clone()),
lh,
reveal_st,
reveal_lh,
reveal_hty,
)?;
let m = Message::from_digest(h.to_byte_array());
let m = Message::from_digest(h.to_byte_array());

Signature { sig: secp.sign_schnorr(&m, &wallet.funding.pair), hash_ty: reveal_st }
};
Signature { sig: secp.sign_schnorr(&m, &wallet.funding.pair), hash_ty: reveal_hty }
};

reveal_psbt.inputs[0] = Input {
// TODO: Check.
witness_utxo: Some(commit_output[0].clone()),
tap_internal_key: Some(reveal_spend_info.internal_key()),
tap_merkle_root: reveal_spend_info.merkle_root(),
final_script_witness: {
let mut w = Witness::new();

w.push(reveal_tks.to_vec());
w.push(reveal_script.as_bytes());
w.push(
reveal_spend_info
.control_block(&(reveal_script, LeafVersion::TapScript))
.unwrap()
.serialize(),
);
psbt.inputs[0] = Input {
// TODO: Check.
witness_utxo: Some(commit_output[0].clone()),
tap_internal_key: Some(reveal_spend_info.internal_key()),
tap_merkle_root: reveal_spend_info.merkle_root(),
final_script_witness: {
let mut w = Witness::new();

w.push(tap_key_sig.to_vec());
w.push(reveal_script.as_bytes());
w.push(
reveal_spend_info
.control_block(&(reveal_script, LeafVersion::TapScript))
.unwrap()
.serialize(),
);

Some(w)
},
..Default::default()
};

Some(w)
},
..Default::default()
psbt.extract_tx_unchecked_fee_rate()
};

let reveal_tx = reveal_psbt.extract_tx_unchecked_fee_rate();
let reveal_txid = reveal_tx.txid();

tracing::info!("reveal txid {reveal_txid}");
tracing::info!("reveal txid {}", reveal_tx.txid());
tracing::info!("reveal tx {reveal_tx:#?}");

self.api.broadcast(encode::serialize_hex(&reveal_tx)).await?;
Expand Down Expand Up @@ -351,7 +448,7 @@ impl Miner {
Ok(Data {
secp,
satsbyte,
bitwork_info_commit: ft.mint_bitworkc,
bitwork: ft.bitwork,
additional_outputs,
reveal_script,
reveal_spend_info,
Expand Down Expand Up @@ -495,36 +592,17 @@ pub struct Payload {
pub time: u64,
}

// #[derive(Debug)]
// struct ScriptTree {
// output: Vec<u8>,
// }

// #[derive(Debug)]
// struct HashLockRedeem {
// output: Vec<u8>,
// redeem_version: u32,
// }

#[derive(Clone, Debug)]
struct Data {
secp: Secp256k1<All>,
satsbyte: u64,
// bitwork_info_commit: BitworkInfo,
bitwork_info_commit: String,
bitwork: Bitwork,
additional_outputs: Vec<TxOut>,
reveal_script: ScriptBuf,
reveal_spend_info: TaprootSpendInfo,
fees: Fees,
funding_utxo: Utxo,
}
// #[derive(Clone, Debug)]
// struct BitworkInfo {
// input_bitwork: String,
// hex_bitwork: String,
// prefix: String,
// ext: u64,
// }
#[derive(Clone, Debug)]
struct Fees {
commit: u64,
Expand Down
19 changes: 9 additions & 10 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
// crates.io
use bitcoin::{
opcodes::{
all::{OP_CHECKSIG, OP_ENDIF, OP_IF},
all::{OP_CHECKSIG, OP_ENDIF, OP_IF, OP_RETURN},
OP_0,
},
script::PushBytes,
Expand Down Expand Up @@ -168,15 +168,14 @@ fn build_reval_script_should_work() {
);
}

// // TODO: bitworkr.
// pub fn time_nonce_script() -> ScriptBuf {
// let (time, nonce) = time_nonce();
//
// Script::builder()
// .push_opcode(OP_RETURN)
// .push_slice(<&PushBytes>::try_from(format!("{time}:{nonce}").as_bytes()).unwrap())
// .into_script()
// }
pub fn time_nonce_script() -> ScriptBuf {
let (time, nonce) = time_nonce();

Script::builder()
.push_opcode(OP_RETURN)
.push_slice(<&PushBytes>::try_from(format!("{time}:{nonce}").as_bytes()).unwrap())
.into_script()
}

pub fn address2scripthash(address: &Address) -> Result<String> {
let mut hasher = Sha256::new();
Expand Down

0 comments on commit 5c2f0a9

Please sign in to comment.