mirror of
https://github.com/serai-dex/serai.git
synced 2025-02-04 12:16:37 +00:00
Adjust Bitcoin processor layout
This commit is contained in:
parent
776cbbb9a4
commit
b61ba9d1bb
6 changed files with 13 additions and 119 deletions
|
@ -6,14 +6,12 @@
|
|||
static ALLOCATOR: zalloc::ZeroizingAlloc<std::alloc::System> =
|
||||
zalloc::ZeroizingAlloc(std::alloc::System);
|
||||
|
||||
mod primitives;
|
||||
pub(crate) use primitives::*;
|
||||
|
||||
// Internal utilities for scanning transactions
|
||||
mod scan;
|
||||
|
||||
// Primitive trait satisfactions
|
||||
mod output;
|
||||
mod transaction;
|
||||
mod block;
|
||||
|
||||
// App-logic trait satisfactions
|
||||
mod rpc;
|
||||
mod scheduler;
|
||||
|
@ -70,17 +68,10 @@ use serai_client::{
|
|||
|
||||
/*
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct Fee(u64);
|
||||
pub(crate) struct Fee(u64);
|
||||
|
||||
#[async_trait]
|
||||
impl TransactionTrait<Bitcoin> for Transaction {
|
||||
type Id = [u8; 32];
|
||||
fn id(&self) -> Self::Id {
|
||||
let mut hash = *self.compute_txid().as_raw_hash().as_byte_array();
|
||||
hash.reverse();
|
||||
hash
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn fee(&self, network: &Bitcoin) -> u64 {
|
||||
let mut value = 0;
|
||||
|
@ -130,17 +121,8 @@ impl BlockTrait<Bitcoin> for Block {
|
|||
}
|
||||
}
|
||||
|
||||
// Shim required for testing/debugging purposes due to generic arguments also necessitating trait
|
||||
// bounds
|
||||
impl PartialEq for Bitcoin {
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
impl Eq for Bitcoin {}
|
||||
|
||||
impl Bitcoin {
|
||||
pub async fn new(url: String) -> Bitcoin {
|
||||
pub(crate) async fn new(url: String) -> Bitcoin {
|
||||
let mut res = Rpc::new(url.clone()).await;
|
||||
while let Err(e) = res {
|
||||
log::error!("couldn't connect to Bitcoin node: {e:?}");
|
||||
|
@ -151,7 +133,7 @@ impl Bitcoin {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub async fn fresh_chain(&self) {
|
||||
pub(crate) async fn fresh_chain(&self) {
|
||||
if self.rpc.get_latest_block_number().await.unwrap() > 0 {
|
||||
self
|
||||
.rpc
|
||||
|
@ -194,64 +176,8 @@ impl Bitcoin {
|
|||
Ok(Fee(fee.max(1)))
|
||||
}
|
||||
|
||||
async fn make_signable_transaction(
|
||||
&self,
|
||||
block_number: usize,
|
||||
inputs: &[Output],
|
||||
payments: &[Payment<Self>],
|
||||
change: &Option<Address>,
|
||||
calculating_fee: bool,
|
||||
) -> Result<Option<BSignableTransaction>, NetworkError> {
|
||||
for payment in payments {
|
||||
assert_eq!(payment.balance.coin, Coin::Bitcoin);
|
||||
}
|
||||
|
||||
// TODO2: Use an fee representative of several blocks, cached inside Self
|
||||
let block_for_fee = self.get_block(block_number).await?;
|
||||
let fee = self.median_fee(&block_for_fee).await?;
|
||||
|
||||
let payments = payments
|
||||
.iter()
|
||||
.map(|payment| {
|
||||
(
|
||||
payment.address.clone().into(),
|
||||
// If we're solely estimating the fee, don't specify the actual amount
|
||||
// This won't affect the fee calculation yet will ensure we don't hit a not enough funds
|
||||
// error
|
||||
if calculating_fee { Self::DUST } else { payment.balance.amount.0 },
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
match BSignableTransaction::new(
|
||||
inputs.iter().map(|input| input.output.clone()).collect(),
|
||||
&payments,
|
||||
change.clone().map(Into::into),
|
||||
None,
|
||||
fee.0,
|
||||
) {
|
||||
Ok(signable) => Ok(Some(signable)),
|
||||
Err(TransactionError::NoInputs) => {
|
||||
panic!("trying to create a bitcoin transaction without inputs")
|
||||
}
|
||||
// No outputs left and the change isn't worth enough/not even enough funds to pay the fee
|
||||
Err(TransactionError::NoOutputs | TransactionError::NotEnoughFunds) => Ok(None),
|
||||
// amortize_fee removes payments which fall below the dust threshold
|
||||
Err(TransactionError::DustPayment) => panic!("dust payment despite removing dust"),
|
||||
Err(TransactionError::TooMuchData) => {
|
||||
panic!("too much data despite not specifying data")
|
||||
}
|
||||
Err(TransactionError::TooLowFee) => {
|
||||
panic!("created a transaction whose fee is below the minimum")
|
||||
}
|
||||
Err(TransactionError::TooLargeTransaction) => {
|
||||
panic!("created a too large transaction despite limiting inputs/outputs")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn sign_btc_input_for_p2pkh(
|
||||
pub(crate) fn sign_btc_input_for_p2pkh(
|
||||
tx: &Transaction,
|
||||
input_index: usize,
|
||||
private_key: &PrivateKey,
|
||||
|
@ -288,17 +214,8 @@ impl Bitcoin {
|
|||
}
|
||||
}
|
||||
|
||||
fn address_from_key(key: ProjectivePoint) -> Address {
|
||||
Address::new(
|
||||
p2tr_script_buf(key).expect("creating address from key which isn't properly tweaked"),
|
||||
)
|
||||
.expect("couldn't create Serai-representable address for P2TR script")
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Network for Bitcoin {
|
||||
type Scheduler = Scheduler<Bitcoin>;
|
||||
|
||||
// 2 inputs should be 2 * 230 = 460 weight units
|
||||
// The output should be ~36 bytes, or 144 weight units
|
||||
// The overhead should be ~20 bytes at most, or 80 weight units
|
||||
|
@ -307,34 +224,12 @@ impl Network for Bitcoin {
|
|||
// aggregation TX
|
||||
const COST_TO_AGGREGATE: u64 = 800;
|
||||
|
||||
const MAX_OUTPUTS: usize = MAX_OUTPUTS;
|
||||
|
||||
fn tweak_keys(keys: &mut ThresholdKeys<Self::Curve>) {
|
||||
*keys = tweak_keys(keys);
|
||||
// Also create a scanner to assert these keys, and all expected paths, are usable
|
||||
scanner(keys.group_key());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn external_address(&self, key: ProjectivePoint) -> Address {
|
||||
address_from_key(key)
|
||||
}
|
||||
|
||||
fn branch_address(key: ProjectivePoint) -> Option<Address> {
|
||||
let (_, offsets, _) = scanner(key);
|
||||
Some(address_from_key(key + (ProjectivePoint::GENERATOR * offsets[&OutputType::Branch])))
|
||||
}
|
||||
|
||||
fn change_address(key: ProjectivePoint) -> Option<Address> {
|
||||
let (_, offsets, _) = scanner(key);
|
||||
Some(address_from_key(key + (ProjectivePoint::GENERATOR * offsets[&OutputType::Change])))
|
||||
}
|
||||
|
||||
fn forward_address(key: ProjectivePoint) -> Option<Address> {
|
||||
let (_, offsets, _) = scanner(key);
|
||||
Some(address_from_key(key + (ProjectivePoint::GENERATOR * offsets[&OutputType::Forwarded])))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn get_block_number(&self, id: &[u8; 32]) -> usize {
|
||||
self.rpc.get_block_number(id).await.unwrap()
|
||||
|
@ -409,8 +304,4 @@ impl Network for Bitcoin {
|
|||
self.get_block(block).await.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl UtxoNetwork for Bitcoin {
|
||||
const MAX_INPUTS: usize = MAX_INPUTS;
|
||||
}
|
||||
*/
|
||||
|
|
3
processor/bitcoin/src/primitives/mod.rs
Normal file
3
processor/bitcoin/src/primitives/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub(crate) mod output;
|
||||
pub(crate) mod transaction;
|
||||
pub(crate) mod block;
|
|
@ -53,7 +53,7 @@ pub(crate) struct Output {
|
|||
}
|
||||
|
||||
impl Output {
|
||||
pub fn new(
|
||||
pub(crate) fn new(
|
||||
getter: &impl Get,
|
||||
key: <Secp256k1 as Ciphersuite>::G,
|
||||
tx: &Transaction,
|
||||
|
@ -70,7 +70,7 @@ impl Output {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_with_presumed_origin(
|
||||
pub(crate) fn new_with_presumed_origin(
|
||||
key: <Secp256k1 as Ciphersuite>::G,
|
||||
tx: &Transaction,
|
||||
presumed_origin: Option<Address>,
|
|
@ -67,7 +67,7 @@ impl<D: Db> ContinuallyRan for TxIndexTask<D> {
|
|||
let txid = hash_bytes(tx.compute_txid().to_raw_hash());
|
||||
for (o, output) in tx.output.iter().enumerate() {
|
||||
let o = u32::try_from(o).unwrap();
|
||||
// Set the script pub key for this transaction
|
||||
// Set the script public key for this transaction
|
||||
db::ScriptPubKey::set(&mut txn, txid, o, &output.script_pubkey.clone().into_bytes());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue