mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-09 04:39:24 +00:00
bitcoin 0.32
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user