Sender

Struct Sender 

Source
pub struct Sender(/* private fields */);
Expand description

A struct that a sender of funds uses in combination with a recipient’s PaymentCode in order to send notifications and calculate payment addresses. This is invariant with regard to recipient and needs to be constructed only once per account (unique per BIP32 seed + account).

Implementations§

Source§

impl Sender

Source

pub fn from_seed<C: Signing>( secp: &Secp256k1<C>, seed: &[u8], network: Network, account: u32, ) -> Result<Self, Error>

Construct a sender side from a BIP32 seed.

Examples found in repository?
examples/sending.rs (line 12)
9fn main() -> Result<(), bip351::Error> {
10    let secp = Secp256k1::new();
11
12    let sender = bip351::Sender::from_seed(&secp, &[0xFE], Network::Bitcoin, 0)?;
13
14    let recipient = bip351::PaymentCode::from_str(
15        "pay1qqpsxq4730l4yre4lt3588eyt3f2lwggtfalvtgfns04a8smzkn7yys6xv2gs8",
16    )?;
17
18    // Sender makes sure the recipient supports segwit addresses.
19    let p2wpkh_addr_type = recipient
20        .address_types()
21        .get(&bip351::AddressType::P2wpkh)
22        .unwrap();
23
24    let (notification_txout, sender_recipient_commitment) =
25        sender.notify(&secp, &recipient, 0, p2wpkh_addr_type.clone())?;
26
27    // Here the sender would add `notification_txout` to a transaction and broadcast it.
28    // wallet.broadcast(tx)...
29
30    let payload = notification_txout.script_pubkey.as_bytes();
31    assert_eq!(
32        payload[2..].to_hex(),
33        "505049cb55bb02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f46401"
34    );
35
36    // At this point the recipient is notified. Sender can now send funds to their secret address at index `0`.
37    let recipient_addr_0 = sender.address(&secp, &sender_recipient_commitment, 0)?;
38    assert_eq!(
39        recipient_addr_0.to_string(),
40        "bc1qw7ld5h9tj2ruwxqvetznjfq9g5jyp0gjhrs30w"
41    );
42
43    // wallet.send(&recipient_addr_0, 100000);
44
45    Ok(())
46}
More examples
Hide additional examples
examples/notify.rs (line 31)
10fn main() -> std::io::Result<()> {
11    let secp = bitcoin::secp256k1::Secp256k1::new();
12
13    let payment_code = prompt("Enter the recipient's payment code").unwrap();
14    let payment_code = PaymentCode::from_str(&payment_code).expect("Invalid payment code");
15
16    let sender_seed = prompt("Enter the sender's hex-encoded BIP39 seed").unwrap();
17    let sender_seed: Vec<u8> = FromHex::from_hex(&sender_seed).expect("Not a hex-encoded seed");
18
19    let network = prompt("Enter 0 for mainnet or 1 for testnet").unwrap();
20    let network = match network.as_str() {
21        "0" => Network::Bitcoin,
22        "1" => Network::Testnet,
23        _ => panic!("unknown network"),
24    };
25
26    let recipient_index = prompt("Enter a numerical recipient index").unwrap();
27    let recipient_index: u32 = recipient_index
28        .parse()
29        .expect("Not a valid unsigned integer");
30
31    let sender = Sender::from_seed(&secp, &sender_seed, network, 0).unwrap();
32
33    println!("The recipient supports the following address types:");
34    let accepted_addresses: Vec<_> = payment_code.address_types().iter().collect();
35    for (index, addr_type) in accepted_addresses.iter().enumerate() {
36        println!("({}): {:?}", index, addr_type);
37    }
38
39    let ordinal = prompt("Pick the number next to the address type you want to use").unwrap();
40    let addr_type = accepted_addresses
41        .into_iter()
42        .nth(ordinal.parse().expect("Not a valid integer"))
43        .expect("Index out of range")
44        .clone();
45
46    let (txout, _) = sender
47        .notify(&secp, &payment_code, recipient_index, addr_type)
48        .unwrap();
49    let payload = txout.script_pubkey.as_bytes()[2..].to_hex();
50    println!("The notification OP_RETURN payload is:\n{}", payload);
51
52    Ok(())
53}
Source

pub fn from_master_xprv<C: Signing>( secp: &Secp256k1<C>, master: ExtendedPrivKey, account: u32, ) -> Result<Self, Error>

Construct a sender side from a master extended private key. Not supplying a master key here produces an error.

Source

pub fn notify( &self, secp: &Secp256k1<All>, payment_code: &PaymentCode, recipient_index: u32, address_type: AddressType, ) -> Result<(TxOut, SenderCommitment), Error>

Construct a notification for a payment code. The txout is an OP_RETURN consuming 0 sats. The returned SenderCommitment is used for subsequent interaction with the payment code.

recipient_index must be unique for each recipient as it uniquely defines the relationship between a sender and a recipient.

Examples found in repository?
examples/sending.rs (line 25)
9fn main() -> Result<(), bip351::Error> {
10    let secp = Secp256k1::new();
11
12    let sender = bip351::Sender::from_seed(&secp, &[0xFE], Network::Bitcoin, 0)?;
13
14    let recipient = bip351::PaymentCode::from_str(
15        "pay1qqpsxq4730l4yre4lt3588eyt3f2lwggtfalvtgfns04a8smzkn7yys6xv2gs8",
16    )?;
17
18    // Sender makes sure the recipient supports segwit addresses.
19    let p2wpkh_addr_type = recipient
20        .address_types()
21        .get(&bip351::AddressType::P2wpkh)
22        .unwrap();
23
24    let (notification_txout, sender_recipient_commitment) =
25        sender.notify(&secp, &recipient, 0, p2wpkh_addr_type.clone())?;
26
27    // Here the sender would add `notification_txout` to a transaction and broadcast it.
28    // wallet.broadcast(tx)...
29
30    let payload = notification_txout.script_pubkey.as_bytes();
31    assert_eq!(
32        payload[2..].to_hex(),
33        "505049cb55bb02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f46401"
34    );
35
36    // At this point the recipient is notified. Sender can now send funds to their secret address at index `0`.
37    let recipient_addr_0 = sender.address(&secp, &sender_recipient_commitment, 0)?;
38    assert_eq!(
39        recipient_addr_0.to_string(),
40        "bc1qw7ld5h9tj2ruwxqvetznjfq9g5jyp0gjhrs30w"
41    );
42
43    // wallet.send(&recipient_addr_0, 100000);
44
45    Ok(())
46}
More examples
Hide additional examples
examples/notify.rs (line 47)
10fn main() -> std::io::Result<()> {
11    let secp = bitcoin::secp256k1::Secp256k1::new();
12
13    let payment_code = prompt("Enter the recipient's payment code").unwrap();
14    let payment_code = PaymentCode::from_str(&payment_code).expect("Invalid payment code");
15
16    let sender_seed = prompt("Enter the sender's hex-encoded BIP39 seed").unwrap();
17    let sender_seed: Vec<u8> = FromHex::from_hex(&sender_seed).expect("Not a hex-encoded seed");
18
19    let network = prompt("Enter 0 for mainnet or 1 for testnet").unwrap();
20    let network = match network.as_str() {
21        "0" => Network::Bitcoin,
22        "1" => Network::Testnet,
23        _ => panic!("unknown network"),
24    };
25
26    let recipient_index = prompt("Enter a numerical recipient index").unwrap();
27    let recipient_index: u32 = recipient_index
28        .parse()
29        .expect("Not a valid unsigned integer");
30
31    let sender = Sender::from_seed(&secp, &sender_seed, network, 0).unwrap();
32
33    println!("The recipient supports the following address types:");
34    let accepted_addresses: Vec<_> = payment_code.address_types().iter().collect();
35    for (index, addr_type) in accepted_addresses.iter().enumerate() {
36        println!("({}): {:?}", index, addr_type);
37    }
38
39    let ordinal = prompt("Pick the number next to the address type you want to use").unwrap();
40    let addr_type = accepted_addresses
41        .into_iter()
42        .nth(ordinal.parse().expect("Not a valid integer"))
43        .expect("Index out of range")
44        .clone();
45
46    let (txout, _) = sender
47        .notify(&secp, &payment_code, recipient_index, addr_type)
48        .unwrap();
49    let payload = txout.script_pubkey.as_bytes()[2..].to_hex();
50    println!("The notification OP_RETURN payload is:\n{}", payload);
51
52    Ok(())
53}
Source

pub fn address( &self, secp: &Secp256k1<All>, commitment: &SenderCommitment, addr_index: u64, ) -> Result<Address, Error>

Generate an address for a recipient that has already been notified.

Examples found in repository?
examples/sending.rs (line 37)
9fn main() -> Result<(), bip351::Error> {
10    let secp = Secp256k1::new();
11
12    let sender = bip351::Sender::from_seed(&secp, &[0xFE], Network::Bitcoin, 0)?;
13
14    let recipient = bip351::PaymentCode::from_str(
15        "pay1qqpsxq4730l4yre4lt3588eyt3f2lwggtfalvtgfns04a8smzkn7yys6xv2gs8",
16    )?;
17
18    // Sender makes sure the recipient supports segwit addresses.
19    let p2wpkh_addr_type = recipient
20        .address_types()
21        .get(&bip351::AddressType::P2wpkh)
22        .unwrap();
23
24    let (notification_txout, sender_recipient_commitment) =
25        sender.notify(&secp, &recipient, 0, p2wpkh_addr_type.clone())?;
26
27    // Here the sender would add `notification_txout` to a transaction and broadcast it.
28    // wallet.broadcast(tx)...
29
30    let payload = notification_txout.script_pubkey.as_bytes();
31    assert_eq!(
32        payload[2..].to_hex(),
33        "505049cb55bb02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f46401"
34    );
35
36    // At this point the recipient is notified. Sender can now send funds to their secret address at index `0`.
37    let recipient_addr_0 = sender.address(&secp, &sender_recipient_commitment, 0)?;
38    assert_eq!(
39        recipient_addr_0.to_string(),
40        "bc1qw7ld5h9tj2ruwxqvetznjfq9g5jyp0gjhrs30w"
41    );
42
43    // wallet.send(&recipient_addr_0, 100000);
44
45    Ok(())
46}
Source

pub fn network(&self) -> Network

Get the network used by this sender.

Trait Implementations§

Source§

impl Clone for Sender

Source§

fn clone(&self) -> Sender

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Sender

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Sender

Source§

fn eq(&self, other: &Sender) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for Sender

Source§

impl StructuralPartialEq for Sender

Auto Trait Implementations§

§

impl Freeze for Sender

§

impl RefUnwindSafe for Sender

§

impl Send for Sender

§

impl Sync for Sender

§

impl Unpin for Sender

§

impl UnwindSafe for Sender

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.