use crate::{AsyncSecureStore, OwnedVid, RelationshipStatus, VerifiedVid};
use futures::StreamExt;
#[tokio::test]
#[serial_test::serial(tcp)]
async fn test_direct_mode() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let mut bobs_messages = bob_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob")
.await
.unwrap();
let mut alice_db = AsyncSecureStore::new();
let alice_vid = OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
alice_db.add_private_vid(alice_vid.clone()).unwrap();
alice_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob", None)
.await
.unwrap();
alice_db
.send(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
Some(b"extra non-confidential data"),
b"hello world",
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::RequestRelationship { .. } =
bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a relationship request message")
};
let crate::definitions::ReceivedTspMessage::GenericMessage {
message,
message_type,
..
} = bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a generic message")
};
assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext);
assert_ne!(
message_type.signature_type,
crate::cesr::SignatureType::NoSignature
);
assert_eq!(message.iter().as_slice(), b"hello world");
}
#[tokio::test]
#[serial_test::serial(tcp)]
async fn test_large_messages() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let mut bobs_messages = bob_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob")
.await
.unwrap();
let mut alice_db = AsyncSecureStore::new();
let alice_vid = OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
alice_db.add_private_vid(alice_vid.clone()).unwrap();
alice_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob", None)
.await
.unwrap();
for i in 1..10 {
let sent_message = "hello world ".repeat(i * 70);
alice_db
.send(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
None,
sent_message.as_bytes(),
)
.await
.unwrap();
if i == 1 {
let crate::definitions::ReceivedTspMessage::RequestRelationship { .. } =
bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a relationship request message")
};
}
let crate::definitions::ReceivedTspMessage::GenericMessage {
message,
message_type,
..
} = bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a generic message")
};
assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext);
assert_ne!(
message_type.signature_type,
crate::cesr::SignatureType::NoSignature
);
assert_eq!(sent_message.as_bytes(), message);
}
}
#[tokio::test]
#[serial_test::serial(tcp)]
async fn test_anycast() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let mut bobs_messages = bob_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob")
.await
.unwrap();
let mut alice_db = AsyncSecureStore::new();
let alice_vid = OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
alice_db.add_private_vid(alice_vid.clone()).unwrap();
alice_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob", None)
.await
.unwrap();
alice_db
.send_anycast(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
&["did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob"],
b"hello world",
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::GenericMessage {
message,
message_type,
..
} = bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a broadcast message")
};
assert_eq!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext);
assert_ne!(
message_type.signature_type,
crate::cesr::SignatureType::NoSignature
);
assert_eq!(message.iter().as_slice(), b"hello world");
}
#[tokio::test]
#[serial_test::serial(tcp)]
async fn test_nested_mode() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let mut alice_db = AsyncSecureStore::new();
let alice_vid = OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
alice_db.add_private_vid(alice_vid.clone()).unwrap();
alice_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob", None)
.await
.unwrap();
let nested_bob_vid = OwnedVid::new_did_peer(bob_vid.endpoint().clone());
bob_db.add_private_vid(nested_bob_vid.clone()).unwrap();
bob_db
.set_parent_for_vid(nested_bob_vid.identifier(), Some(bob_vid.identifier()))
.unwrap();
let mut bobs_inner_messages = bob_db.receive(nested_bob_vid.identifier()).await.unwrap();
let nested_alice_vid = OwnedVid::new_did_peer(alice_vid.endpoint().clone());
alice_db.add_private_vid(nested_alice_vid.clone()).unwrap();
alice_db
.set_parent_for_vid(nested_alice_vid.identifier(), Some(alice_vid.identifier()))
.unwrap();
alice_db
.verify_vid(nested_bob_vid.identifier(), None)
.await
.unwrap();
alice_db
.set_parent_for_vid(nested_bob_vid.identifier(), Some(bob_vid.identifier()))
.unwrap();
alice_db
.set_relation_and_status_for_vid(
nested_bob_vid.identifier(),
RelationshipStatus::Unrelated,
nested_alice_vid.identifier(),
)
.unwrap();
bob_db
.verify_vid(nested_alice_vid.identifier(), None)
.await
.unwrap();
bob_db
.set_parent_for_vid(nested_alice_vid.identifier(), Some(alice_vid.identifier()))
.unwrap();
alice_db
.send(
nested_alice_vid.identifier(),
nested_bob_vid.identifier(),
Some(b"extra non-confidential data"),
b"hello nested world",
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::RequestRelationship { .. } =
bobs_inner_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a relationship request message")
};
let crate::definitions::ReceivedTspMessage::GenericMessage {
message,
message_type,
..
} = bobs_inner_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a generic message inner")
};
assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext);
assert_ne!(
message_type.signature_type,
crate::cesr::SignatureType::NoSignature
);
assert_eq!(message.iter().as_slice(), b"hello nested world");
}
#[tokio::test]
#[serial_test::serial(tcp)]
async fn test_routed_mode() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
let mut alice_db = AsyncSecureStore::new();
let alice_vid = OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
alice_db.add_private_vid(alice_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let mut bobs_messages = bob_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob")
.await
.unwrap();
alice_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob", None)
.await
.unwrap();
alice_db
.set_route_for_vid(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
&[
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
"did:web:hidden.web:endpoint:realbob",
],
)
.unwrap();
alice_db
.set_relation_and_status_for_vid(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
RelationshipStatus::Bidirectional { thread_id: Default::default(), outstanding_nested_thread_ids: vec![] },
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
)
.unwrap();
alice_db
.set_relation_and_status_for_vid(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
RelationshipStatus::Bidirectional { thread_id: Default::default(), outstanding_nested_thread_ids: vec![] },
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
)
.unwrap();
alice_db
.send(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
None,
b"hello self (via bob)",
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::ForwardRequest {
opaque_payload,
sender,
next_hop,
route,
} = bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a forward request")
};
assert_eq!(
sender,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice"
);
assert_eq!(
next_hop,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice"
);
assert_eq!(
route
.iter()
.map(|b| b.iter().as_slice())
.collect::<Vec<_>>(),
vec![b"did:web:hidden.web:endpoint:realbob"]
);
let mut alice_messages = alice_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice")
.await
.unwrap();
bob_db
.set_relation_and_status_for_vid(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
RelationshipStatus::Unrelated,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
)
.unwrap();
bob_db
.forward_routed_message(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
route,
&opaque_payload,
)
.await
.unwrap();
let crate::ReceivedTspMessage::ForwardRequest {
next_hop,
route,
opaque_payload,
..
} = alice_messages.next().await.unwrap().unwrap()
else {
panic!("alice accepted a message which she cannot handle");
};
assert_eq!(next_hop, "did:web:hidden.web:endpoint:realbob");
let crate::Error::UnverifiedVid { .. } = alice_db
.forward_routed_message(&next_hop, route, &opaque_payload)
.await
.unwrap_err()
else {
panic!("unexpected error");
};
let crate::Error::UnverifiedVid { .. } = alice_db
.forward_routed_message(&next_hop, Vec::<&[u8]>::new(), &opaque_payload)
.await
.unwrap_err()
else {
panic!("unexpected error");
};
bob_db
.forward_routed_message(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
vec![b"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob"],
&opaque_payload,
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::ForwardRequest {
sender,
next_hop,
route,
..
} = alice_messages.next().await.unwrap().unwrap()
else {
panic!("alice did not receive message");
};
assert_eq!(
sender,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob"
);
assert_eq!(
next_hop,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob"
);
assert!(route.is_empty());
bob_db
.set_relation_and_status_for_vid(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
RelationshipStatus::Unrelated,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
)
.unwrap();
bob_db
.forward_routed_message(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
Vec::<&[u8]>::new(),
&opaque_payload,
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::GenericMessage {
sender,
message,
message_type,
..
} = alice_messages.next().await.unwrap().unwrap()
else {
panic!("alice did not receive message");
};
assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext);
assert_ne!(
message_type.signature_type,
crate::cesr::SignatureType::NoSignature
);
assert_eq!(
sender,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice"
);
assert_eq!(message.iter().as_slice(), b"hello self (via bob)");
}
#[tokio::test]
async fn attack_failures() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let alice = crate::vid::OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
let bob = crate::vid::verify_vid(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
)
.await
.unwrap();
let payload = b"hello world";
for i in 0.. {
let mut faulty_message =
crate::crypto::seal(&alice, &bob, None, super::Payload::Content(payload)).unwrap();
if i >= faulty_message.len() {
break;
} else {
faulty_message[i] ^= 0x10;
}
if let Ok(msg) = bob_db.open_message(&mut faulty_message) {
let crate::ReceivedTspMessage::PendingMessage {
unknown_vid,
payload,
} = msg
else {
panic!("a corrupted message was decoded correctly! corrupt byte: {i}",);
};
assert_ne!(
unknown_vid,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice"
);
assert!(bob_db.verify_and_open(&unknown_vid, payload).await.is_err());
};
}
}
#[tokio::test]
#[serial_test::serial(tcp)]
async fn test_relation_forming() {
let mut bob_db = AsyncSecureStore::new();
let bob_vid = OwnedVid::from_file("../examples/test/bob/piv.json")
.await
.unwrap();
bob_db.add_private_vid(bob_vid.clone()).unwrap();
bob_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice", None)
.await
.unwrap();
let mut bobs_messages = bob_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob")
.await
.unwrap();
let mut alice_db = AsyncSecureStore::new();
let alice_vid = OwnedVid::from_file("../examples/test/alice/piv.json")
.await
.unwrap();
alice_db.add_private_vid(alice_vid.clone()).unwrap();
alice_db
.verify_vid("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob", None)
.await
.unwrap();
alice_db
.send_relationship_request(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
None,
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::RequestRelationship {
sender, thread_id, ..
} = bobs_messages.next().await.unwrap().unwrap()
else {
panic!("bob did not receive a relation request")
};
let mut alice_messages = alice_db
.receive("did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice")
.await
.unwrap();
assert_eq!(
sender,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice"
);
bob_db
.send_relationship_accept(
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob",
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:alice",
thread_id,
None,
)
.await
.unwrap();
let crate::definitions::ReceivedTspMessage::AcceptRelationship { sender, .. } =
alice_messages.next().await.unwrap().unwrap()
else {
panic!("alice did not receive a relation accept")
};
assert_eq!(
sender,
"did:web:raw.githubusercontent.com:openwallet-foundation-labs:tsp:main:examples:test:bob"
);
}