use std::{collections::BTreeSet, str::FromStr, sync::atomic::Ordering};
mod common;
#[allow(unused)]
use ave_common::identity::{HashAlgorithm, hash_borsh};
use ave_common::{
ValueWrapper,
identity::{KeyPair, PublicKey, keys::Ed25519Signer},
request::{ConfirmRequest, EventRequest, FactRequest},
response::RequestState,
};
use ave_core::auth::AuthWitness;
use ave_network::{NodeType, RoutingNode};
use common::{
create_and_authorize_governance, create_nodes_and_connections,
create_subject, emit_confirm, emit_fact, emit_reject, emit_transfer,
get_subject,
};
use futures::future::join_all;
use serde_json::json;
use test_log::test;
use crate::common::{
CreateNodeConfig, CreateNodesAndConnectionsConfig, PORT_COUNTER,
create_node, emit_fact_signed, get_abort_request, node_running,
wait_request, wait_request_state,
};
const EXAMPLE_CONTRACT: &str = "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==";
#[test(tokio::test)]
// distribución manual.
async fn manual_distribution() {
let (mut nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = nodes[0].api.clone();
let creator_1 = nodes[1].api.clone();
let creator_2 = nodes[2].api.clone();
let witness = nodes[3].api.clone();
let governance_id = create_and_authorize_governance(
&owner_governance,
vec![&creator_1, &creator_2, &witness],
)
.await;
// add node bootstrap and ephemeral to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode2",
"key": creator_1.public_key()
},
{
"name": "AveNode3",
"key": creator_2.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2", "AveNode3"
]
}
},
"schema":
[
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode2",
"namespace": [],
"quantity": "infinity"
},
{
"name": "AveNode3",
"namespace": [],
"quantity": "infinity"
}
],
"issuer": [
{
"name": "Any",
"namespace": []
}
]
}
}
]
}
});
emit_fact(&owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let _state = get_subject(&creator_1, governance_id.clone(), Some(1), true)
.await
.unwrap();
let _state = get_subject(&creator_2, governance_id.clone(), Some(1), true)
.await
.unwrap();
let (subject_id, ..) =
create_subject(&creator_1, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
let _request_id =
emit_fact(&creator_1, subject_id.clone(), json.clone(), false)
.await
.unwrap();
let _state = get_subject(&creator_1, subject_id.clone(), Some(1), true)
.await
.unwrap();
let _state =
get_subject(&owner_governance, subject_id.clone(), Some(1), true)
.await
.unwrap();
let json = json!({
"members": {
"add": [
{
"name": "AveNode4",
"key": witness.public_key()
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode4"
]
}
},
"schema":
[
{
"schema_id": "Example",
"add": {
"witness": [
{
"name": "AveNode4",
"namespace": []
}
]
}
}
]
}
});
emit_fact(&owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let _state = get_subject(&creator_1, governance_id.clone(), Some(2), true)
.await
.unwrap();
let _state = get_subject(&creator_2, governance_id.clone(), Some(2), true)
.await
.unwrap();
let _state = get_subject(&witness, governance_id.clone(), Some(2), true)
.await
.unwrap();
assert!(witness.get_subject_state(subject_id.clone()).await.is_err());
creator_1
.manual_distribution(subject_id.clone())
.await
.unwrap();
let _state = get_subject(&witness, subject_id.clone(), Some(1), true)
.await
.unwrap();
nodes[3].token.cancel();
join_all(nodes[3].handler.iter_mut()).await;
emit_transfer(
&creator_1,
subject_id.clone(),
PublicKey::from_str(&creator_2.public_key()).unwrap(),
true,
)
.await
.unwrap();
let _state = get_subject(&creator_2, subject_id.clone(), Some(2), true)
.await
.unwrap();
let _state =
get_subject(&owner_governance, subject_id.clone(), Some(2), true)
.await
.unwrap();
emit_reject(&creator_2, subject_id.clone(), true)
.await
.unwrap();
let _state =
get_subject(&owner_governance, subject_id.clone(), Some(3), true)
.await
.unwrap();
let _state = get_subject(&creator_1, subject_id.clone(), Some(3), true)
.await
.unwrap();
let port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
let listen_address = format!("/memory/{}", port);
let peers = vec![RoutingNode {
peer_id: owner_governance.peer_id().to_string(),
address: vec![nodes[0].listen_address.clone()],
}];
let (node_other_witness, _dirs) = create_node(CreateNodeConfig {
node_type: NodeType::Bootstrap,
listen_address,
peers,
..Default::default()
})
.await;
let new_other_witness = node_other_witness.api.clone();
node_running(&new_other_witness).await.unwrap();
assert!(
new_other_witness
.get_subject_state(governance_id.clone())
.await
.is_err()
);
new_other_witness
.auth_subject(
governance_id.clone(),
AuthWitness::One(
PublicKey::from_str(&owner_governance.public_key()).unwrap(),
),
)
.await
.unwrap();
let json = json!({
"members": {
"add": [
{
"name": "AveNode5",
"key": new_other_witness.public_key()
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode5"
]
}
},
"schema":
[
{
"schema_id": "Example",
"add": {
"witness": [
{
"name": "AveNode5",
"namespace": []
}
]
}
}
]
}
});
emit_fact(&owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
new_other_witness
.update_subject(governance_id.clone())
.await
.unwrap();
let _state =
get_subject(&new_other_witness, governance_id.clone(), Some(3), true)
.await
.unwrap();
assert!(
new_other_witness
.get_subject_state(subject_id.clone())
.await
.is_err()
);
creator_2
.manual_distribution(subject_id.clone())
.await
.unwrap();
let _state =
get_subject(&new_other_witness, subject_id.clone(), Some(3), true)
.await
.unwrap();
}
#[test(tokio::test)]
// Compilamos un contrato bajamos y subimos
async fn test_up_down_compiler() {
let (mut nodes, dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = nodes[0].api.clone();
let governance_id =
create_and_authorize_governance(&owner_governance, vec![]).await;
// add member to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
},
});
emit_fact(&owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
nodes[0].token.cancel();
join_all(nodes[0].handler.iter_mut()).await;
let port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
let listen_address = format!("/memory/{}", port);
let peers = vec![];
let (node_new_node2, _dirs) = create_node(CreateNodeConfig {
node_type: NodeType::Bootstrap,
listen_address,
peers,
always_accept: true,
keys: Some(nodes[0].keys.clone()),
local_db: Some(dirs[0].path().to_path_buf()),
ext_db: Some(dirs[1].path().to_path_buf()),
..Default::default()
})
.await;
let new_owner = node_new_node2.api.clone();
node_running(&new_owner).await.unwrap();
// create subject
let (subject_id, ..) =
create_subject(&new_owner, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
let _request_id =
emit_fact(&new_owner, subject_id.clone(), json.clone(), false)
.await
.unwrap();
let _state = get_subject(&new_owner, subject_id.clone(), Some(1), true)
.await
.unwrap();
}
#[test(tokio::test)]
// El issuer es any
async fn test_issuer_any() {
// Ephemeral -> Bootstrap ≤- Addressable
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let emit_events = &nodes[1].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![emit_events])
.await;
// add node bootstrap and ephemeral to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode2",
"key": emit_events.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2"
]
}
},
"schema":
[
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode2",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Any",
"namespace": []
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (subject_id_1, ..) =
create_subject(emit_events, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
let issuer_keys = KeyPair::Ed25519(Ed25519Signer::generate().unwrap());
emit_fact_signed(
emit_events,
&issuer_keys,
subject_id_1.clone(),
json,
true,
)
.await
.unwrap();
let state = get_subject(emit_events, subject_id_1.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state =
get_subject(owner_governance, subject_id_1.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Testear limitaciones en la creación de sujetos INFINITY - QUANTITY
async fn test_limits_in_subjects() {
// Ephemeral -> Bootstrap ≤- Addressable
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let emit_events = &nodes[1].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![emit_events])
.await;
// add node bootstrap and ephemeral to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode2",
"key": emit_events.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2"
]
}
},
"schema":
[
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode2",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "AveNode2",
"namespace": []
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (subject_id_1, ..) =
create_subject(emit_events, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(emit_events, subject_id_1.clone(), json, true)
.await
.unwrap();
// create other subject and error
let subject_id_error = create_subject(
emit_events,
governance_id.clone(),
"Example",
"",
false,
)
.await;
assert!(subject_id_error.is_err());
// modify the governance to allow more subjects
let json = json!({
"roles": {
"schema": [
{
"schema_id": "Example",
"change": {
"creator": [
{
"actual_name": "AveNode2",
"actual_namespace": [],
"new_quantity": "infinity"
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create other subject
let (subject_id_2, ..) =
create_subject(emit_events, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// now we have two subjects, modify the governance to allow only one
let json = json!({
"roles": {
"schema": [
{
"schema_id": "Example",
"change": {
"creator": [
{
"actual_name": "AveNode2",
"actual_namespace": [],
"new_quantity": 1
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let subject_id_error = create_subject(
emit_events,
governance_id.clone(),
"Example",
"",
false,
)
.await;
assert!(subject_id_error.is_err());
let json = json!({
"ModOne": {
"data": 200,
}
});
emit_fact(emit_events, subject_id_2.clone(), json, true)
.await
.unwrap();
let state = get_subject(emit_events, subject_id_1.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id_1.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(emit_events, subject_id_2.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_2.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 2);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 200, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id_2.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_2.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 2);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 200, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Testear los esppacios de nombre
async fn test_namespace_in_role_1() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0], vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let evaluator = &nodes[0].api;
let owner_governance = &nodes[1].api;
let emit_events = &nodes[2].api;
let witness_schema = &nodes[3].api;
let witness_not_schema = &nodes[4].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![evaluator, emit_events, witness_schema, witness_not_schema],
)
.await;
// Tiene sentido que el las politicas del schema se ponga el rol de aprovador???
let json = json!({
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2", "AveNode3", "AveNode4", "AveNode5"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "AveNode3",
"namespace": ["Spain"]
}
],
"witness": [
{
"name": "AveNode4",
"namespace": ["Spain"]
},
{
"name": "AveNode5",
"namespace": ["Other"]
}
],
"issuer": [
{
"name": "AveNode2",
"namespace": []
}
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode2",
"namespace": ["Spain"],
"quantity": 1
}
]
}
}
]
},
"members": {
"add": [
{
"name": "AveNode2",
"key": emit_events.public_key()
},
{
"name": "AveNode3",
"key": evaluator.public_key()
},
{
"name": "AveNode4",
"key": witness_schema.public_key()
},
{
"name": "AveNode5",
"key": witness_not_schema.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"policies": {
"schema": [
{
"schema_id": "Example",
"change": {
"evaluate": {
"fixed": 10
},
"validate": {
"fixed": 10
}
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let subject_id = create_subject(
emit_events,
governance_id.clone(),
"Example",
"",
false,
)
.await;
assert!(subject_id.is_err());
let subject_id = create_subject(
emit_events,
governance_id.clone(),
"Example",
"Other",
false,
)
.await;
assert!(subject_id.is_err());
let (subject_id, ..) = create_subject(
emit_events,
governance_id.clone(),
"Example",
"Spain",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(emit_events, subject_id.clone(), json, true)
.await
.unwrap();
let state =
get_subject(owner_governance, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(emit_events, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(witness_schema, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
assert!(
witness_not_schema
.get_subject_state(subject_id.clone())
.await
.is_err()
);
}
#[test(tokio::test)]
// Testear los esppacios de nombre
async fn test_namespace_in_role_2() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0], vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let evaluator = &nodes[0].api;
let owner_governance = &nodes[1].api;
let emit_events = &nodes[2].api;
let witness_schema = &nodes[3].api;
let witness_not_schema = &nodes[4].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![evaluator, emit_events, witness_schema, witness_not_schema],
)
.await;
let json = json!({
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2", "AveNode3", "AveNode4", "AveNode5"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "AveNode3",
"namespace": ["Spain"]
}
],
"witness": [
{
"name": "AveNode4",
"namespace": ["Spain", "Canary"]
},
{
"name": "AveNode5",
"namespace": ["Spain", "Canary", "Gran Canaria"]
}
],
"issuer": [
{
"name": "AveNode2",
"namespace": []
}
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode2",
"namespace": ["Spain", "Canary", "Tenerife"],
"quantity": 1
}
]
}
}
]
},
"members": {
"add": [
{
"name": "AveNode2",
"key": emit_events.public_key()
},
{
"name": "AveNode3",
"key": evaluator.public_key()
},
{
"name": "AveNode4",
"key": witness_schema.public_key()
},
{
"name": "AveNode5",
"key": witness_not_schema.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"policies": {
"schema": [
{
"schema_id": "Example",
"change": {
"evaluate": {
"fixed": 10
},
"validate": {
"fixed": 10
}
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let subject_id = create_subject(
emit_events,
governance_id.clone(),
"Example",
"Spain",
false,
)
.await;
assert!(subject_id.is_err());
let subject_id = create_subject(
emit_events,
governance_id.clone(),
"Example",
"Spain.Canary",
false,
)
.await;
assert!(subject_id.is_err());
// create subject in namespace
let (subject_id, ..) = create_subject(
emit_events,
governance_id.clone(),
"Example",
"Spain.Canary.Tenerife",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(emit_events, subject_id.clone(), json, true)
.await
.unwrap();
let state =
get_subject(owner_governance, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain.Canary.Tenerife");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(emit_events, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain.Canary.Tenerife");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(witness_schema, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain.Canary.Tenerife");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, emit_events.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, emit_events.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
assert!(
witness_not_schema
.get_subject_state(subject_id.clone())
.await
.is_err()
);
}
#[test(tokio::test)]
// Testear la transferencia de sujeto
async fn test_subject_transfer_event_1() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0]],
always_accept: true,
..Default::default()
})
.await;
let future_owner = &nodes[0].api;
let owner_governance = &nodes[1].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![future_owner])
.await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": future_owner.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1"
]
}
},
"tracker_schemas": {
"add": {
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
{
"name": "Owner",
"namespace": []
}
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode1",
"namespace": [],
"quantity": "infinity"
},
{
"name": "Owner",
"namespace": [],
"quantity": "infinity"
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(owner_governance, subject_id.clone(), json.clone(), true)
.await
.unwrap();
// autorizar para recibir copias del nuevo sujeto
future_owner
.auth_subject(
subject_id.clone(),
AuthWitness::One(
PublicKey::from_str(&owner_governance.public_key()).unwrap(),
),
)
.await
.unwrap();
// transfer subject
emit_transfer(
owner_governance,
subject_id.clone(),
PublicKey::from_str(&future_owner.public_key()).unwrap(),
true,
)
.await
.unwrap();
future_owner
.update_subject(subject_id.clone())
.await
.unwrap();
let _ = get_subject(future_owner, subject_id.clone(), None, true)
.await
.unwrap();
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
owner_governance.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(transfer_data[0].subject_id, subject_id);
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
owner_governance.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(transfer_data[0].subject_id, subject_id);
emit_confirm(future_owner, subject_id.clone(), None, true)
.await
.unwrap();
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
assert!(
emit_fact(owner_governance, subject_id.clone(), json.clone(), false)
.await
.is_err()
);
let json = json!({
"ModOne": {
"data": 150,
}
});
emit_fact(future_owner, subject_id.clone(), json.clone(), true)
.await
.unwrap();
let state = get_subject(future_owner, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, future_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 4);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, future_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 4);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Testear la transferencia de sujeto, entre dos nodos que no son el owner de la gobernanza
async fn test_subject_transfer_event_2() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let future_owner = &nodes[1].api;
let old_owner = &nodes[2].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![future_owner, old_owner],
)
.await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": future_owner.public_key()
},
{
"name": "AveNode2",
"key": old_owner.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1", "AveNode2"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
{
"name": "AveNode2",
"namespace": []
}
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "AveNode1",
"namespace": [],
"quantity": 1
},
{
"name": "AveNode2",
"namespace": [],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) =
create_subject(old_owner, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(old_owner, subject_id.clone(), json.clone(), true)
.await
.unwrap();
// autorizar para recibir copias del nuevo sujeto
future_owner
.auth_subject(
subject_id.clone(),
AuthWitness::One(
PublicKey::from_str(&owner_governance.public_key()).unwrap(),
),
)
.await
.unwrap();
// transfer subject
emit_transfer(
old_owner,
subject_id.clone(),
PublicKey::from_str(&future_owner.public_key()).unwrap(),
true,
)
.await
.unwrap();
future_owner
.update_subject(subject_id.clone())
.await
.unwrap();
let _ = get_subject(future_owner, subject_id.clone(), None, true)
.await
.unwrap();
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id.to_string()
);
let transfer_data = old_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id.to_string()
);
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id.to_string()
);
old_owner
.auth_subject(
subject_id.clone(),
AuthWitness::One(
PublicKey::from_str(&owner_governance.public_key()).unwrap(),
),
)
.await
.unwrap();
emit_confirm(future_owner, subject_id.clone(), None, true)
.await
.unwrap();
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
let transfer_data = old_owner.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
let _state = get_subject(old_owner, subject_id.clone(), Some(3), true)
.await
.unwrap();
let (subject_id_2, ..) =
create_subject(old_owner, governance_id.clone(), "Example", "", true)
.await
.unwrap();
assert!(
emit_fact(old_owner, subject_id.clone(), json.clone(), false)
.await
.is_err()
);
let json = json!({
"ModOne": {
"data": 150,
}
});
emit_fact(future_owner, subject_id.clone(), json.clone(), true)
.await
.unwrap();
emit_fact(old_owner, subject_id_2.clone(), json.clone(), true)
.await
.unwrap();
let state = get_subject(future_owner, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, future_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 4);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, future_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 4);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
let state = get_subject(old_owner, subject_id_2.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_2.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, old_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id_2.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_2.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, old_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Testear la transferencia de sujeto, entre dos nodos que no son el owner de la gobernanza
// Pero el nuevo owner ya tiene el lÃmite y tiene que hacer reject y el otro recupera el sujeto.
async fn test_subject_transfer_event_3() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let future_owner = &nodes[1].api;
let old_owner = &nodes[2].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![future_owner, old_owner],
)
.await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": future_owner.public_key()
},
{
"name": "AveNode2",
"key": old_owner.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1", "AveNode2"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
{
"name": "AveNode2",
"namespace": []
}
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "AveNode1",
"namespace": [],
"quantity": 1
},
{
"name": "AveNode2",
"namespace": [],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id_1, ..) =
create_subject(old_owner, governance_id.clone(), "Example", "", true)
.await
.unwrap();
let _subject_id_2 = create_subject(
future_owner,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(old_owner, subject_id_1.clone(), json.clone(), true)
.await
.unwrap();
// autorizar para recibir copias del nuevo sujeto
future_owner
.auth_subject(
subject_id_1.clone(),
AuthWitness::One(
PublicKey::from_str(&owner_governance.public_key()).unwrap(),
),
)
.await
.unwrap();
// transfer subject
emit_transfer(
old_owner,
subject_id_1.clone(),
PublicKey::from_str(&future_owner.public_key()).unwrap(),
true,
)
.await
.unwrap();
future_owner
.update_subject(subject_id_1.clone())
.await
.unwrap();
let _ = get_subject(future_owner, subject_id_1.clone(), None, true)
.await
.unwrap();
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id_1.to_string()
);
let transfer_data = old_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id_1.to_string()
);
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id_1.to_string()
);
let request = EventRequest::Confirm(ConfirmRequest {
subject_id: subject_id_1.clone(),
name_old_owner: None,
});
assert!(future_owner.own_request(request).await.is_err());
// El owner no sabe que la transferencia se ha acceptado.
assert!(
create_subject(old_owner, governance_id.clone(), "Example", "", false)
.await
.is_err()
);
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id_1.to_string()
);
let transfer_data = old_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id_1.to_string()
);
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert_eq!(
transfer_data[0].actual_owner.to_string(),
old_owner.public_key()
);
assert_eq!(
transfer_data[0].new_owner.to_string(),
future_owner.public_key()
);
assert_eq!(
transfer_data[0].subject_id.to_string(),
subject_id_1.to_string()
);
emit_reject(future_owner, subject_id_1.clone(), true)
.await
.unwrap();
old_owner
.auth_subject(
subject_id_1.clone(),
AuthWitness::One(
PublicKey::from_str(&owner_governance.public_key()).unwrap(),
),
)
.await
.unwrap();
old_owner
.update_subject(subject_id_1.clone())
.await
.unwrap();
let _ = get_subject(old_owner, subject_id_1.clone(), Some(3), true)
.await
.unwrap();
let transfer_data = old_owner.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
let transfer_data = future_owner.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
let transfer_data = owner_governance.get_pending_transfers().await.unwrap();
assert!(transfer_data.is_empty());
assert!(
emit_fact(future_owner, subject_id_1.clone(), json.clone(), false)
.await
.is_err()
);
let json = json!({
"ModOne": {
"data": 150,
}
});
emit_fact(old_owner, subject_id_1.clone(), json.clone(), true)
.await
.unwrap();
let state = get_subject(old_owner, subject_id_1.clone(), Some(4), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, old_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 4);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
let state =
get_subject(owner_governance, subject_id_1.clone(), Some(4), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, old_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 4);
assert_eq!(
state.properties,
json!({
"one": 150, "three": 0, "two": 0
})
);
let state = get_subject(future_owner, subject_id_1.clone(), Some(3), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, old_owner.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, old_owner.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 3);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Un testigo nuevo reciba las copias de un sujeto que ya va por un sn != 0.
async fn test_dynamic_witnesses_1() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let creator = &nodes[1].api;
let witness = &nodes[2].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![creator]).await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": creator.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "AveNode1",
"namespace": [],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) =
create_subject(creator, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(creator, subject_id.clone(), json.clone(), true)
.await
.unwrap();
let json = json!({
"members": {
"add": [
{
"name": "AveNode2",
"key": witness.public_key()
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2"
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"witness": [
{
"name": "AveNode2",
"namespace": []
}
]
}
}
]
}});
witness
.auth_subject(governance_id.clone(), AuthWitness::None)
.await
.unwrap();
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 200,
}
});
emit_fact(creator, subject_id.clone(), json.clone(), true)
.await
.unwrap();
let _ = get_subject(witness, governance_id.clone(), None, true)
.await
.unwrap();
let state = get_subject(owner_governance, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 2);
assert_eq!(
state.properties,
json!({
"one": 200, "three": 0, "two": 0
})
);
let state = get_subject(witness, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 2);
assert_eq!(
state.properties,
json!({
"one": 200, "three": 0, "two": 0
})
);
let state = get_subject(creator, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 2);
assert_eq!(
state.properties,
json!({
"one": 200, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Un testigo nuevo le pide la copia a otro testigo viejo.
async fn test_dynamic_witnesses_2() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let creator = &nodes[1].api;
let witness = &nodes[2].api;
let new_witness = &nodes[3].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![creator, witness],
)
.await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": creator.public_key()
},
{
"name": "AveNode2",
"key": witness.public_key()
},
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1", "AveNode2"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
],
"witness": [
{
"name": "AveNode2",
"namespace": []
},
{
"name": "Owner",
"namespace": []
}
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "AveNode1",
"namespace": [],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) =
create_subject(creator, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(creator, subject_id.clone(), json.clone(), true)
.await
.unwrap();
let json = json!({
"members": {
"add": [
{
"name": "AveNode3",
"key": new_witness.public_key()
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode3"
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"witness": [
{
"name": "AveNode3",
"namespace": []
}
]
}
}
]
}});
new_witness
.auth_subject(
governance_id.clone(),
AuthWitness::One(
PublicKey::from_str(&witness.public_key()).unwrap(),
),
)
.await
.unwrap();
new_witness
.auth_subject(
subject_id.clone(),
AuthWitness::One(
PublicKey::from_str(&witness.public_key()).unwrap(),
),
)
.await
.unwrap();
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let _ = get_subject(new_witness, governance_id.clone(), None, true)
.await
.unwrap();
new_witness
.update_subject(subject_id.clone())
.await
.unwrap();
let state = get_subject(witness, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(new_witness, subject_id.clone(), Some(1), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(creator, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let json = json!({
"roles": {
"schema": [
{
"schema_id": "Example",
"change": {
"creator": [
{
"actual_name": "AveNode1",
"actual_namespace": [],
"new_witnesses": []
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let json = json!({
"ModTwo": {
"data": 200,
}
});
emit_fact(creator, subject_id.clone(), json, true)
.await
.unwrap();
let state = creator.get_subject_state(subject_id.clone()).await.unwrap();
assert_eq!(state.sn, 2);
let state = witness.get_subject_state(subject_id.clone()).await.unwrap();
assert_eq!(state.sn, 1);
let state = new_witness
.get_subject_state(subject_id.clone())
.await
.unwrap();
assert_eq!(state.sn, 1);
}
#[test(tokio::test)]
// EL Owner_governance es testigo pero Witnesses no es testigo explicito, no recibe copia.
// Un testigo nuevo reciba las copias de un sujeto que ya va por un sn != 0.
async fn test_dynamic_witnesses_explicit_1() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let creator = &nodes[1].api;
let witness = &nodes[2].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![creator, witness],
)
.await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": creator.public_key()
},
{
"name": "AveNode2",
"key": witness.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1", "AveNode2"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "AveNode1",
"namespace": [],
"witnesses": [
{
"name": "AveNode2",
"viewpoints": ["AllViewpoints"]
}
],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) =
create_subject(creator, governance_id.clone(), "Example", "", true)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(creator, subject_id.clone(), json.clone(), true)
.await
.unwrap();
owner_governance
.auth_subject(
subject_id.clone(),
AuthWitness::One(
PublicKey::from_str(&creator.public_key()).unwrap(),
),
)
.await
.unwrap();
owner_governance
.update_subject(subject_id.clone())
.await
.unwrap();
let state = get_subject(creator, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(witness, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
owner_governance
.get_subject_state(subject_id.clone())
.await
.unwrap_err();
}
#[test(tokio::test)]
// 2 sujetos, con diferentes namespace, el owner es testigo no explicito de uno,
// el otro tiene un testigo explicito pero no es el owner
// witness recibe la copia del testigo 1 y owner del 2.
async fn test_dynamic_witnesses_explicit_2() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let creator = &nodes[1].api;
let witness = &nodes[2].api;
let governance_id = create_and_authorize_governance(
owner_governance,
vec![creator, witness],
)
.await;
// add member to governance
let json = json!({
"members": {
"add": [
{
"name": "AveNode1",
"key": creator.public_key()
},
{
"name": "AveNode2",
"key": witness.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode1", "AveNode2"
]
}
},
"tracker_schemas": {
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"issuer": [
{
"name": "AveNode1",
"namespace": []
},
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "AveNode1",
"namespace": [],
"witnesses": [
{
"name": "AveNode2",
"viewpoints": ["AllViewpoints"]
}
],
"quantity": 1
},
{
"name": "AveNode1",
"namespace": ["Spain"],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id_1, ..) =
create_subject(creator, governance_id.clone(), "Example", "", true)
.await
.unwrap();
let (subject_id_2, ..) = create_subject(
creator,
governance_id.clone(),
"Example",
"Spain",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(creator, subject_id_1.clone(), json.clone(), true)
.await
.unwrap();
emit_fact(creator, subject_id_2.clone(), json.clone(), true)
.await
.unwrap();
let state = get_subject(creator, subject_id_1.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(witness, subject_id_1.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
owner_governance
.get_subject_state(subject_id_1.clone())
.await
.unwrap_err();
let state = get_subject(creator, subject_id_2.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_2.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
let state = get_subject(owner_governance, subject_id_2.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_2.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "Spain");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, creator.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, creator.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 100, "three": 0, "two": 0
})
);
witness
.get_subject_state(subject_id_2.clone())
.await
.unwrap_err();
}
#[test(tokio::test)]
// una red sin validadores ni evaluadores para el esquema,
// Vemos que se reinicia la request y la abortamos manualmente.
async fn test_no_subject_validator() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
// add member to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, request_id) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let _ = wait_request_state(
owner_governance,
request_id.clone(),
Some(RequestState::RebootTimeOut {
seconds: 0,
count: 0,
}),
)
.await
.unwrap();
owner_governance
.manual_request_abort(subject_id.clone())
.await
.unwrap();
wait_request_state(
owner_governance,
request_id.clone(),
Some(RequestState::Abort {
subject_id: String::default(),
who: String::default(),
sn: None,
error: String::default(),
}),
)
.await
.unwrap();
let aborts =
get_abort_request(owner_governance, subject_id.clone(), request_id)
.await
.unwrap();
assert_eq!(aborts.events.len(), 1);
assert_eq!(
aborts.events[0].error,
"The user manually aborted the request"
);
}
#[test(tokio::test)]
// una red evaluadores para el esquema,
// Vemos que se reinicia la request y la abortamos manualmente.
async fn test_no_subject_evaluator() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
// add member to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
let request_id =
emit_fact(owner_governance, subject_id.clone(), json.clone(), false)
.await
.unwrap();
let _ = wait_request_state(
owner_governance,
request_id.clone(),
Some(RequestState::RebootTimeOut {
seconds: 0,
count: 0,
}),
)
.await
.unwrap();
owner_governance
.manual_request_abort(subject_id.clone())
.await
.unwrap();
wait_request_state(
owner_governance,
request_id.clone(),
Some(RequestState::Abort {
subject_id: String::default(),
who: String::default(),
sn: None,
error: String::default(),
}),
)
.await
.unwrap();
let aborts =
get_abort_request(owner_governance, subject_id.clone(), request_id)
.await
.unwrap();
assert_eq!(aborts.events.len(), 1);
assert_eq!(
aborts.events[0].error,
"The user manually aborted the request"
);
let state = get_subject(owner_governance, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, owner_governance.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 0);
assert_eq!(
state.properties,
json!({
"one": 0, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// No es issuer
async fn test_no_subject_issuer() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
// add member to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(owner_governance, subject_id.clone(), json.clone(), true)
.await
.unwrap_err();
let state = get_subject(owner_governance, subject_id.clone(), None, true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, owner_governance.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 0);
assert_eq!(
state.properties,
json!({
"one": 0, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Testear 300 eventos sin cooldown para un sujeto
async fn test_300_events() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
// add node bootstrap and ephemeral to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema":
[
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (subject_id_1, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
for i in 0..300 {
// emit event to subject
let json = json!({
"ModOne": {
"data": 1 + i,
}
});
let request = EventRequest::Fact(FactRequest {
subject_id: subject_id_1.clone(),
payload: ValueWrapper(json),
viewpoints: Default::default(),
});
let _response = owner_governance.own_request(request).await.unwrap();
}
let state =
get_subject(owner_governance, subject_id_1.clone(), Some(300), false)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, owner_governance.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 300);
assert_eq!(
state.properties,
json!({
"one": 300, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Definimos 2 validadores con Quorum 1, pero solo funciona uno.
// Hay que tener en cuenta que seleccionar uno es rng, puede seleccionar
// uno que esté o que no
async fn test_subj_no_all_validators() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
let offline_controller =
KeyPair::Ed25519(Ed25519Signer::generate().unwrap())
.public_key()
.to_string();
// add node bootstrap and ephemeral to governance
let json = json!({
"members": {
"add": [
{
"name": "offline",
"key": offline_controller
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema":
[
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
},
{
"name": "offline",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
},
"policies": {
"schema": [
{
"schema_id": "Example",
"change": {
"evaluate": {
"fixed": 1
},
"validate": {
"fixed": 1
}
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (subject_id_1, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 1,
}
});
let request = EventRequest::Fact(FactRequest {
subject_id: subject_id_1.clone(),
payload: ValueWrapper(json),
viewpoints: Default::default(),
});
let _response = owner_governance.own_request(request).await.unwrap();
let state =
get_subject(owner_governance, subject_id_1.clone(), Some(1), false)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, owner_governance.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 1, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Verificar que update protocol actualiza pasivamente la un tracker, a un testigo no al creator.
async fn test_update_protocol() {
let (mut nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
addressable: vec![vec![0], vec![0]],
always_accept: true,
is_service: true,
..Default::default()
})
.await;
let owner_governance = nodes[0].api.clone();
let future_witness = nodes[1].api.clone();
let creator = nodes[2].api.clone();
let governance_id = create_and_authorize_governance(
&owner_governance,
vec![&future_witness, &creator],
)
.await;
let json = json!({
"members": {
"add": [
{
"name": "AveNode2",
"key": future_witness.public_key()
},
{
"name": "AveNode3",
"key": creator.public_key()
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"governance": {
"add": {
"witness": [
"AveNode2", "AveNode3"
]
}
},
"schema": [
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "AveNode3",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "AveNode3",
"namespace": []
}
]
}
}
]
}
});
emit_fact(&owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let _ = get_subject(&future_witness, governance_id.clone(), Some(1), true)
.await
.unwrap();
let _ = get_subject(&creator, governance_id.clone(), Some(1), true)
.await
.unwrap();
let (subject_id, ..) =
create_subject(&creator, governance_id.clone(), "Example", "", true)
.await
.unwrap();
let json = json!({
"ModOne": {
"data": 100,
}
});
emit_fact(&creator, subject_id.clone(), json, true)
.await
.unwrap();
assert!(
future_witness
.get_subject_state(subject_id.clone())
.await
.is_err()
);
let _ = get_subject(&creator, subject_id.clone(), Some(1), true)
.await
.unwrap();
let _ = get_subject(&owner_governance, subject_id.clone(), Some(1), true)
.await
.unwrap();
nodes[2].token.cancel();
join_all(nodes[2].handler.iter_mut()).await;
let json = json!({
"roles": {
"tracker_schemas": {
"add": {
"witness": [
{
"name": "AveNode2",
"namespace": []
}
]
}
}
}
});
emit_fact(&owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let _ = get_subject(&future_witness, subject_id.clone(), Some(1), false)
.await
.unwrap();
}
#[test(tokio::test)]
// Definimos 2 validadores con Quorum 1, pero solo funciona uno.
// Hay que tener en cuenta que seleccionar uno es rng, puede seleccionar
// uno que esté o que no
async fn test_subj_no_all_evaluators() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
let offline_controller =
KeyPair::Ed25519(Ed25519Signer::generate().unwrap())
.public_key()
.to_string();
// add node bootstrap and ephemeral to governance
let json = json!({
"members": {
"add": [
{
"name": "offline",
"key": offline_controller
}
]
},
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema":
[
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
},
{
"name": "offline",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"witness": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
},
"policies": {
"schema": [
{
"schema_id": "Example",
"change": {
"evaluate": {
"fixed": 1
},
"validate": {
"fixed": 1
}
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (subject_id_1, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
// emit event to subject
let json = json!({
"ModOne": {
"data": 1,
}
});
let request = EventRequest::Fact(FactRequest {
subject_id: subject_id_1.clone(),
payload: ValueWrapper(json),
viewpoints: Default::default(),
});
let _response = owner_governance.own_request(request).await.unwrap();
let state =
get_subject(owner_governance, subject_id_1.clone(), Some(1), false)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id_1.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.genesis_gov_version, 1);
assert_eq!(state.namespace, "");
assert_eq!(state.schema_id, "Example");
assert_eq!(state.owner, owner_governance.public_key());
assert_eq!(state.new_owner, None);
assert_eq!(state.creator, owner_governance.public_key());
assert_eq!(state.active, true);
assert_eq!(state.sn, 1);
assert_eq!(
state.properties,
json!({
"one": 1, "three": 0, "two": 0
})
);
}
#[test(tokio::test)]
// Creator infinity, falla porque no hay validadores, luego se completan todas las creaciones.
async fn test_infinty_creations() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
// add member to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": "infinity"
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id_1, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_2, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_3, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_4, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_5, request_id) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let _ = wait_request_state(
owner_governance,
request_id.clone(),
Some(RequestState::RebootTimeOut {
seconds: 0,
count: 0,
}),
)
.await
.unwrap();
let json = json!({
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let _state =
get_subject(owner_governance, subject_id_1.clone(), Some(0), true)
.await
.unwrap();
let _state =
get_subject(owner_governance, subject_id_2.clone(), Some(0), true)
.await
.unwrap();
let _state =
get_subject(owner_governance, subject_id_3.clone(), Some(0), true)
.await
.unwrap();
let _state =
get_subject(owner_governance, subject_id_4.clone(), Some(0), true)
.await
.unwrap();
let _state =
get_subject(owner_governance, subject_id_5.clone(), Some(0), true)
.await
.unwrap();
}
#[test(tokio::test)]
// Creator Quantity 2, falla porque no hay validadores, luego se completa 2 creaciones.
async fn test_quantity_creations() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
// add member to governance
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": "dXNlIHNlcmRlOjp7U2VyaWFsaXplLCBEZXNlcmlhbGl6ZX07CnVzZSBhdmVfY29udHJhY3Rfc2RrIGFzIHNkazsKCi8vLyBEZWZpbmUgdGhlIHN0YXRlIG9mIHRoZSBjb250cmFjdC4gCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUsIENsb25lKV0Kc3RydWN0IFN0YXRlIHsKICBwdWIgb25lOiB1MzIsCiAgcHViIHR3bzogdTMyLAogIHB1YiB0aHJlZTogdTMyCn0KCiNbZGVyaXZlKFNlcmlhbGl6ZSwgRGVzZXJpYWxpemUpXQplbnVtIFN0YXRlRXZlbnQgewogIE1vZE9uZSB7IGRhdGE6IHUzMiB9LAogIE1vZFR3byB7IGRhdGE6IHUzMiB9LAogIE1vZFRocmVlIHsgZGF0YTogdTMyIH0sCiAgTW9kQWxsIHsgb25lOiB1MzIsIHR3bzogdTMyLCB0aHJlZTogdTMyIH0KfQoKI1t1bnNhZmUobm9fbWFuZ2xlKV0KcHViIHVuc2FmZSBmbiBtYWluX2Z1bmN0aW9uKHN0YXRlX3B0cjogaTMyLCBpbml0X3N0YXRlX3B0cjogaTMyLCBldmVudF9wdHI6IGkzMiwgaXNfb3duZXI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmV4ZWN1dGVfY29udHJhY3Qoc3RhdGVfcHRyLCBpbml0X3N0YXRlX3B0ciwgZXZlbnRfcHRyLCBpc19vd25lciwgY29udHJhY3RfbG9naWMpCn0KCiNbdW5zYWZlKG5vX21hbmdsZSldCnB1YiB1bnNhZmUgZm4gaW5pdF9jaGVja19mdW5jdGlvbihzdGF0ZV9wdHI6IGkzMikgLT4gdTMyIHsKICBzZGs6OmNoZWNrX2luaXRfZGF0YShzdGF0ZV9wdHIsIGluaXRfbG9naWMpCn0KCmZuIGluaXRfbG9naWMoCiAgX3N0YXRlOiAmU3RhdGUsCiAgY29udHJhY3RfcmVzdWx0OiAmbXV0IHNkazo6Q29udHJhY3RJbml0Q2hlY2ssCikgewogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQoKZm4gY29udHJhY3RfbG9naWMoCiAgY29udGV4dDogJnNkazo6Q29udGV4dDxTdGF0ZUV2ZW50PiwKICBjb250cmFjdF9yZXN1bHQ6ICZtdXQgc2RrOjpDb250cmFjdFJlc3VsdDxTdGF0ZT4sCikgewogIGxldCBzdGF0ZSA9ICZtdXQgY29udHJhY3RfcmVzdWx0LnN0YXRlOwogIG1hdGNoIGNvbnRleHQuZXZlbnQgewogICAgICBTdGF0ZUV2ZW50OjpNb2RPbmUgeyBkYXRhIH0gPT4gewogICAgICAgIHN0YXRlLm9uZSA9IGRhdGE7CiAgICAgIH0sCiAgICAgIFN0YXRlRXZlbnQ6Ok1vZFR3byB7IGRhdGEgfSA9PiB7CiAgICAgICAgc3RhdGUudHdvID0gZGF0YTsKICAgICAgfSwKICAgICAgU3RhdGVFdmVudDo6TW9kVGhyZWUgeyBkYXRhIH0gPT4gewogICAgICAgIGlmIGRhdGEgPT0gNTAgewogICAgICAgICAgY29udHJhY3RfcmVzdWx0LmVycm9yID0gIkNhbiBub3QgY2hhbmdlIHRocmVlIHZhbHVlLCA1MCBpcyBhIGludmFsaWQgdmFsdWUiLnRvX293bmVkKCk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgc3RhdGUudGhyZWUgPSBkYXRhOwogICAgICB9LAogICAgICBTdGF0ZUV2ZW50OjpNb2RBbGwgeyBvbmUsIHR3bywgdGhyZWUgfSA9PiB7CiAgICAgICAgc3RhdGUub25lID0gb25lOwogICAgICAgIHN0YXRlLnR3byA9IHR3bzsKICAgICAgICBzdGF0ZS50aHJlZSA9IHRocmVlOwogICAgICB9CiAgfQogIGNvbnRyYWN0X3Jlc3VsdC5zdWNjZXNzID0gdHJ1ZTsKfQ==",
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 2
}
]
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
// create subject
let (subject_id_1, request_id_1) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_2, request_id_2) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_3, request_id_3) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_4, request_id_4) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let (subject_id_5, request_id_5) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
false,
)
.await
.unwrap();
let _ = wait_request_state(
owner_governance,
request_id_5.clone(),
Some(RequestState::RebootTimeOut {
seconds: 0,
count: 0,
}),
)
.await
.unwrap();
let json = json!({
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"validator": [
{
"name": "Owner",
"namespace": []
}
],
}
}
]
},
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
wait_request(owner_governance, request_id_1).await.unwrap();
wait_request(owner_governance, request_id_2).await.unwrap();
wait_request(owner_governance, request_id_3).await.unwrap();
wait_request(owner_governance, request_id_4).await.unwrap();
wait_request(owner_governance, request_id_5).await.unwrap();
let mut error = 0;
if owner_governance
.get_subject_state(subject_id_1)
.await
.is_err()
{
error += 1;
}
if owner_governance
.get_subject_state(subject_id_2)
.await
.is_err()
{
error += 1;
}
if owner_governance
.get_subject_state(subject_id_3)
.await
.is_err()
{
error += 1;
}
if owner_governance
.get_subject_state(subject_id_4)
.await
.is_err()
{
error += 1;
}
if owner_governance
.get_subject_state(subject_id_5)
.await
.is_err()
{
error += 1;
}
assert_eq!(error, 3);
}
#[test(tokio::test)]
async fn test_tracker_fact_viewpoints_accept_valid_values() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": EXAMPLE_CONTRACT,
"initial_value": {
"one": 0,
"two": 0,
"three": 0
},
"viewpoints": ["agua", "basura"]
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (subject_id, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
let request = EventRequest::Fact(FactRequest {
subject_id: subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 1
}
})),
viewpoints: BTreeSet::new(),
});
let response = owner_governance.own_request(request).await.unwrap();
wait_request(owner_governance, response.request_id)
.await
.unwrap();
let request = EventRequest::Fact(FactRequest {
subject_id: subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 2
}
})),
viewpoints: BTreeSet::from(["agua".to_owned()]),
});
let response = owner_governance.own_request(request).await.unwrap();
wait_request(owner_governance, response.request_id)
.await
.unwrap();
let request = EventRequest::Fact(FactRequest {
subject_id: subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 3
}
})),
viewpoints: BTreeSet::from(["agua".to_owned(), "basura".to_owned()]),
});
let response = owner_governance.own_request(request).await.unwrap();
wait_request(owner_governance, response.request_id)
.await
.unwrap();
let state =
get_subject(owner_governance, subject_id.clone(), Some(3), true)
.await
.unwrap();
assert_eq!(state.subject_id, subject_id.to_string());
assert_eq!(state.governance_id, governance_id.to_string());
assert_eq!(state.sn, 3);
assert_eq!(
state.properties,
json!({
"one": 3,
"two": 0,
"three": 0
})
);
}
#[test(tokio::test)]
async fn test_tracker_fact_viewpoints_reject_invalid_values() {
let (nodes, _dirs) =
create_nodes_and_connections(CreateNodesAndConnectionsConfig {
bootstrap: vec![vec![]],
always_accept: true,
..Default::default()
})
.await;
let owner_governance = &nodes[0].api;
let governance_id =
create_and_authorize_governance(owner_governance, vec![]).await;
let json = json!({
"schemas": {
"add": [
{
"id": "Example",
"contract": EXAMPLE_CONTRACT,
"initial_value": {
"one": 0,
"two": 0,
"three": 0
},
"viewpoints": ["agua", "basura"]
},
{
"id": "Plain",
"contract": EXAMPLE_CONTRACT,
"initial_value": {
"one": 0,
"two": 0,
"three": 0
}
}
]
},
"roles": {
"schema": [
{
"schema_id": "Example",
"add": {
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
},
{
"schema_id": "Plain",
"add": {
"validator": [
{
"name": "Owner",
"namespace": []
}
],
"evaluator": [
{
"name": "Owner",
"namespace": []
}
],
"creator": [
{
"name": "Owner",
"namespace": [],
"quantity": 1
}
],
"issuer": [
{
"name": "Owner",
"namespace": []
}
]
}
}
]
}
});
emit_fact(owner_governance, governance_id.clone(), json, true)
.await
.unwrap();
let (example_subject_id, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Example",
"",
true,
)
.await
.unwrap();
let (plain_subject_id, ..) = create_subject(
owner_governance,
governance_id.clone(),
"Plain",
"",
true,
)
.await
.unwrap();
let request = EventRequest::Fact(FactRequest {
subject_id: governance_id.clone(),
payload: ValueWrapper(json!({
"members": {
"add": [
{
"name": "Alice",
"key": owner_governance.public_key()
}
]
}
})),
viewpoints: BTreeSet::from(["agua".to_owned()]),
});
assert!(owner_governance.own_request(request).await.is_err());
let request = EventRequest::Fact(FactRequest {
subject_id: plain_subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 1
}
})),
viewpoints: BTreeSet::from(["agua".to_owned()]),
});
assert!(owner_governance.own_request(request).await.is_err());
let request = EventRequest::Fact(FactRequest {
subject_id: example_subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 1
}
})),
viewpoints: BTreeSet::from(["NoViewpoints".to_owned()]),
});
assert!(owner_governance.own_request(request).await.is_err());
let request = EventRequest::Fact(FactRequest {
subject_id: example_subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 1
}
})),
viewpoints: BTreeSet::from(["AllViewpoints".to_owned()]),
});
assert!(owner_governance.own_request(request).await.is_err());
let request = EventRequest::Fact(FactRequest {
subject_id: example_subject_id.clone(),
payload: ValueWrapper(json!({
"ModOne": {
"data": 1
}
})),
viewpoints: BTreeSet::from(["vidrio".to_owned()]),
});
assert!(owner_governance.own_request(request).await.is_err());
let state = get_subject(
owner_governance,
example_subject_id.clone(),
Some(0),
true,
)
.await
.unwrap();
assert_eq!(state.subject_id, example_subject_id.to_string());
assert_eq!(state.sn, 0);
let state =
get_subject(owner_governance, plain_subject_id.clone(), Some(0), true)
.await
.unwrap();
assert_eq!(state.subject_id, plain_subject_id.to_string());
assert_eq!(state.sn, 0);
}