wip: dkg contract interactions

This commit is contained in:
soju-drinker
2023-10-05 09:52:03 -04:00
committed by Jacinta Ferrant
parent fb2309f998
commit 5f6c8427d5
3 changed files with 383 additions and 14 deletions

199
Cargo.lock generated
View File

@@ -445,7 +445,7 @@ version = "0.64.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"cexpr",
"clang-sys",
"lazy_static",
@@ -467,6 +467,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]]
name = "bitvec"
version = "1.0.1"
@@ -667,7 +673,7 @@ version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"textwrap",
"unicode-width",
]
@@ -793,6 +799,16 @@ dependencies = [
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
@@ -1209,6 +1225,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.1.0"
@@ -1224,7 +1255,7 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"fuchsia-zircon-sys",
]
@@ -1502,7 +1533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584"
dependencies = [
"base64 0.13.1",
"bitflags",
"bitflags 1.3.2",
"bytes",
"headers-core",
"http",
@@ -1679,6 +1710,19 @@ dependencies = [
"tokio-rustls",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "iana-time-zone"
version = "0.1.53"
@@ -2107,6 +2151,24 @@ dependencies = [
"version_check",
]
[[package]]
name = "native-tls"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "net2"
version = "0.2.38"
@@ -2124,7 +2186,7 @@ version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"cc",
"cfg-if 1.0.0",
"libc",
@@ -2222,6 +2284,50 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openssl"
version = "0.10.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
dependencies = [
"bitflags 2.4.0",
"cfg-if 1.0.0",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
]
[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "overload"
version = "0.1.1"
@@ -2384,7 +2490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e1f879b2998099c2d69ab9605d145d5b661195627eccc680002c4918a7fb6fa"
dependencies = [
"autocfg",
"bitflags",
"bitflags 1.3.2",
"cfg-if 1.0.0",
"concurrent-queue",
"libc",
@@ -2644,7 +2750,7 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
@@ -2653,7 +2759,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
@@ -2695,9 +2801,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "reqwest"
version = "0.11.20"
version = "0.11.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
dependencies = [
"base64 0.21.0",
"bytes",
@@ -2709,10 +2815,12 @@ dependencies = [
"http-body",
"hyper",
"hyper-rustls",
"hyper-tls",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
@@ -2721,7 +2829,9 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
"system-configuration",
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tower-service",
"url",
@@ -2830,7 +2940,7 @@ version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"byteorder",
"fallible-iterator",
"fallible-streaming-iterator",
@@ -2905,7 +3015,7 @@ version = "0.37.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
@@ -2965,6 +3075,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
@@ -3012,6 +3131,29 @@ dependencies = [
"cc",
]
[[package]]
name = "security-framework"
version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "semver"
version = "0.9.0"
@@ -3407,6 +3549,7 @@ dependencies = [
"libstackerdb",
"p256k1",
"rand_core 0.6.4",
"reqwest",
"secp256k1",
"serde",
"serde_derive",
@@ -3416,6 +3559,7 @@ dependencies = [
"slog-json",
"slog-term",
"stacks-common",
"stackslib",
"thiserror",
"toml",
"tracing",
@@ -3580,6 +3724,27 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "tap"
version = "1.0.1"
@@ -3790,6 +3955,16 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.24.1"

View File

@@ -28,6 +28,7 @@ libsigner = { path = "../libsigner" }
libstackerdb = { path = "../libstackerdb" }
p256k1 = "5.5"
rand_core = "0.6"
reqwest = { version = "0.11.22", features = ["blocking", "json"] }
serde = "1"
serde_derive = "1"
serde_stacker = "0.1"
@@ -35,6 +36,7 @@ slog = { version = "2.5.2", features = [ "max_level_trace" ] }
slog-json = { version = "2.3.0", optional = true }
slog-term = "2.6.0"
stacks-common = { path = "../stacks-common" }
stackslib = { path = "../stackslib"}
thiserror = "1.0"
toml = "0.5.6"
tracing = "0.1.37"

View File

@@ -1,10 +1,22 @@
use bincode::Error as BincodeError;
use blockstack_lib::chainstate::stacks::{
StacksTransaction, StacksTransactionSigner, TransactionAnchorMode, TransactionAuth,
TransactionContractCall, TransactionPayload, TransactionPostConditionMode,
TransactionSpendingCondition, TransactionVersion,
};
use clarity::vm::Value as ClarityValue;
use clarity::vm::{ClarityName, ContractName};
use hashbrown::HashMap;
use libsigner::{RPCError, SignerSession, StackerDBSession};
use libstackerdb::{Error as StackerDBError, StackerDBChunkAckData, StackerDBChunkData};
use serde_json::json;
use slog::{slog_debug, slog_warn};
use stacks_common::types::chainstate::StacksPrivateKey;
use stacks_common::{debug, warn};
use stacks_common::{
codec::StacksMessageCodec,
debug,
types::chainstate::{StacksAddress, StacksPrivateKey, StacksPublicKey},
warn,
};
use wsts::net::{Message, Packet};
use crate::config::Config;
@@ -29,6 +41,9 @@ pub enum ClientError {
/// Stacker-db instance rejected the chunk
#[error("Stacker-db rejected the chunk. Reason: {0}")]
PutChunkRejected(String),
/// A request sent to the Stacks Node sent an invalid response
#[error("Unable to parse JSON response from url {0}, error response was {1}")]
UnableToParseResponseJSON(String, String),
}
/// TODO: Add stacks node communication to this
@@ -55,6 +70,34 @@ impl From<&Config> for StacksClient {
}
}
/// Trait used to make interact with Clarity contracts for use in the signing process
pub trait InteractWithStacksContracts {
/// Submits a transaction to a node RPC server
fn submit_tx(http_origin: &str, tx: &Vec<u8>) -> String;
/// Call read only tx
fn read_only_contract_call(
http_origin: &str,
sender: &StacksAddress,
contract_addr: &StacksAddress,
contract_name: &str,
function_name: &str,
function_args: &[ClarityValue],
) -> String;
/// Creates a contract call transaction
fn transaction_contract_call(
sender: &StacksPrivateKey,
nonce: u64,
contract_addr: &StacksAddress,
contract_name: &str,
function_name: &str,
function_args: &[ClarityValue],
tx_version: TransactionVersion,
chain_id: u32,
) -> Vec<u8>;
}
impl StacksClient {
/// Sends messages to the stacker-db
pub fn send_message(
@@ -99,8 +142,157 @@ impl StacksClient {
// See: https://github.com/stacks-network/stacks-blockchain/issues/3921
SLOTS_PER_USER
}
fn seralize_sign_tx_anchor_mode_version(
payload: TransactionPayload,
sender: &StacksPrivateKey,
payer: Option<&StacksPrivateKey>,
sender_nonce: u64,
payer_nonce: Option<u64>,
tx_fee: u64,
anchor_mode: TransactionAnchorMode,
version: TransactionVersion,
chain_id: u32,
) -> Vec<u8> {
let mut sender_spending_condition = TransactionSpendingCondition::new_singlesig_p2pkh(
StacksPublicKey::from_private(sender),
)
.expect("Failed to create p2pkh spending condition from public key.");
sender_spending_condition.set_nonce(sender_nonce);
let auth = match (payer, payer_nonce) {
(Some(payer), Some(payer_nonce)) => {
let mut payer_spending_condition =
TransactionSpendingCondition::new_singlesig_p2pkh(
StacksPublicKey::from_private(payer),
)
.expect("Failed to create p2pkh spending condition from public key.");
payer_spending_condition.set_nonce(payer_nonce);
payer_spending_condition.set_tx_fee(tx_fee);
TransactionAuth::Sponsored(sender_spending_condition, payer_spending_condition)
}
_ => {
sender_spending_condition.set_tx_fee(tx_fee);
TransactionAuth::Standard(sender_spending_condition)
}
};
let mut unsigned_tx = StacksTransaction::new(version, auth, payload);
unsigned_tx.anchor_mode = anchor_mode;
unsigned_tx.post_condition_mode = TransactionPostConditionMode::Allow;
unsigned_tx.chain_id = chain_id;
let mut tx_signer = StacksTransactionSigner::new(&unsigned_tx);
tx_signer.sign_origin(sender).unwrap();
if let (Some(payer), Some(_)) = (payer, payer_nonce) {
tx_signer.sign_sponsor(payer).unwrap();
}
let mut buf = vec![];
tx_signer
.get_tx()
.unwrap()
.consensus_serialize(&mut buf)
.unwrap();
buf
}
}
impl InteractWithStacksContracts for StacksClient {
fn transaction_contract_call(
sender: &StacksPrivateKey,
nonce: u64,
contract_addr: &StacksAddress,
contract_name: &str,
function_name: &str,
function_args: &[ClarityValue],
tx_version: TransactionVersion,
chain_id: u32,
) -> Vec<u8> {
let contract_name = ContractName::from(contract_name);
let function_name = ClarityName::from(function_name);
let payload = TransactionContractCall {
address: contract_addr.clone(),
contract_name,
function_name,
function_args: function_args.iter().map(|x| x.clone()).collect(),
};
let tx_fee = 0;
Self::seralize_sign_tx_anchor_mode_version(
payload.into(),
sender,
None,
nonce,
None,
tx_fee,
TransactionAnchorMode::OnChainOnly,
tx_version,
chain_id,
)
}
fn submit_tx(http_origin: &str, tx: &Vec<u8>) -> String {
let client = reqwest::blocking::Client::new();
let path = format!("{http_origin}/v2/transactions");
let res = client
.post(&path)
.header("Content-Type", "application/octet-stream")
.body(tx.clone())
.send()
.unwrap();
if res.status().is_success() {
let res: String = res.json().unwrap();
assert_eq!(
res,
StacksTransaction::consensus_deserialize(&mut &tx[..])
.unwrap()
.txid()
.to_string()
);
return res;
} else {
// FIXME (https://github.com/stacks-network/stacks-blockchain/issues/3993): this needs to handled better
eprintln!("Submit tx error: {}", res.text().unwrap());
panic!("");
}
}
fn read_only_contract_call(
http_origin: &str,
sender: &StacksAddress,
contract_addr: &StacksAddress,
contract_name: &str,
function_name: &str,
function_args: &[ClarityValue],
) -> String {
let body = json!({
"sender": sender.to_string(),
"arguments": function_args
})
.to_string();
let client = reqwest::blocking::Client::new();
let path = format!(
"{http_origin}/v2/contracts/call-read/{contract_addr}/{contract_name}/{function_name}"
);
let res = client
.post(&path)
.header("Content-TYpe", "application/json")
.body(body)
.send()
.unwrap();
if res.status().is_success() {
let res: String = res.json().unwrap();
return res;
} else {
// FIXME (https://github.com/stacks-network/stacks-blockchain/issues/3993): this needs to handled better
eprintln!("Submit tx error: {}", res.text().unwrap());
panic!("");
}
}
}
/// Helper function to determine the slot ID for the provided stacker-db writer id and the message type
fn slot_id(id: u32, message: &Message) -> u32 {
let slot_id = match message {