Merge branch 'develop' into HEAD

This commit is contained in:
Luke Parker
2024-06-06 02:43:33 -04:00
261 changed files with 10394 additions and 3812 deletions

View File

@@ -20,7 +20,6 @@ workspace = true
hex = "0.4"
async-trait = "0.1"
async-recursion = "1"
zeroize = { version = "1", default-features = false }
rand_core = { version = "0.6", default-features = false }

View File

@@ -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()
@@ -447,19 +454,17 @@ async fn mint_and_burn_test() {
// Create a random Bitcoin/Monero address
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
Address::p2pkh(
&loop {
use bitcoin_serai::bitcoin::{key::PublicKey, ScriptBuf};
ScriptBuf::new_p2pkh(
&(loop {
let mut bytes = [0; 33];
OsRng.fill_bytes(&mut bytes);
bytes[0] %= 4;
if let Ok(key) = PublicKey::from_slice(&bytes) {
break key;
}
},
Network::Bitcoin,
})
.pubkey_hash(),
)
};
@@ -552,7 +557,7 @@ async fn mint_and_burn_test() {
let received_output = block.txdata[1]
.output
.iter()
.find(|output| output.script_pubkey == bitcoin_addr.script_pubkey())
.find(|output| output.script_pubkey == bitcoin_addr)
.unwrap();
let tx_fee = 1_100_000_00 -

View File

@@ -57,12 +57,16 @@ pub(crate) async fn new_test(test_body: impl TestBody) {
let (coord_key, message_queue_keys, message_queue_composition) = message_queue_instance();
let (bitcoin_composition, bitcoin_port) = network_instance(NetworkId::Bitcoin);
let bitcoin_processor_composition =
let mut bitcoin_processor_composition =
processor_instance(NetworkId::Bitcoin, bitcoin_port, message_queue_keys[&NetworkId::Bitcoin]);
assert_eq!(bitcoin_processor_composition.len(), 1);
let bitcoin_processor_composition = bitcoin_processor_composition.swap_remove(0);
let (monero_composition, monero_port) = network_instance(NetworkId::Monero);
let monero_processor_composition =
let mut monero_processor_composition =
processor_instance(NetworkId::Monero, monero_port, message_queue_keys[&NetworkId::Monero]);
assert_eq!(monero_processor_composition.len(), 1);
let monero_processor_composition = monero_processor_composition.swap_remove(0);
let coordinator_composition = coordinator_instance(name, coord_key);
let serai_composition = serai_composition(name, false);
@@ -161,54 +165,57 @@ pub(crate) async fn new_test(test_body: impl TestBody) {
*OUTER_OPS.get_or_init(|| Mutex::new(None)).lock().await = None;
// Spawns a coordinator, if one has yet to be spawned, or else runs the test.
#[async_recursion::async_recursion]
async fn spawn_coordinator_or_run_test(inner_ops: DockerOperations) {
// If the outer operations have yet to be set, these *are* the outer operations
let outer_ops = OUTER_OPS.get().unwrap();
if outer_ops.lock().await.is_none() {
*outer_ops.lock().await = Some(inner_ops);
}
pub(crate) fn spawn_coordinator_or_run_test(
inner_ops: DockerOperations,
) -> core::pin::Pin<Box<impl Send + Future<Output = ()>>> {
Box::pin(async {
// If the outer operations have yet to be set, these *are* the outer operations
let outer_ops = OUTER_OPS.get().unwrap();
if outer_ops.lock().await.is_none() {
*outer_ops.lock().await = Some(inner_ops);
}
let context_lock = CONTEXT.get().unwrap().lock().await;
let Context { pending_coordinator_compositions, handles, test_body } =
context_lock.as_ref().unwrap();
let context_lock = CONTEXT.get().unwrap().lock().await;
let Context { pending_coordinator_compositions, handles, test_body } =
context_lock.as_ref().unwrap();
// Check if there is a coordinator left
let maybe_coordinator = {
let mut remaining = pending_coordinator_compositions.lock().await;
let maybe_coordinator = if !remaining.is_empty() {
let handles = handles[handles.len() - remaining.len()].clone();
let composition = remaining.remove(0);
Some((composition, handles))
// Check if there is a coordinator left
let maybe_coordinator = {
let mut remaining = pending_coordinator_compositions.lock().await;
let maybe_coordinator = if !remaining.is_empty() {
let handles = handles[handles.len() - remaining.len()].clone();
let composition = remaining.remove(0);
Some((composition, handles))
} else {
None
};
drop(remaining);
maybe_coordinator
};
if let Some((mut composition, handles)) = maybe_coordinator {
let network = {
let outer_ops = outer_ops.lock().await;
let outer_ops = outer_ops.as_ref().unwrap();
// Spawn it by building another DockerTest which recursively calls this function
// TODO: Spawn this outside of DockerTest so we can remove the recursion
let serai_container = outer_ops.handle(&handles.serai);
composition.modify_env("SERAI_HOSTNAME", serai_container.ip());
let message_queue_container = outer_ops.handle(&handles.message_queue);
composition.modify_env("MESSAGE_QUEUE_RPC", message_queue_container.ip());
format!("container:{}", serai_container.name())
};
let mut test = DockerTest::new().with_network(dockertest::Network::External(network));
test.provide_container(composition);
drop(context_lock);
test.run_async(spawn_coordinator_or_run_test).await;
} else {
None
};
drop(remaining);
maybe_coordinator
};
if let Some((mut composition, handles)) = maybe_coordinator {
let network = {
let outer_ops = outer_ops.lock().await;
let outer_ops = outer_ops.as_ref().unwrap();
// Spawn it by building another DockerTest which recursively calls this function
// TODO: Spawn this outside of DockerTest so we can remove the recursion
let serai_container = outer_ops.handle(&handles.serai);
composition.modify_env("SERAI_HOSTNAME", serai_container.ip());
let message_queue_container = outer_ops.handle(&handles.message_queue);
composition.modify_env("MESSAGE_QUEUE_RPC", message_queue_container.ip());
format!("container:{}", serai_container.name())
};
let mut test = DockerTest::new().with_network(dockertest::Network::External(network));
test.provide_container(composition);
drop(context_lock);
test.run_async(spawn_coordinator_or_run_test).await;
} else {
let outer_ops = outer_ops.lock().await.take().unwrap();
test_body.body(outer_ops, handles.clone()).await;
}
let outer_ops = outer_ops.lock().await.take().unwrap();
test_body.body(outer_ops, handles.clone()).await;
}
})
}
test.run_async(spawn_coordinator_or_run_test).await;