Skip to content

Commit

Permalink
Create ContractSignerProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Jan 13, 2024
1 parent f303972 commit ba753bc
Show file tree
Hide file tree
Showing 30 changed files with 1,189 additions and 420 deletions.
182 changes: 113 additions & 69 deletions bitcoin-rpc-provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::sync::{Arc, Mutex};
use std::time::Duration;

use bitcoin::consensus::encode::Error as EncodeError;
use bitcoin::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine};
use bitcoin::psbt::PartiallySignedTransaction;
use bitcoin::secp256k1::rand::thread_rng;
use bitcoin::secp256k1::{PublicKey, SecretKey};
Expand All @@ -18,7 +19,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 @@ -102,7 +103,7 @@ impl BitcoinCoreProvider {

pub fn new_from_rpc_client(rpc_client: Client) -> Self {
let client = Arc::new(Mutex::new(rpc_client));
let mut fees: HashMap<ConfirmationTarget, AtomicU32> = HashMap::new();
let mut fees: HashMap<ConfirmationTarget, AtomicU32> = HashMap::with_capacity(7);
fees.insert(ConfirmationTarget::OnChainSweep, AtomicU32::new(5000));
fees.insert(
ConfirmationTarget::MaxAllowedNonAnchorChannelRemoteFee,
Expand Down Expand Up @@ -168,7 +169,46 @@ 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_signer_key_id(&self, _is_offer_party: bool, temp_id: [u8; 32]) -> [u8; 32] {
temp_id // fixme not safe
}

fn derive_contract_signer(&self, keys_id: [u8; 32]) -> Result<Self::Signer, ManagerError> {
// todo not a safe way to get the seed, not sure what to do here
let wallet_info = self
.client
.lock()
.unwrap()
.get_wallet_info()
.map_err(rpc_err_to_manager_err)?;
let seed = wallet_info.hd_seed_id.unwrap().to_vec();
let mut hmac = HmacEngine::<sha256::Hash>::new(&seed);
hmac.input(&keys_id);
let secret_bytes = Hmac::from_engine(hmac).into_inner();
let secret_key = SecretKey::from_slice(&secret_bytes).expect("Secret key is valid");

// import key
let network = self.get_network()?;
self.client
.lock()
.unwrap()
.import_private_key(
&PrivateKey {
compressed: true,
network,
inner: secret_key,
},
None,
Some(false),
)
.map_err(rpc_err_to_manager_err)?;

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 @@ -182,76 +222,14 @@ impl Signer for BitcoinCoreProvider {
.lock()
.unwrap()
.dump_private_key(&address)
.map_err(|e| {
eprintln!("error getting sk for pk {e:?}");
e
})
.map_err(rpc_err_to_manager_err)?;
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[outpoint.vout as usize].clone())
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT input".to_string(),
))
}
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT input".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 @@ -271,6 +249,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 @@ -321,6 +313,58 @@ 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[outpoint.vout as usize].clone())
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT input".to_string(),
))
}
} else {
Err(ManagerError::InvalidParameters(
"No TxOut for PSBT input".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
4 changes: 3 additions & 1 deletion dlc-manager/src/channel/offered_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use secp256k1_zkp::PublicKey;

use crate::{
contract::offered_contract::OfferedContract, conversion_utils::get_tx_input_infos,
error::Error, ChannelId, ContractId,
error::Error, ChannelId, ContractId, KeysId,
};

use super::party_points::PartyBasePoints;
Expand Down Expand Up @@ -83,6 +83,7 @@ impl OfferedChannel {
pub fn from_offer_channel(
offer_channel: &OfferChannel,
counter_party: PublicKey,
keys_id: KeysId,
) -> Result<(OfferedChannel, OfferedContract), Error> {
let channel = OfferedChannel {
offered_contract_id: offer_channel.temporary_contract_id,
Expand Down Expand Up @@ -128,6 +129,7 @@ impl OfferedChannel {
.map(|x| x.into())
.collect(),
total_collateral: offer_channel.contract_info.get_total_collateral(),
keys_id,
};

Ok((channel, contract))
Expand Down
22 changes: 11 additions & 11 deletions dlc-manager/src/channel/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ impl_dlc_writeable!(SignedChannel, {

impl_dlc_writeable_enum!(
SignedChannelState,;
(0, Established, {(signed_contract_id, writeable), (own_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (counter_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (buffer_transaction, writeable), (is_offer, writeable)}),
(1, SettledOffered, {(counter_payout, writeable), (next_per_update_point, writeable), (timeout, writeable)}),
(2, SettledReceived, {(own_payout, writeable), (counter_next_per_update_point, writeable)}),
(3, SettledAccepted, {(counter_next_per_update_point, writeable), (own_next_per_update_point, writeable), (settle_tx, writeable), (own_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable)}),
(4, SettledConfirmed, {(settle_tx, writeable), (counter_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (own_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (counter_next_per_update_point, writeable), (own_next_per_update_point, writeable), (timeout, writeable), (own_payout, writeable) }),
(5, Settled, {(settle_tx, writeable), (counter_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (own_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature})}),
(6, RenewOffered, {(offered_contract_id, writeable), (counter_payout, writeable), (is_offer, writeable), (offer_next_per_update_point, writeable), (timeout, writeable)}),
(7, RenewAccepted, {(contract_id, writeable), (offer_per_update_point, writeable), (accept_per_update_point, writeable), (buffer_transaction, writeable), (buffer_script_pubkey, writeable), (accept_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable)}),
(8, RenewConfirmed, {(contract_id, writeable), (offer_per_update_point, writeable), (accept_per_update_point, writeable), (buffer_transaction, writeable), (buffer_script_pubkey, writeable), (offer_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (accept_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable)}),
(9, Closing, {(buffer_transaction, writeable), (signed_cet, writeable), (contract_id, writeable), (attestations, vec)}),
(0, Established, {(signed_contract_id, writeable), (own_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (counter_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (buffer_transaction, writeable), (is_offer, writeable), (keys_id, writeable)}),
(1, SettledOffered, {(counter_payout, writeable), (next_per_update_point, writeable), (timeout, writeable), (keys_id, writeable)}),
(2, SettledReceived, {(own_payout, writeable), (counter_next_per_update_point, writeable), (keys_id, writeable)}),
(3, SettledAccepted, {(counter_next_per_update_point, writeable), (own_next_per_update_point, writeable), (settle_tx, writeable), (own_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable), (keys_id, writeable)}),
(4, SettledConfirmed, {(settle_tx, writeable), (counter_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (own_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (counter_next_per_update_point, writeable), (own_next_per_update_point, writeable), (timeout, writeable), (own_payout, writeable), (keys_id, writeable) }),
(5, Settled, {(settle_tx, writeable), (counter_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (own_settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (keys_id, writeable)}),
(6, RenewOffered, {(offered_contract_id, writeable), (counter_payout, writeable), (is_offer, writeable), (offer_next_per_update_point, writeable), (timeout, writeable), (keys_id, writeable)}),
(7, RenewAccepted, {(contract_id, writeable), (offer_per_update_point, writeable), (accept_per_update_point, writeable), (buffer_transaction, writeable), (buffer_script_pubkey, writeable), (accept_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable), (keys_id, writeable)}),
(8, RenewConfirmed, {(contract_id, writeable), (offer_per_update_point, writeable), (accept_per_update_point, writeable), (buffer_transaction, writeable), (buffer_script_pubkey, writeable), (offer_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (accept_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable), (keys_id, writeable)}),
(9, Closing, {(buffer_transaction, writeable), (signed_cet, writeable), (contract_id, writeable), (attestations, vec), (keys_id, writeable)}),
(10, ClosedPunished, { (punishment_txid, writeable) }),
(11, CollaborativeCloseOffered, { (counter_payout, writeable), (offer_signature, writeable), (close_tx, writeable), (timeout, writeable) })
(11, CollaborativeCloseOffered, { (counter_payout, writeable), (offer_signature, writeable), (close_tx, writeable), (timeout, writeable), (keys_id, writeable) })
;;(12, Closed), (13, CounterClosed), (14, CollaborativelyClosed)
);

Expand Down
Loading

0 comments on commit ba753bc

Please sign in to comment.