Skip to content

Commit

Permalink
Sign p2c output
Browse files Browse the repository at this point in the history
  • Loading branch information
Yamaguchi committed Aug 13, 2024
1 parent e55e2f1 commit d691fdf
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
55 changes: 50 additions & 5 deletions crates/wallet/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use miniscript::{
psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier},
Descriptor, DescriptorPublicKey,
};
use tapyrus::hashes::{Hash, HashEngine};
use tapyrus::sighash::{EcdsaSighashType, TapSighashType};
use tapyrus::{
absolute, psbt, script::color_identifier::ColorIdentifier, Address, Block, FeeRate, MalFixTxid,
Expand All @@ -37,6 +36,11 @@ use tapyrus::{
use tapyrus::{address::NetworkChecked, secp256k1::Scalar};
use tapyrus::{consensus::encode::serialize, transaction, BlockHash, Psbt};
use tapyrus::{constants::mainnet_genesis_block, constants::testnet_genesis_block, Amount};
use tapyrus::{
hashes::{Hash, HashEngine},
secp256k1::SecretKey,
PrivateKey,
};
use tapyrus::{
secp256k1::{All, Secp256k1},
TxIn,
Expand Down Expand Up @@ -442,6 +446,8 @@ pub enum GenerateContractError {
/// public key(payment base).
public_key: PublicKey,
},
/// Can not create private key.
InvalidPrivateKey,
}

impl fmt::Display for GenerateContractError {
Expand All @@ -457,6 +463,9 @@ impl fmt::Display for GenerateContractError {
write!(f, "invalid payment base ({})", public_key)
}
GenerateContractError::InvalidAddress(e) => e.fmt(f),
GenerateContractError::InvalidPrivateKey => {
write!(f, "invalid private key")
}
}
}
}
Expand Down Expand Up @@ -1035,6 +1044,38 @@ impl Wallet {
Ok(script)
}

fn create_pay_to_contract_private_key(
&self,
payment_base: &PublicKey,
contract: Vec<u8>,
) -> Result<PrivateKey, GenerateContractError> {
if contract.is_empty() {
return Err(GenerateContractError::ContractTooSmall { length: 0 });
}
if contract.len() > CONTRACT_MAX_SIZE {
return Err(GenerateContractError::ContractTooLarge {
length: contract.len(),
});
}

let index = match self
.indexed_graph
.index
.index_of_spk(ScriptBuf::new_p2pkh(&payment_base.pubkey_hash()).as_script())
{
Some(i) => i,
None => {
return Err(GenerateContractError::InvalidPublicKey {
public_key: payment_base.clone(),
})
}
};
let commitment: Scalar = self.create_pay_to_contract_commitment(payment_base, contract);
let sk = SecretKey::from_slice(&commitment.to_be_bytes())
.map_err(|_| GenerateContractError::InvalidPrivateKey)?;
Ok(PrivateKey::new(sk, self.network()))
}

/// Generate pay-to-contract public key with the specified content hash.
pub fn pay_to_contract_key(
&self,
Expand Down Expand Up @@ -2388,10 +2429,14 @@ impl Wallet {
}

fn get_descriptor_for_txout(&self, txout: &TxOut) -> Option<DerivedDescriptor> {
let (keychain, child) = self
.indexed_graph
.index
.index_of_spk(&txout.script_pubkey)?;
let payment_base = self.spk_index().p2c_spk(&txout.script_pubkey);
let script_pubkey_ref = if let Some(p) = payment_base {
p
} else {
&txout.script_pubkey
};

let (keychain, child) = self.indexed_graph.index.index_of_spk(script_pubkey_ref)?;
let descriptor = self.get_descriptor_for_keychain(keychain);
descriptor.at_derivation_index(child).ok()
}
Expand Down
3 changes: 2 additions & 1 deletion crates/wallet/src/wallet/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ use tapyrus::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpriv};
use tapyrus::hashes::hash160;
use tapyrus::secp256k1::Message;
use tapyrus::sighash::{EcdsaSighashType, TapSighash, TapSighashType};
use tapyrus::{ecdsa, psbt, sighash, taproot};
use tapyrus::{ecdsa, psbt, sighash, taproot, Script, ScriptBuf};
use tapyrus::{key::XOnlyPublicKey, secp256k1};
use tapyrus::{PrivateKey, Psbt, PublicKey};

Expand Down Expand Up @@ -448,6 +448,7 @@ impl InputSigner for SignerWrapper<PrivateKey> {
}

let pubkey = PublicKey::from_private_key(secp, self);
let utxo = psbt.get_utxo_for(input_index);

if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
return Ok(());
Expand Down
13 changes: 12 additions & 1 deletion crates/wallet/tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ fn test_create_tx_with_contract() {
builder
.add_recipient(addr.script_pubkey(), Amount::from_tap(25_000))
.add_contract_utxo(OutPoint { txid, vout: 0 });
let psbt = builder.finish().unwrap();
let mut psbt = builder.finish().unwrap();
check_fee!(wallet, psbt);
assert_eq!(psbt.unsigned_tx.output.len(), 2);
let sent_received = wallet.sent_and_received(
Expand All @@ -1412,6 +1412,17 @@ fn test_create_tx_with_contract() {
Amount::from_tap(25_000) - psbt.fee_amount().unwrap()
)
);

let finished = wallet.sign(
&mut psbt,
SignOptions {
trust_witness_utxo: true,
..Default::default()
},
);

let ret = finished.unwrap();
assert!(ret, "transaction should be signed");
}

// TODO: Fix this test
Expand Down

0 comments on commit d691fdf

Please sign in to comment.