Skip to content

Commit

Permalink
feat: add more protobuf types part 2 (#577)
Browse files Browse the repository at this point in the history
* Add more common types
* Add some request types
* Move the bitcoin and generic crypto stuff to their own packages
  • Loading branch information
djordon committed Sep 26, 2024
1 parent 36a75c8 commit 9c55459
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 68 deletions.
21 changes: 21 additions & 0 deletions protobufs/bitcoin/bitcoin.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
syntax = "proto3";

package bitcoin;

import "crypto/common.proto";

// The id for a transaction on the bitcoin blockchain.
message BitcoinTxid {
crypto.Uint256 txid = 1;
}

// A bitcoin block hash.
message BitcoinBlockHash {
crypto.Uint256 block_hash = 1;
}

// A pointer to a specific output in a bitcoin transaction.
message OutPoint {
BitcoinTxid txid = 1;
uint32 vout = 2;
}
36 changes: 36 additions & 0 deletions protobufs/crypto/common.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
syntax = "proto3";

package crypto;

/// A type representing a 256-bit integer.
message Uint256 {
// These are the 64 bits of the 256-bit integer from bits 0-63.
fixed64 bits_part0 = 1;
// These are the 64 bits of the 256-bit integer from bits 64-127.
fixed64 bits_part1 = 2;
// These are the 64 bits of the 256-bit integer from bits 128-191.
fixed64 bits_part2 = 3;
// These are the 64 bits of the 256-bit integer from bits 192-255.
fixed64 bits_part3 = 4;
}

/// Represents a public key type for the secp256k1 elliptic curve.
message PublicKey {
// The x-coordinate of the public key.
Uint256 x_only_public_key = 1;
// Represents the parity bit of the public key. True means the parity is
// odd, while false means the parity is even.
bool parity_is_odd = 2;
}

// This is a recoverable signature representation. It is nonstandard and
// defined by the libsecp256k1 library.
message RecoverableSignature {
// These are the first 256-bits of the 64 byte signature part, so bits 0-255.
Uint256 lower_bits = 1;
// These are the last 256-bits of the 64 byte signature part, so bits 256-511.
Uint256 upper_bits = 2;
// A tag used for recovering the public key from a compact signature. It
// must be one of the values 0-3.
int32 recovery_id = 3;
}
40 changes: 23 additions & 17 deletions protobufs/stacks/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@ syntax = "proto3";

package stacks;

/// A type representing a 256-bit integer.
message Uint256 {
// These are the 64 bits of the 256-bit integer from bits 0-63.
fixed64 bits_part0 = 1;
// These are the 64 bits of the 256-bit integer from bits 64-127.
fixed64 bits_part1 = 2;
// These are the 64 bits of the 256-bit integer from bits 128-191.
fixed64 bits_part2 = 3;
// These are the 64 bits of the 256-bit integer from bits 192-255.
fixed64 bits_part3 = 4;
import "crypto/common.proto";

// Represents a standard address on the Stacks blockchain
message StacksAddress {
// The consensus serialized bytes of the Stacks address defined in
// SIP-005.
bytes address = 1;
}

// This type maps to the StacksBlockId in the stackslib Rust crate.
message StacksBlockId {
crypto.Uint256 block_id = 1;
}

// The protobuf representation of the clarity::vm::types::PrincipalData
// type. It represents either a standard Stacks Address or a contract
// address.
message StacksPrincipal {
// The consensus serialized bytes of the Stacks PrincipalData.
bytes data = 1;
}

/// Represents a public key type for the secp256k1 elliptic curve.
message PublicKey {
// The x-coordinate of the public key.
Uint256 x_only_public_key = 1;
// Represents the parity bit of the public key. True means the parity is
// odd, while false means the parity is even.
bool parity_is_odd = 2;
// The id for a transaction on the stacks blockchain.
message StacksTxid {
crypto.Uint256 txid = 1;
}
29 changes: 15 additions & 14 deletions protobufs/stacks/signer/v1/decisions.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ syntax = "proto3";

package stacks.signer.v1;

import "bitcoin/bitcoin.proto";
import "crypto/common.proto";
import "stacks/common.proto";

// Represents a decision to accept or reject a deposit request.
message SignerDepositDecision {
// The bitcoin transaction ID of the transaction containing the deposit
// request. It must be 32 bytes.
BitcoinTxid txid = 1;
bitcoin.BitcoinTxid txid = 1;
// Index of the deposit request UTXO.
uint32 output_index = 2;
// Whether or not the signer has accepted the deposit request.
Expand All @@ -21,25 +23,24 @@ message SignerWithdrawDecision {
uint64 request_id = 1;
// The Stacks block ID of the Stacks block containing the request. It
// must be 32 bytes.
StacksBlockId block_id = 2;
stacks.StacksBlockId block_id = 2;
// The stacks transaction ID that lead to the creation of the
// withdrawal request.
StacksTxid txid = 3;
stacks.StacksTxid txid = 3;
// Whether or not the signer has accepted the withdrawal request.
bool accepted = 4;
}

// The id for a transaction on the stacks blockchain.
message StacksTxid {
stacks.Uint256 txid = 1;
// Represents an acknowledgment of a signed Bitcoin transaction.
message BitcoinTransactionSignAck {
// The ID of the acknowledged transaction.
bitcoin.BitcoinTxid txid = 1;
}

// The id for a transaction on the bitcoin blockchain.
message BitcoinTxid {
stacks.Uint256 txid = 1;
}

// This type maps to the StacksBlockId in the stackslib Rust crate.
message StacksBlockId {
stacks.Uint256 block_id = 1;
// Represents a signature of a Stacks transaction.
message StacksTransactionSignature {
// Id of the signed transaction.
stacks.StacksTxid txid = 1;
// A recoverable ECDSA signature over the transaction.
crypto.RecoverableSignature signature = 2;
}
80 changes: 80 additions & 0 deletions protobufs/stacks/signer/v1/requests.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
syntax = "proto3";

package stacks.signer.v1;

import "bitcoin/bitcoin.proto";
import "crypto/common.proto";
import "stacks/common.proto";

// Represents a request to sign a Bitcoin transaction.
message BitcoinTransactionSignRequest {
// The transaction.
bytes tx = 1;
// The aggregate key used to sign the transaction,
crypto.PublicKey aggregate_key = 2;
}

// Represents a request to sign a Stacks transaction.
message StacksTransactionSignRequest {
// The aggregate public key that will sign the transaction.
crypto.PublicKey aggregate_key = 1;
// The contract call transaction to sign.
// pub contract_call: ContractCall,
// The nonce to use for the transaction.
uint64 nonce = 3;
// The transaction fee in microSTX.
uint64 tx_fee = 4;
// The expected digest of the transaction than needs to be signed.
// It's essentially a hash of the contract call struct, the nonce, the
// tx_fee and a few other things.
crypto.Uint256 digest = 5;
}

// A complete-deposit contract call on Stacks.
message CompleteDeposit {
// The outpoint of the bitcoin UTXO that was spent as a deposit for
// sBTC.
bitcoin.OutPoint outpoint = 1;
// The amount of sats swept in by the signers when they moved in the
// above UTXO.
uint64 amount = 2;
// The address where the newly minted sBTC will be deposited.
stacks.StacksPrincipal recipient = 3;
// The address that deployed the sBTC smart contract containing the
// complete-deposit contract call.
stacks.StacksAddress deployer = 4;
// The transaction ID for the sweep transaction that moved the deposit
// UTXO into the signers' UTXO. One of the inputs to the sweep
// transaction must be the above `outpoint`.
bitcoin.BitcoinTxid sweep_txid = 5;
// The block hash of the bitcoin block that contains a sweep
// transaction with the above `outpoint` as one of its inputs.
bitcoin.BitcoinBlockHash sweep_block_hash = 6;
// The block height associated with the above bitcoin block hash.
uint64 sweep_block_height = 7;
}

// The `accept-withdrawal-request` contract call on the stacks blockchain.
message AcceptWithdrawal {
// The ID of the withdrawal request generated by the
// `initiate-withdrawal-request` function in the sbtc-withdrawal smart
// contract.
uint64 request_id = 1;
// The outpoint of the bitcoin UTXO that was spent to fulfill the
// withdrawal request.
bitcoin.OutPoint outpoint = 2;
// The fee that was spent to the bitcoin miner when fulfilling the
// withdrawal request.
uint64 tx_fee = 3;
// A bitmap of how the signers voted. This structure supports up to
// 128 distinct signers. Here, we assume that a 1 (or true) implies
// that the signer voted *against* the transaction.
repeated bool signer_bitmap = 4;
// The address that deployed the contract.
stacks.StacksAddress deployer = 5;
// The block hash of the bitcoin block that contains a sweep
// transaction with the above `outpoint` as one of its outputs.
bitcoin.BitcoinBlockHash sweep_block_hash = 6;
// The block height associated with the above bitcoin block hash.
uint64 sweep_block_height = 7;
}
7 changes: 5 additions & 2 deletions signer/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@ pub fn compile_protos() {
.unwrap();

let protos = [
"protobufs/bitcoin/bitcoin.proto",
"protobufs/crypto/common.proto",
"protobufs/stacks/common.proto",
"protobufs/stacks/signer/v1/decisions.proto",
"protobufs/stacks/signer/v1/requests.proto",
]
.map(|path| workingdir.join(path));

println!("cargo:rerun-if-changed=protobufs/stacks/signer/");
println!("cargo:rerun-if-changed=protobufs/");

// Compile protocol buffers
tonic_build::configure()
.build_server(true)
.build_client(true)
.out_dir(workingdir.join("signer/src/proto/generated/"))
.include_file("mod.rs")
.type_attribute("stacks.Uint256", "#[derive(Copy)]")
.type_attribute("crypto.Uint256", "#[derive(Copy)]")
.compile(&protos, &[workingdir.join("protobufs")])
.expect("Unable to compile protocol buffers");
}
24 changes: 24 additions & 0 deletions signer/src/proto/generated/bitcoin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// This file is @generated by prost-build.
/// The id for a transaction on the bitcoin blockchain.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BitcoinTxid {
#[prost(message, optional, tag = "1")]
pub txid: ::core::option::Option<super::crypto::Uint256>,
}
/// A bitcoin block hash.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BitcoinBlockHash {
#[prost(message, optional, tag = "1")]
pub block_hash: ::core::option::Option<super::crypto::Uint256>,
}
/// A pointer to a specific output in a bitcoin transaction.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct OutPoint {
#[prost(message, optional, tag = "1")]
pub txid: ::core::option::Option<BitcoinTxid>,
#[prost(uint32, tag = "2")]
pub vout: u32,
}
47 changes: 47 additions & 0 deletions signer/src/proto/generated/crypto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// This file is @generated by prost-build.
/// / A type representing a 256-bit integer.
#[derive(Copy)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Uint256 {
/// These are the 64 bits of the 256-bit integer from bits 0-63.
#[prost(fixed64, tag = "1")]
pub bits_part0: u64,
/// These are the 64 bits of the 256-bit integer from bits 64-127.
#[prost(fixed64, tag = "2")]
pub bits_part1: u64,
/// These are the 64 bits of the 256-bit integer from bits 128-191.
#[prost(fixed64, tag = "3")]
pub bits_part2: u64,
/// These are the 64 bits of the 256-bit integer from bits 192-255.
#[prost(fixed64, tag = "4")]
pub bits_part3: u64,
}
/// / Represents a public key type for the secp256k1 elliptic curve.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PublicKey {
/// The x-coordinate of the public key.
#[prost(message, optional, tag = "1")]
pub x_only_public_key: ::core::option::Option<Uint256>,
/// Represents the parity bit of the public key. True means the parity is
/// odd, while false means the parity is even.
#[prost(bool, tag = "2")]
pub parity_is_odd: bool,
}
/// This is a recoverable signature representation. It is nonstandard and
/// defined by the libsecp256k1 library.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RecoverableSignature {
/// These are the first 256-bits of the 64 byte signature part, so bits 0-255.
#[prost(message, optional, tag = "1")]
pub lower_bits: ::core::option::Option<Uint256>,
/// These are the last 256-bits of the 64 byte signature part, so bits 256-511.
#[prost(message, optional, tag = "2")]
pub upper_bits: ::core::option::Option<Uint256>,
/// A tag used for recovering the public key from a compact signature. It
/// must be one of the values 0-3.
#[prost(int32, tag = "3")]
pub recovery_id: i32,
}
6 changes: 6 additions & 0 deletions signer/src/proto/generated/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
// This file is @generated by prost-build.
pub mod bitcoin {
include!("bitcoin.rs");
}
pub mod crypto {
include!("crypto.rs");
}
pub mod stacks {
include!("stacks.rs");
pub mod signer {
Expand Down
Loading

0 comments on commit 9c55459

Please sign in to comment.