Skip to content

Commit

Permalink
Create ContractSignerProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Dec 18, 2023
1 parent 3ed5c52 commit 9da1619
Show file tree
Hide file tree
Showing 14 changed files with 629 additions and 343 deletions.
155 changes: 84 additions & 71 deletions bitcoin-rpc-provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use bitcoin::{Address, OutPoint, TxOut};
use bitcoincore_rpc::{json, Auth, Client, RpcApi};
use bitcoincore_rpc_json::AddressType;
use dlc_manager::error::Error as ManagerError;
use dlc_manager::{Blockchain, Signer, Utxo, Wallet};
use dlc_manager::{Blockchain, ContractSignerProvider, SimpleSigner, Utxo, Wallet};
use json::EstimateMode;
use lightning::chain::chaininterface::{ConfirmationTarget, FeeEstimator};
use log::error;
Expand Down Expand Up @@ -168,7 +168,20 @@ fn enc_err_to_manager_err(_e: EncodeError) -> ManagerError {
Error::BitcoinError.into()
}

impl Signer for BitcoinCoreProvider {
impl ContractSignerProvider for BitcoinCoreProvider {
type Signer = SimpleSigner;

fn derive_contract_signer(
&self,
_: bool,
_: u64,
_: [u8; 32],
) -> Result<Self::Signer, ManagerError> {
// fixme needs to be idempotent
let secret_key = self.get_new_secret_key()?;
Ok(SimpleSigner::new(secret_key))
}

fn get_secret_key_for_pubkey(&self, pubkey: &PublicKey) -> Result<SecretKey, ManagerError> {
let b_pubkey = bitcoin::PublicKey {
compressed: true,
Expand All @@ -186,75 +199,6 @@ impl Signer for BitcoinCoreProvider {
Ok(pk.inner)
}

fn sign_psbt_input(
&self,
psbt: &mut PartiallySignedTransaction,
input_index: usize,
) -> Result<(), ManagerError> {
let outpoint = &psbt.unsigned_tx.input[input_index].previous_output;
let tx_out = if let Some(input) = psbt.inputs.get(input_index) {
if let Some(wit_utxo) = &input.witness_utxo {
Ok(wit_utxo.clone())
} else if let Some(in_tx) = &input.non_witness_utxo {
Ok(
in_tx.output[psbt.unsigned_tx.input[input_index].previous_output.vout as usize]
.clone(),
)
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT inout".to_string(),
))
}
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT inout".to_string(),
))
}?;

let redeem_script = psbt
.inputs
.get(input_index)
.and_then(|i| i.redeem_script.clone());

let input = json::SignRawTransactionInput {
txid: outpoint.txid,
vout: outpoint.vout,
script_pub_key: tx_out.script_pubkey.clone(),
redeem_script,
amount: Some(Amount::from_sat(tx_out.value)),
};

let sign_result = self
.client
.lock()
.unwrap()
.sign_raw_transaction_with_wallet(&psbt.unsigned_tx, Some(&[input]), None)
.map_err(rpc_err_to_manager_err)?;
let signed_tx = Transaction::consensus_decode(&mut sign_result.hex.as_slice())
.map_err(enc_err_to_manager_err)?;

psbt.inputs[input_index].final_script_sig =
Some(signed_tx.input[input_index].script_sig.clone());
psbt.inputs[input_index].final_script_witness =
Some(signed_tx.input[input_index].witness.clone());

Ok(())
}
}

impl Wallet for BitcoinCoreProvider {
fn get_new_address(&self) -> Result<Address, ManagerError> {
self.client
.lock()
.unwrap()
.get_new_address(None, Some(AddressType::Bech32))
.map_err(rpc_err_to_manager_err)
}

fn get_new_change_address(&self) -> Result<Address, ManagerError> {
self.get_new_address()
}

fn get_new_secret_key(&self) -> Result<SecretKey, ManagerError> {
let sk = SecretKey::new(&mut thread_rng());
let network = self.get_network()?;
Expand All @@ -274,6 +218,20 @@ impl Wallet for BitcoinCoreProvider {

Ok(sk)
}
}

impl Wallet for BitcoinCoreProvider {
fn get_new_address(&self) -> Result<Address, ManagerError> {
self.client
.lock()
.unwrap()
.get_new_address(None, Some(AddressType::Bech32))
.map_err(rpc_err_to_manager_err)
}

fn get_new_change_address(&self) -> Result<Address, ManagerError> {
self.get_new_address()
}

fn get_utxos_for_amount(
&self,
Expand Down Expand Up @@ -324,6 +282,61 @@ impl Wallet for BitcoinCoreProvider {
.import_address(address, None, Some(false))
.map_err(rpc_err_to_manager_err)
}

fn sign_psbt_input(
&self,
psbt: &mut PartiallySignedTransaction,
input_index: usize,
) -> Result<(), ManagerError> {
let outpoint = &psbt.unsigned_tx.input[input_index].previous_output;
let tx_out = if let Some(input) = psbt.inputs.get(input_index) {
if let Some(wit_utxo) = &input.witness_utxo {
Ok(wit_utxo.clone())
} else if let Some(in_tx) = &input.non_witness_utxo {
Ok(
in_tx.output[psbt.unsigned_tx.input[input_index].previous_output.vout as usize]
.clone(),
)
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT inout".to_string(),
))
}
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT inout".to_string(),
))
}?;

let redeem_script = psbt
.inputs
.get(input_index)
.and_then(|i| i.redeem_script.clone());

let input = json::SignRawTransactionInput {
txid: outpoint.txid,
vout: outpoint.vout,
script_pub_key: tx_out.script_pubkey.clone(),
redeem_script,
amount: Some(Amount::from_sat(tx_out.value)),
};

let sign_result = self
.client
.lock()
.unwrap()
.sign_raw_transaction_with_wallet(&psbt.unsigned_tx, Some(&[input]), None)
.map_err(rpc_err_to_manager_err)?;
let signed_tx = Transaction::consensus_decode(&mut sign_result.hex.as_slice())
.map_err(enc_err_to_manager_err)?;

psbt.inputs[input_index].final_script_sig =
Some(signed_tx.input[input_index].script_sig.clone());
psbt.inputs[input_index].final_script_witness =
Some(signed_tx.input[input_index].witness.clone());

Ok(())
}
}

impl Blockchain for BitcoinCoreProvider {
Expand Down
Loading

0 comments on commit 9da1619

Please sign in to comment.