Skip to content

Commit

Permalink
Bind to uniffi using proc macros
Browse files Browse the repository at this point in the history
Proc macros let rust-analyzer check that types are compatible
at rust compile time, and thus let downstream projects more easily
depend on bitcoin-ffi.

A couple types needed explicit wrappers in order to use macros.
  • Loading branch information
DanGould committed Nov 13, 2024
1 parent 4cd8e64 commit 6469324
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 175 deletions.
151 changes: 0 additions & 151 deletions src/bitcoin.udl
Original file line number Diff line number Diff line change
@@ -1,152 +1 @@
namespace bitcoin {};

// ------------------------------------------------------------------------
// Core types
// ------------------------------------------------------------------------

interface Script {
constructor(sequence<u8> raw_output_script);

sequence<u8> to_bytes();
};

interface Amount {
[Name=from_sat]
constructor(u64 from_sat);

[Name=from_btc, Throws=ParseAmountError]
constructor(f64 from_btc);

u64 to_sat();

f64 to_btc();
};

interface FeeRate {
[Name=from_sat_per_vb, Throws=FeeRateError]
constructor(u64 sat_per_vb);

[Name=from_sat_per_kwu]
constructor(u64 sat_per_kwu);

u64 to_sat_per_vb_ceil();

u64 to_sat_per_vb_floor();

u64 to_sat_per_kwu();
};

[Custom]
typedef string Txid;

[Custom]
typedef string BlockHash;

dictionary OutPoint {
Txid txid;
u32 vout;
};

dictionary TxIn {
OutPoint previous_output;
Script script_sig;
u32 sequence;
sequence<sequence<u8>> witness;
};

[NonExhaustive]
enum Network {
"Bitcoin",
"Testnet",
"Signet",
"Regtest",
};

[Traits=(Display)]
interface Address {
[Throws=AddressParseError]
constructor(string address, Network network);

[Name=from_script, Throws=FromScriptError]
constructor(Script script, Network network);

Script script_pubkey();

string to_qr_uri();

boolean is_valid_for_network(Network network);
};

dictionary TxOut {
Amount value;
Script script_pubkey;
};

interface Transaction {
[Name=deserialize, Throws=EncodeError]
constructor([ByRef] bytes transaction_bytes);
bytes serialize();
string compute_txid();
u64 total_size();
u64 vsize();
boolean is_coinbase();
boolean is_explicitly_rbf();
boolean is_lock_time_enabled();
i32 version();
u64 weight();
sequence<TxIn> input();
sequence<TxOut> output();
u32 lock_time();
};

// ------------------------------------------------------------------------
// Errors
// ------------------------------------------------------------------------

[Error]
enum AddressParseError {
"Base58",
"Bech32",
"WitnessVersion",
"WitnessProgram",
"UnknownHrp",
"LegacyAddressTooLong",
"InvalidBase58PayloadLength",
"InvalidLegacyPrefix",
"NetworkValidation",
"OtherAddressParseErr",
};

[Error]
interface FromScriptError {
UnrecognizedScript();
WitnessProgram(string error_message);
WitnessVersion(string error_message);
OtherFromScriptErr();
};

[Error]
interface ParseAmountError {
OutOfRange();
TooPrecise();
MissingDigits();
InputTooLarge();
InvalidCharacter(string error_message);
OtherParseAmountErr();
};

[Error]
interface FeeRateError {
ArithmeticOverflow();
};

[Error]
interface EncodeError {
Io();
OversizedVectorAllocation();
InvalidChecksum(string expected, string actual);
NonMinimalVarInt();
ParseFailed();
UnsupportedSegwitFlag(u8 flag);
OtherEncodeErr();
};
10 changes: 5 additions & 5 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bitcoin::amount::ParseAmountError as BitcoinParseAmountError;
use bitcoin::consensus::encode::Error as BitcoinEncodeError;
use bitcoin::hex::DisplayHex;

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum AddressParseError {
#[error("base58 address encoding error")]
Base58,
Expand Down Expand Up @@ -51,13 +51,13 @@ impl From<BitcoinParseError> for AddressParseError {
}
}

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum FeeRateError {
#[error("arithmetic overflow on feerate")]
ArithmeticOverflow,
}

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum FromScriptError {
#[error("script is not a p2pkh, p2sh or witness program")]
UnrecognizedScript,
Expand Down Expand Up @@ -88,7 +88,7 @@ impl From<BitcoinFromScriptError> for FromScriptError {
}
}

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum ParseAmountError {
#[error("amount out of range")]
OutOfRange,
Expand Down Expand Up @@ -125,7 +125,7 @@ impl From<BitcoinParseAmountError> for ParseAmountError {
}
}

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum EncodeError {
#[error("io error")]
Io,
Expand Down
Loading

0 comments on commit 6469324

Please sign in to comment.