mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-16 17:07:35 +00:00
bitcoin 0.32
This commit is contained in:
parent
fb7d12ee6e
commit
a0a7d63dad
14 changed files with 224 additions and 168 deletions
84
Cargo.lock
generated
84
Cargo.lock
generated
|
@ -862,6 +862,16 @@ dependencies = [
|
|||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base58ck"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f"
|
||||
dependencies = [
|
||||
"bitcoin-internals",
|
||||
"bitcoin_hashes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
|
@ -888,9 +898,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
|||
|
||||
[[package]]
|
||||
name = "bech32"
|
||||
version = "0.10.0-beta"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea"
|
||||
checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d"
|
||||
|
||||
[[package]]
|
||||
name = "beef"
|
||||
|
@ -947,14 +957,16 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
|||
|
||||
[[package]]
|
||||
name = "bitcoin"
|
||||
version = "0.31.2"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae"
|
||||
checksum = "7170e7750a20974246f17ece04311b4205a6155f1db564c5b224af817663c3ea"
|
||||
dependencies = [
|
||||
"base58ck",
|
||||
"bech32",
|
||||
"bitcoin-internals",
|
||||
"bitcoin-io",
|
||||
"bitcoin-units",
|
||||
"bitcoin_hashes",
|
||||
"core2 0.3.3",
|
||||
"hex-conservative",
|
||||
"hex_lit",
|
||||
"secp256k1",
|
||||
|
@ -963,13 +975,19 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitcoin-internals"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb"
|
||||
checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin-io"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56"
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin-serai"
|
||||
version = "0.3.0"
|
||||
|
@ -991,13 +1009,22 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.13.0"
|
||||
name = "bitcoin-units"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b"
|
||||
checksum = "cb54da0b28892f3c52203a7191534033e051b6f4b52bc15480681b57b7e036f5"
|
||||
dependencies = [
|
||||
"bitcoin-internals",
|
||||
"core2 0.3.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16"
|
||||
dependencies = [
|
||||
"bitcoin-io",
|
||||
"hex-conservative",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1400,7 +1427,7 @@ version = "0.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3"
|
||||
dependencies = [
|
||||
"core2 0.4.0",
|
||||
"core2",
|
||||
"multibase",
|
||||
"multihash 0.18.1",
|
||||
"serde",
|
||||
|
@ -1584,15 +1611,6 @@ version = "0.8.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "core2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core2"
|
||||
version = "0.4.0"
|
||||
|
@ -3128,11 +3146,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hex-conservative"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2"
|
||||
checksum = "e1aa273bf451e37ed35ced41c71a5e2a4e29064afb104158f2514bcd71c2c986"
|
||||
dependencies = [
|
||||
"core2 0.3.3",
|
||||
"arrayvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3288,7 +3306,7 @@ dependencies = [
|
|||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite 0.2.14",
|
||||
"socket2 0.4.10",
|
||||
"socket2 0.5.6",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
@ -4758,7 +4776,7 @@ dependencies = [
|
|||
"blake2b_simd",
|
||||
"blake2s_simd",
|
||||
"blake3",
|
||||
"core2 0.4.0",
|
||||
"core2",
|
||||
"digest 0.10.7",
|
||||
"multihash-derive 0.8.0",
|
||||
"sha2",
|
||||
|
@ -4772,7 +4790,7 @@ version = "0.19.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492"
|
||||
dependencies = [
|
||||
"core2 0.4.0",
|
||||
"core2",
|
||||
"unsigned-varint",
|
||||
]
|
||||
|
||||
|
@ -4785,7 +4803,7 @@ dependencies = [
|
|||
"blake2b_simd",
|
||||
"blake2s_simd",
|
||||
"blake3",
|
||||
"core2 0.4.0",
|
||||
"core2",
|
||||
"digest 0.10.7",
|
||||
"multihash-derive 0.9.0",
|
||||
"ripemd",
|
||||
|
@ -4815,7 +4833,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "890e72cb7396cb99ed98c1246a97b243cc16394470d94e0bc8b0c2c11d84290e"
|
||||
dependencies = [
|
||||
"core2 0.4.0",
|
||||
"core2",
|
||||
"multihash 0.19.1",
|
||||
"multihash-derive-impl",
|
||||
]
|
||||
|
@ -7548,9 +7566,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "secp256k1"
|
||||
version = "0.28.2"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10"
|
||||
checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3"
|
||||
dependencies = [
|
||||
"bitcoin_hashes",
|
||||
"rand",
|
||||
|
@ -7560,9 +7578,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "secp256k1-sys"
|
||||
version = "0.9.2"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb"
|
||||
checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
|
|
@ -23,7 +23,7 @@ thiserror = { version = "1", default-features = false, optional = true }
|
|||
zeroize = { version = "^1.5", default-features = false }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
|
||||
bitcoin = { version = "0.31", default-features = false, features = ["no-std"] }
|
||||
bitcoin = { version = "0.32", default-features = false }
|
||||
|
||||
k256 = { version = "^0.13.1", default-features = false, features = ["arithmetic", "bits"] }
|
||||
|
||||
|
@ -36,7 +36,7 @@ serde_json = { version = "1", default-features = false, optional = true }
|
|||
simple-request = { path = "../../common/request", version = "0.1", default-features = false, features = ["tls", "basic-auth"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
secp256k1 = { version = "0.28", default-features = false, features = ["std"] }
|
||||
secp256k1 = { version = "0.29", default-features = false, features = ["std"] }
|
||||
|
||||
frost = { package = "modular-frost", path = "../../crypto/frost", features = ["tests"] }
|
||||
|
||||
|
|
|
@ -195,13 +195,13 @@ impl Rpc {
|
|||
// If this was already successfully published, consider this having succeeded
|
||||
if let RpcError::RequestError(Error { code, .. }) = e {
|
||||
if code == RPC_VERIFY_ALREADY_IN_CHAIN {
|
||||
return Ok(tx.txid());
|
||||
return Ok(tx.compute_txid());
|
||||
}
|
||||
}
|
||||
Err(e)?
|
||||
}
|
||||
};
|
||||
if txid != tx.txid() {
|
||||
if txid != tx.compute_txid() {
|
||||
Err(RpcError::InvalidResponse("returned TX ID inequals calculated TX ID"))?;
|
||||
}
|
||||
Ok(txid)
|
||||
|
@ -215,7 +215,7 @@ impl Rpc {
|
|||
let tx: Transaction = encode::deserialize(&bytes)
|
||||
.map_err(|_| RpcError::InvalidResponse("node sent an improperly serialized transaction"))?;
|
||||
|
||||
let mut tx_hash = *tx.txid().as_raw_hash().as_byte_array();
|
||||
let mut tx_hash = *tx.compute_txid().as_raw_hash().as_byte_array();
|
||||
tx_hash.reverse();
|
||||
if hash != &tx_hash {
|
||||
Err(RpcError::InvalidResponse("node replied with a different transaction"))?;
|
||||
|
|
|
@ -39,7 +39,7 @@ fn test_algorithm() {
|
|||
.verify_schnorr(
|
||||
&Signature::from_slice(&sig)
|
||||
.expect("couldn't convert produced signature to secp256k1::Signature"),
|
||||
&Message::from(Hash::hash(MESSAGE)),
|
||||
&Message::from_digest_slice(Hash::hash(MESSAGE).as_ref()).unwrap(),
|
||||
&x_only(&keys[&Participant::new(1).unwrap()].group_key()),
|
||||
)
|
||||
.unwrap()
|
||||
|
|
|
@ -4,7 +4,7 @@ use std_shims::{
|
|||
io::{self, Write},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use std_shims::io::Read;
|
||||
use std::io::{Read, BufReader};
|
||||
|
||||
use k256::{
|
||||
elliptic_curve::sec1::{Tag, ToEncodedPoint},
|
||||
|
@ -18,8 +18,8 @@ use frost::{
|
|||
};
|
||||
|
||||
use bitcoin::{
|
||||
consensus::encode::serialize, key::TweakedPublicKey, address::Payload, OutPoint, ScriptBuf,
|
||||
TxOut, Transaction, Block,
|
||||
consensus::encode::serialize, key::TweakedPublicKey, OutPoint, ScriptBuf, TxOut, Transaction,
|
||||
Block,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use bitcoin::consensus::encode::Decodable;
|
||||
|
@ -46,12 +46,12 @@ pub fn tweak_keys(keys: &ThresholdKeys<Secp256k1>) -> ThresholdKeys<Secp256k1> {
|
|||
/// Return the Taproot address payload for a public key.
|
||||
///
|
||||
/// If the key is odd, this will return None.
|
||||
pub fn address_payload(key: ProjectivePoint) -> Option<Payload> {
|
||||
pub fn p2tr_script_buf(key: ProjectivePoint) -> Option<ScriptBuf> {
|
||||
if key.to_encoded_point(true).tag() != Tag::CompressedEvenY {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(x_only(&key))))
|
||||
Some(ScriptBuf::new_p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(x_only(&key))))
|
||||
}
|
||||
|
||||
/// A spendable output.
|
||||
|
@ -89,11 +89,17 @@ impl ReceivedOutput {
|
|||
/// Read a ReceivedOutput from a generic satisfying Read.
|
||||
#[cfg(feature = "std")]
|
||||
pub fn read<R: Read>(r: &mut R) -> io::Result<ReceivedOutput> {
|
||||
Ok(ReceivedOutput {
|
||||
offset: Secp256k1::read_F(r)?,
|
||||
output: TxOut::consensus_decode(r).map_err(|_| io::Error::other("invalid TxOut"))?,
|
||||
outpoint: OutPoint::consensus_decode(r).map_err(|_| io::Error::other("invalid OutPoint"))?,
|
||||
})
|
||||
let offset = Secp256k1::read_F(r)?;
|
||||
let output;
|
||||
let outpoint;
|
||||
{
|
||||
let mut buf_r = BufReader::new(r);
|
||||
output =
|
||||
TxOut::consensus_decode(&mut buf_r).map_err(|_| io::Error::other("invalid TxOut"))?;
|
||||
outpoint =
|
||||
OutPoint::consensus_decode(&mut buf_r).map_err(|_| io::Error::other("invalid OutPoint"))?;
|
||||
}
|
||||
Ok(ReceivedOutput { offset, output, outpoint })
|
||||
}
|
||||
|
||||
/// Write a ReceivedOutput to a generic satisfying Write.
|
||||
|
@ -124,7 +130,7 @@ impl Scanner {
|
|||
/// Returns None if this key can't be scanned for.
|
||||
pub fn new(key: ProjectivePoint) -> Option<Scanner> {
|
||||
let mut scripts = HashMap::new();
|
||||
scripts.insert(address_payload(key)?.script_pubkey(), Scalar::ZERO);
|
||||
scripts.insert(p2tr_script_buf(key)?, Scalar::ZERO);
|
||||
Some(Scanner { key, scripts })
|
||||
}
|
||||
|
||||
|
@ -141,9 +147,8 @@ impl Scanner {
|
|||
// chance of being even
|
||||
// That means this should terminate within a very small amount of iterations
|
||||
loop {
|
||||
match address_payload(self.key + (ProjectivePoint::GENERATOR * offset)) {
|
||||
Some(address) => {
|
||||
let script = address.script_pubkey();
|
||||
match p2tr_script_buf(self.key + (ProjectivePoint::GENERATOR * offset)) {
|
||||
Some(script) => {
|
||||
if self.scripts.contains_key(&script) {
|
||||
None?;
|
||||
}
|
||||
|
@ -166,7 +171,7 @@ impl Scanner {
|
|||
res.push(ReceivedOutput {
|
||||
offset: *offset,
|
||||
output: output.clone(),
|
||||
outpoint: OutPoint::new(tx.txid(), vout),
|
||||
outpoint: OutPoint::new(tx.compute_txid(), vout),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use bitcoin::{
|
|||
|
||||
use crate::{
|
||||
crypto::Schnorr,
|
||||
wallet::{ReceivedOutput, address_payload},
|
||||
wallet::{ReceivedOutput, p2tr_script_buf},
|
||||
};
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
@ -248,7 +248,7 @@ impl SignableTransaction {
|
|||
|
||||
/// Returns the TX ID of the transaction this will create.
|
||||
pub fn txid(&self) -> [u8; 32] {
|
||||
let mut res = self.tx.txid().to_byte_array();
|
||||
let mut res = self.tx.compute_txid().to_byte_array();
|
||||
res.reverse();
|
||||
res
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ impl SignableTransaction {
|
|||
transcript.append_message(b"signing_input", u32::try_from(i).unwrap().to_le_bytes());
|
||||
|
||||
let offset = keys.clone().offset(self.offsets[i]);
|
||||
if address_payload(offset.group_key())?.script_pubkey() != self.prevouts[i].script_pubkey {
|
||||
if p2tr_script_buf(offset.group_key())? != self.prevouts[i].script_pubkey {
|
||||
None?;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,10 @@ use bitcoin_serai::{
|
|||
hashes::Hash as HashTrait,
|
||||
blockdata::opcodes::all::OP_RETURN,
|
||||
script::{PushBytesBuf, Instruction, Instructions, Script},
|
||||
address::NetworkChecked,
|
||||
OutPoint, Amount, TxOut, Transaction, Network, Address,
|
||||
},
|
||||
wallet::{
|
||||
tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError, SignableTransaction,
|
||||
tweak_keys, p2tr_script_buf, ReceivedOutput, Scanner, TransactionError, SignableTransaction,
|
||||
},
|
||||
rpc::Rpc,
|
||||
};
|
||||
|
@ -48,7 +47,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint)
|
|||
"generatetoaddress",
|
||||
serde_json::json!([
|
||||
1,
|
||||
Address::<NetworkChecked>::new(Network::Regtest, address_payload(key).unwrap())
|
||||
Address::from_script(&p2tr_script_buf(key).unwrap(), Network::Regtest).unwrap()
|
||||
]),
|
||||
)
|
||||
.await
|
||||
|
@ -69,7 +68,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint)
|
|||
assert_eq!(outputs, scanner.scan_transaction(&block.txdata[0]));
|
||||
|
||||
assert_eq!(outputs.len(), 1);
|
||||
assert_eq!(outputs[0].outpoint(), &OutPoint::new(block.txdata[0].txid(), 0));
|
||||
assert_eq!(outputs[0].outpoint(), &OutPoint::new(block.txdata[0].compute_txid(), 0));
|
||||
assert_eq!(outputs[0].value(), block.txdata[0].output[0].value.to_sat());
|
||||
|
||||
assert_eq!(
|
||||
|
@ -193,7 +192,7 @@ async_sequential! {
|
|||
assert_eq!(output.offset(), Scalar::ZERO);
|
||||
|
||||
let inputs = vec![output];
|
||||
let addr = || Address::<NetworkChecked>::new(Network::Regtest, address_payload(key).unwrap());
|
||||
let addr = || Address::from_script(&p2tr_script_buf(key).unwrap(), Network::Regtest).unwrap();
|
||||
let payments = vec![(addr(), 1000)];
|
||||
|
||||
assert!(SignableTransaction::new(inputs.clone(), &payments, None, None, FEE).is_ok());
|
||||
|
@ -261,14 +260,14 @@ async_sequential! {
|
|||
|
||||
// Declare payments, change, fee
|
||||
let payments = [
|
||||
(Address::<NetworkChecked>::new(Network::Regtest, address_payload(key).unwrap()), 1005),
|
||||
(Address::<NetworkChecked>::new(Network::Regtest, address_payload(offset_key).unwrap()), 1007)
|
||||
(Address::from_script(&p2tr_script_buf(key).unwrap(), Network::Regtest).unwrap(), 1005),
|
||||
(Address::from_script(&p2tr_script_buf(offset_key).unwrap(), Network::Regtest).unwrap(), 1007)
|
||||
];
|
||||
|
||||
let change_offset = scanner.register_offset(Scalar::random(&mut OsRng)).unwrap();
|
||||
let change_key = key + (ProjectivePoint::GENERATOR * change_offset);
|
||||
let change_addr =
|
||||
Address::<NetworkChecked>::new(Network::Regtest, address_payload(change_key).unwrap());
|
||||
Address::from_script(&p2tr_script_buf(change_key).unwrap(), Network::Regtest).unwrap();
|
||||
|
||||
// Create and sign the TX
|
||||
let tx = SignableTransaction::new(
|
||||
|
@ -287,7 +286,7 @@ async_sequential! {
|
|||
// Ensure we can scan it
|
||||
let outputs = scanner.scan_transaction(&tx);
|
||||
for (o, output) in outputs.iter().enumerate() {
|
||||
assert_eq!(output.outpoint(), &OutPoint::new(tx.txid(), u32::try_from(o).unwrap()));
|
||||
assert_eq!(output.outpoint(), &OutPoint::new(tx.compute_txid(), u32::try_from(o).unwrap()));
|
||||
assert_eq!(&ReceivedOutput::read::<&[u8]>(&mut output.serialize().as_ref()).unwrap(), output);
|
||||
}
|
||||
|
||||
|
@ -320,7 +319,7 @@ async_sequential! {
|
|||
// This also tests send_raw_transaction and get_transaction, which the RPC test can't
|
||||
// effectively test
|
||||
rpc.send_raw_transaction(&tx).await.unwrap();
|
||||
let mut hash = *tx.txid().as_raw_hash().as_byte_array();
|
||||
let mut hash = *tx.compute_txid().as_raw_hash().as_byte_array();
|
||||
hash.reverse();
|
||||
assert_eq!(tx, rpc.get_transaction(&hash).await.unwrap());
|
||||
assert_eq!(expected_id, hash);
|
||||
|
@ -344,7 +343,7 @@ async_sequential! {
|
|||
&SignableTransaction::new(
|
||||
vec![output],
|
||||
&[],
|
||||
Some(&Address::<NetworkChecked>::new(Network::Regtest, address_payload(key).unwrap())),
|
||||
Some(&Address::from_script(&p2tr_script_buf(key).unwrap(), Network::Regtest).unwrap()),
|
||||
Some(data.clone()),
|
||||
FEE
|
||||
).unwrap()
|
||||
|
|
|
@ -45,7 +45,7 @@ frost-schnorrkel = { path = "../crypto/schnorrkel", default-features = false }
|
|||
k256 = { version = "^0.13.1", default-features = false, features = ["std"], optional = true }
|
||||
|
||||
# Bitcoin
|
||||
secp256k1 = { version = "0.28", default-features = false, features = ["std", "global-context", "rand-std"], optional = true }
|
||||
secp256k1 = { version = "0.29", default-features = false, features = ["std", "global-context", "rand-std"], optional = true }
|
||||
bitcoin-serai = { path = "../coins/bitcoin", default-features = false, features = ["std"], optional = true }
|
||||
|
||||
# Ethereum
|
||||
|
|
|
@ -20,12 +20,12 @@ use bitcoin_serai::{
|
|||
key::{Parity, XOnlyPublicKey},
|
||||
consensus::{Encodable, Decodable},
|
||||
script::Instruction,
|
||||
address::{NetworkChecked, Address as BAddress},
|
||||
address::Address as BAddress,
|
||||
Transaction, Block, Network as BNetwork, ScriptBuf,
|
||||
opcodes::all::{OP_SHA256, OP_EQUALVERIFY},
|
||||
},
|
||||
wallet::{
|
||||
tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError,
|
||||
tweak_keys, p2tr_script_buf, ReceivedOutput, Scanner, TransactionError,
|
||||
SignableTransaction as BSignableTransaction, TransactionMachine,
|
||||
},
|
||||
rpc::{RpcError, Rpc},
|
||||
|
@ -175,7 +175,7 @@ pub struct Fee(u64);
|
|||
impl TransactionTrait<Bitcoin> for Transaction {
|
||||
type Id = [u8; 32];
|
||||
fn id(&self) -> Self::Id {
|
||||
let mut hash = *self.txid().as_raw_hash().as_byte_array();
|
||||
let mut hash = *self.compute_txid().as_raw_hash().as_byte_array();
|
||||
hash.reverse();
|
||||
hash
|
||||
}
|
||||
|
@ -243,7 +243,8 @@ impl EventualityTrait for Eventuality {
|
|||
buf
|
||||
}
|
||||
fn read_completion<R: io::Read>(reader: &mut R) -> io::Result<Transaction> {
|
||||
Transaction::consensus_decode(reader).map_err(|e| io::Error::other(format!("{e}")))
|
||||
Transaction::consensus_decode(&mut io::BufReader::new(reader))
|
||||
.map_err(|e| io::Error::other(format!("{e}")))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,11 +536,11 @@ impl Bitcoin {
|
|||
private_key: &PrivateKey,
|
||||
) -> ScriptBuf {
|
||||
let public_key = PublicKey::from_private_key(SECP256K1, private_key);
|
||||
let main_addr = BAddress::p2pkh(&public_key, BNetwork::Regtest);
|
||||
let main_addr = BAddress::p2pkh(public_key, BNetwork::Regtest);
|
||||
|
||||
let mut der = SECP256K1
|
||||
.sign_ecdsa_low_r(
|
||||
&Message::from(
|
||||
&Message::from_digest_slice(
|
||||
SighashCache::new(tx)
|
||||
.legacy_signature_hash(
|
||||
input_index,
|
||||
|
@ -547,8 +548,10 @@ impl Bitcoin {
|
|||
EcdsaSighashType::All.to_u32(),
|
||||
)
|
||||
.unwrap()
|
||||
.to_raw_hash(),
|
||||
),
|
||||
.to_raw_hash()
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap(),
|
||||
&private_key.inner,
|
||||
)
|
||||
.serialize_der()
|
||||
|
@ -577,8 +580,14 @@ const MAX_INPUTS: usize = 520;
|
|||
const MAX_OUTPUTS: usize = 520;
|
||||
|
||||
fn address_from_key(key: ProjectivePoint) -> Address {
|
||||
Address::new(BAddress::<NetworkChecked>::new(BNetwork::Bitcoin, address_payload(key).unwrap()))
|
||||
.unwrap()
|
||||
Address::new(
|
||||
BAddress::from_script(
|
||||
&p2tr_script_buf(key).expect("creating address from key which isn't properly tweaked"),
|
||||
BNetwork::Bitcoin,
|
||||
)
|
||||
.expect("couldn't go from p2tr script buf to address"),
|
||||
)
|
||||
.expect("couldn't create Serai-representable address for bitcoin address")
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -858,7 +867,7 @@ impl Network for Bitcoin {
|
|||
Err(RpcError::ConnectionError) => Err(NetworkError::ConnectionError)?,
|
||||
// TODO: Distinguish already in pool vs double spend (other signing attempt succeeded) vs
|
||||
// invalid transaction
|
||||
Err(e) => panic!("failed to publish TX {}: {e}", tx.txid()),
|
||||
Err(e) => panic!("failed to publish TX {}: {e}", tx.compute_txid()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -909,7 +918,7 @@ impl Network for Bitcoin {
|
|||
let secret_key = SecretKey::new(&mut rand_core::OsRng);
|
||||
let private_key = PrivateKey::new(secret_key, BNetwork::Regtest);
|
||||
let public_key = PublicKey::from_private_key(SECP256K1, &private_key);
|
||||
let main_addr = BAddress::p2pkh(&public_key, BNetwork::Regtest);
|
||||
let main_addr = BAddress::p2pkh(public_key, BNetwork::Regtest);
|
||||
|
||||
let new_block = self.get_latest_block_number().await.unwrap() + 1;
|
||||
self
|
||||
|
@ -923,7 +932,7 @@ impl Network for Bitcoin {
|
|||
version: Version(2),
|
||||
lock_time: LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint { txid: tx.txid(), vout: 0 },
|
||||
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
|
||||
script_sig: Script::new().into(),
|
||||
sequence: Sequence(u32::MAX),
|
||||
witness: Witness::default(),
|
||||
|
|
|
@ -70,7 +70,7 @@ mod bitcoin {
|
|||
// btc key pair to send from
|
||||
let private_key = PrivateKey::new(SecretKey::new(&mut rand_core::OsRng), BNetwork::Regtest);
|
||||
let public_key = PublicKey::from_private_key(SECP256K1, &private_key);
|
||||
let main_addr = BAddress::p2pkh(&public_key, BNetwork::Regtest);
|
||||
let main_addr = BAddress::p2pkh(public_key, BNetwork::Regtest);
|
||||
|
||||
// get unlocked coins
|
||||
let new_block = btc.get_latest_block_number().await.unwrap() + 1;
|
||||
|
@ -107,7 +107,7 @@ mod bitcoin {
|
|||
version: Version(2),
|
||||
lock_time: LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint { txid: tx.txid(), vout: 0 },
|
||||
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
|
||||
script_sig: Script::new().into(),
|
||||
sequence: Sequence(u32::MAX),
|
||||
witness: Witness::default(),
|
||||
|
@ -128,7 +128,7 @@ mod bitcoin {
|
|||
version: Version(2),
|
||||
lock_time: LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint { txid: tx.txid(), vout: 0 },
|
||||
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
|
||||
script_sig: Script::new().into(),
|
||||
sequence: Sequence(u32::MAX),
|
||||
witness: Witness::new(),
|
||||
|
@ -143,12 +143,14 @@ mod bitcoin {
|
|||
// This is the standard script with an extra argument of the InInstruction
|
||||
let mut sig = SECP256K1
|
||||
.sign_ecdsa_low_r(
|
||||
&Message::from(
|
||||
&Message::from_digest_slice(
|
||||
SighashCache::new(&tx)
|
||||
.p2wsh_signature_hash(0, &script, initial_output_value, EcdsaSighashType::All)
|
||||
.unwrap()
|
||||
.to_raw_hash(),
|
||||
),
|
||||
.to_raw_hash()
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap(),
|
||||
&private_key.inner,
|
||||
)
|
||||
.serialize_der()
|
||||
|
|
|
@ -36,7 +36,7 @@ async-lock = "3"
|
|||
|
||||
simple-request = { path = "../../common/request", version = "0.1", optional = true }
|
||||
|
||||
bitcoin = { version = "0.31", optional = true }
|
||||
bitcoin = { version = "0.32", optional = true }
|
||||
|
||||
ciphersuite = { path = "../../crypto/ciphersuite", version = "0.4", optional = true }
|
||||
monero-serai = { path = "../../coins/monero", version = "0.1.4-alpha", optional = true }
|
||||
|
|
|
@ -6,8 +6,8 @@ use bitcoin::{
|
|||
hashes::{Hash as HashTrait, hash160::Hash},
|
||||
PubkeyHash, ScriptHash,
|
||||
network::Network,
|
||||
WitnessVersion, WitnessProgram,
|
||||
address::{Error, Payload, NetworkChecked, Address as BAddressGeneric},
|
||||
WitnessVersion, WitnessProgram, ScriptBuf,
|
||||
address::{AddressType, NetworkChecked, Address as BAddressGeneric},
|
||||
};
|
||||
|
||||
type BAddress = BAddressGeneric<NetworkChecked>;
|
||||
|
@ -17,21 +17,22 @@ pub struct Address(BAddress);
|
|||
|
||||
impl PartialEq for Address {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// Since Serai defines the Bitcoin-address specification as a variant of the payload alone,
|
||||
// define equivalency as the payload alone
|
||||
self.0.payload() == other.0.payload()
|
||||
// Since Serai defines the Bitcoin-address specification as a variant of the script alone,
|
||||
// define equivalency as the script alone
|
||||
self.0.script_pubkey() == other.0.script_pubkey()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Address {
|
||||
type Err = Error;
|
||||
fn from_str(str: &str) -> Result<Address, Error> {
|
||||
type Err = ();
|
||||
fn from_str(str: &str) -> Result<Address, ()> {
|
||||
Address::new(
|
||||
BAddressGeneric::from_str(str)
|
||||
.map_err(|_| Error::UnrecognizedScript)?
|
||||
.require_network(Network::Bitcoin)?,
|
||||
.map_err(|_| ())?
|
||||
.require_network(Network::Bitcoin)
|
||||
.map_err(|_| ())?,
|
||||
)
|
||||
.ok_or(Error::UnrecognizedScript)
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,55 +55,65 @@ enum EncodedAddress {
|
|||
impl TryFrom<Vec<u8>> for Address {
|
||||
type Error = ();
|
||||
fn try_from(data: Vec<u8>) -> Result<Address, ()> {
|
||||
Ok(Address(BAddress::new(
|
||||
Network::Bitcoin,
|
||||
match EncodedAddress::decode(&mut data.as_ref()).map_err(|_| ())? {
|
||||
EncodedAddress::P2PKH(hash) => {
|
||||
Payload::PubkeyHash(PubkeyHash::from_raw_hash(Hash::from_byte_array(hash)))
|
||||
}
|
||||
EncodedAddress::P2SH(hash) => {
|
||||
Payload::ScriptHash(ScriptHash::from_raw_hash(Hash::from_byte_array(hash)))
|
||||
}
|
||||
EncodedAddress::P2WPKH(hash) => {
|
||||
Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V0, hash).unwrap())
|
||||
}
|
||||
EncodedAddress::P2WSH(hash) => {
|
||||
Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V0, hash).unwrap())
|
||||
}
|
||||
EncodedAddress::P2TR(key) => {
|
||||
Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V1, key).unwrap())
|
||||
}
|
||||
},
|
||||
)))
|
||||
Ok(Address(match EncodedAddress::decode(&mut data.as_ref()).map_err(|_| ())? {
|
||||
EncodedAddress::P2PKH(hash) => {
|
||||
BAddress::p2pkh(PubkeyHash::from_raw_hash(Hash::from_byte_array(hash)), Network::Bitcoin)
|
||||
}
|
||||
EncodedAddress::P2SH(hash) => {
|
||||
let script_hash = ScriptHash::from_raw_hash(Hash::from_byte_array(hash));
|
||||
let res =
|
||||
BAddress::from_script(&ScriptBuf::new_p2sh(&script_hash), Network::Bitcoin).unwrap();
|
||||
debug_assert_eq!(res.script_hash(), Some(script_hash));
|
||||
res
|
||||
}
|
||||
EncodedAddress::P2WPKH(hash) => BAddress::from_witness_program(
|
||||
WitnessProgram::new(WitnessVersion::V0, &hash).unwrap(),
|
||||
Network::Bitcoin,
|
||||
),
|
||||
EncodedAddress::P2WSH(hash) => BAddress::from_witness_program(
|
||||
WitnessProgram::new(WitnessVersion::V0, &hash).unwrap(),
|
||||
Network::Bitcoin,
|
||||
),
|
||||
EncodedAddress::P2TR(key) => BAddress::from_witness_program(
|
||||
WitnessProgram::new(WitnessVersion::V1, &key).unwrap(),
|
||||
Network::Bitcoin,
|
||||
),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_to_vec(addr: &Address) -> Result<Vec<u8>, ()> {
|
||||
let witness_program = |addr: &Address| {
|
||||
let script = addr.0.script_pubkey();
|
||||
let program_push = script.as_script().instructions().last().ok_or(())?.map_err(|_| ())?;
|
||||
let program = program_push.push_bytes().ok_or(())?.as_bytes();
|
||||
Ok::<_, ()>(program.to_vec())
|
||||
};
|
||||
Ok(
|
||||
(match addr.0.payload() {
|
||||
Payload::PubkeyHash(hash) => EncodedAddress::P2PKH(*hash.as_raw_hash().as_byte_array()),
|
||||
Payload::ScriptHash(hash) => EncodedAddress::P2SH(*hash.as_raw_hash().as_byte_array()),
|
||||
Payload::WitnessProgram(program) => match program.version() {
|
||||
WitnessVersion::V0 => {
|
||||
let program = program.program();
|
||||
if program.len() == 20 {
|
||||
let mut buf = [0; 20];
|
||||
buf.copy_from_slice(program.as_ref());
|
||||
EncodedAddress::P2WPKH(buf)
|
||||
} else if program.len() == 32 {
|
||||
let mut buf = [0; 32];
|
||||
buf.copy_from_slice(program.as_ref());
|
||||
EncodedAddress::P2WSH(buf)
|
||||
} else {
|
||||
Err(())?
|
||||
}
|
||||
}
|
||||
WitnessVersion::V1 => {
|
||||
let program_ref: &[u8] = program.program().as_ref();
|
||||
EncodedAddress::P2TR(program_ref.try_into().map_err(|_| ())?)
|
||||
}
|
||||
_ => Err(())?,
|
||||
},
|
||||
(match addr.0.address_type() {
|
||||
Some(AddressType::P2pkh) => {
|
||||
EncodedAddress::P2PKH(*addr.0.pubkey_hash().unwrap().as_raw_hash().as_byte_array())
|
||||
}
|
||||
Some(AddressType::P2sh) => {
|
||||
EncodedAddress::P2SH(*addr.0.script_hash().unwrap().as_raw_hash().as_byte_array())
|
||||
}
|
||||
Some(AddressType::P2wpkh) => {
|
||||
let program = witness_program(addr)?;
|
||||
let mut buf = [0; 20];
|
||||
buf.copy_from_slice(program.as_ref());
|
||||
EncodedAddress::P2WPKH(buf)
|
||||
}
|
||||
Some(AddressType::P2wsh) => {
|
||||
let program = witness_program(addr)?;
|
||||
let mut buf = [0; 32];
|
||||
buf.copy_from_slice(program.as_ref());
|
||||
EncodedAddress::P2WSH(buf)
|
||||
}
|
||||
Some(AddressType::P2tr) => {
|
||||
let program = witness_program(addr)?;
|
||||
let program_ref: &[u8] = program.as_ref();
|
||||
EncodedAddress::P2TR(program_ref.try_into().map_err(|_| ())?)
|
||||
}
|
||||
_ => Err(())?,
|
||||
})
|
||||
.encode(),
|
||||
|
|
|
@ -57,7 +57,7 @@ async fn mint_and_burn_test() {
|
|||
};
|
||||
|
||||
let addr = Address::p2pkh(
|
||||
&PublicKey::from_private_key(
|
||||
PublicKey::from_private_key(
|
||||
SECP256K1,
|
||||
&PrivateKey::new(SecretKey::from_slice(&[0x01; 32]).unwrap(), Network::Bitcoin),
|
||||
),
|
||||
|
@ -266,14 +266,13 @@ async fn mint_and_burn_test() {
|
|||
script::{PushBytesBuf, Script, ScriptBuf, Builder},
|
||||
absolute::LockTime,
|
||||
transaction::{Version, Transaction},
|
||||
address::Payload,
|
||||
Sequence, Witness, OutPoint, TxIn, Amount, TxOut, Network,
|
||||
Sequence, Witness, OutPoint, TxIn, Amount, TxOut, Network, Address,
|
||||
};
|
||||
|
||||
let private_key =
|
||||
PrivateKey::new(SecretKey::from_slice(&[0x01; 32]).unwrap(), Network::Bitcoin);
|
||||
let public_key = PublicKey::from_private_key(SECP256K1, &private_key);
|
||||
let addr = Payload::p2pkh(&public_key);
|
||||
let addr = Address::p2pkh(public_key, Network::Bitcoin);
|
||||
|
||||
// Use the first block's coinbase
|
||||
let rpc = handles[0].bitcoin(&ops).await;
|
||||
|
@ -284,7 +283,7 @@ async fn mint_and_burn_test() {
|
|||
version: Version(2),
|
||||
lock_time: LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint { txid: tx.txid(), vout: 0 },
|
||||
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
|
||||
script_sig: Script::new().into(),
|
||||
sequence: Sequence(u32::MAX),
|
||||
witness: Witness::default(),
|
||||
|
@ -292,17 +291,23 @@ async fn mint_and_burn_test() {
|
|||
output: vec![
|
||||
TxOut {
|
||||
value: Amount::from_sat(1_100_000_00),
|
||||
script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(
|
||||
XOnlyPublicKey::from_slice(&bitcoin_key_pair.1[1 ..]).unwrap(),
|
||||
))
|
||||
script_pubkey: Address::p2tr_tweaked(
|
||||
TweakedPublicKey::dangerous_assume_tweaked(
|
||||
XOnlyPublicKey::from_slice(&bitcoin_key_pair.1[1 ..]).unwrap(),
|
||||
),
|
||||
Network::Bitcoin,
|
||||
)
|
||||
.script_pubkey(),
|
||||
},
|
||||
TxOut {
|
||||
// change = amount spent - fee
|
||||
value: Amount::from_sat(tx.output[0].value.to_sat() - 1_100_000_00 - 1_000_00),
|
||||
script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(
|
||||
XOnlyPublicKey::from_slice(&public_key.inner.serialize()[1 ..]).unwrap(),
|
||||
))
|
||||
script_pubkey: Address::p2tr_tweaked(
|
||||
TweakedPublicKey::dangerous_assume_tweaked(
|
||||
XOnlyPublicKey::from_slice(&public_key.inner.serialize()[1 ..]).unwrap(),
|
||||
),
|
||||
Network::Bitcoin,
|
||||
)
|
||||
.script_pubkey(),
|
||||
},
|
||||
TxOut {
|
||||
|
@ -316,12 +321,14 @@ async fn mint_and_burn_test() {
|
|||
|
||||
let mut der = SECP256K1
|
||||
.sign_ecdsa_low_r(
|
||||
&Message::from(
|
||||
&Message::from_digest_slice(
|
||||
SighashCache::new(&tx)
|
||||
.legacy_signature_hash(0, &addr.script_pubkey(), EcdsaSighashType::All.to_u32())
|
||||
.unwrap()
|
||||
.to_raw_hash(),
|
||||
),
|
||||
.to_raw_hash()
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap(),
|
||||
&private_key.inner,
|
||||
)
|
||||
.serialize_der()
|
||||
|
@ -449,9 +456,9 @@ async fn mint_and_burn_test() {
|
|||
let bitcoin_addr = {
|
||||
use bitcoin_serai::bitcoin::{network::Network, key::PublicKey, address::Address};
|
||||
// Uses Network::Bitcoin since it doesn't actually matter, Serai strips it out
|
||||
// TODO: Move Serai to Payload from Address
|
||||
// TODO: Move Serai to ScriptBuf from Address
|
||||
Address::p2pkh(
|
||||
&loop {
|
||||
loop {
|
||||
let mut bytes = [0; 33];
|
||||
OsRng.fill_bytes(&mut bytes);
|
||||
bytes[0] %= 4;
|
||||
|
|
|
@ -126,7 +126,7 @@ impl Wallet {
|
|||
let secret_key = SecretKey::new(&mut rand_core::OsRng);
|
||||
let private_key = PrivateKey::new(secret_key, Network::Regtest);
|
||||
let public_key = PublicKey::from_private_key(SECP256K1, &private_key);
|
||||
let main_addr = Address::p2pkh(&public_key, Network::Regtest);
|
||||
let main_addr = Address::p2pkh(public_key, Network::Regtest);
|
||||
|
||||
let rpc = Rpc::new(rpc_url).await.expect("couldn't connect to the Bitcoin RPC");
|
||||
|
||||
|
@ -258,10 +258,10 @@ impl Wallet {
|
|||
consensus::Encodable,
|
||||
sighash::{EcdsaSighashType, SighashCache},
|
||||
script::{PushBytesBuf, Script, ScriptBuf, Builder},
|
||||
address::Payload,
|
||||
OutPoint, Sequence, Witness, TxIn, Amount, TxOut,
|
||||
absolute::LockTime,
|
||||
transaction::{Version, Transaction},
|
||||
Network, Address,
|
||||
};
|
||||
|
||||
const AMOUNT: u64 = 100000000;
|
||||
|
@ -269,7 +269,7 @@ impl Wallet {
|
|||
version: Version(2),
|
||||
lock_time: LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint { txid: input_tx.txid(), vout: 0 },
|
||||
previous_output: OutPoint { txid: input_tx.compute_txid(), vout: 0 },
|
||||
script_sig: Script::new().into(),
|
||||
sequence: Sequence(u32::MAX),
|
||||
witness: Witness::default(),
|
||||
|
@ -281,9 +281,12 @@ impl Wallet {
|
|||
},
|
||||
TxOut {
|
||||
value: Amount::from_sat(AMOUNT),
|
||||
script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(
|
||||
XOnlyPublicKey::from_slice(&to[1 ..]).unwrap(),
|
||||
))
|
||||
script_pubkey: Address::p2tr_tweaked(
|
||||
TweakedPublicKey::dangerous_assume_tweaked(
|
||||
XOnlyPublicKey::from_slice(&to[1 ..]).unwrap(),
|
||||
),
|
||||
Network::Bitcoin,
|
||||
)
|
||||
.script_pubkey(),
|
||||
},
|
||||
],
|
||||
|
@ -303,7 +306,7 @@ impl Wallet {
|
|||
|
||||
let mut der = SECP256K1
|
||||
.sign_ecdsa_low_r(
|
||||
&Message::from(
|
||||
&Message::from_digest_slice(
|
||||
SighashCache::new(&tx)
|
||||
.legacy_signature_hash(
|
||||
0,
|
||||
|
@ -311,8 +314,10 @@ impl Wallet {
|
|||
EcdsaSighashType::All.to_u32(),
|
||||
)
|
||||
.unwrap()
|
||||
.to_raw_hash(),
|
||||
),
|
||||
.to_raw_hash()
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap(),
|
||||
&private_key.inner,
|
||||
)
|
||||
.serialize_der()
|
||||
|
|
Loading…
Reference in a new issue