From d8ca5ad5a72e6e57fa632a1fe1fffac354ebc428 Mon Sep 17 00:00:00 2001 From: Andrew McKenzie Date: Mon, 26 Feb 2024 13:41:34 +0000 Subject: [PATCH] fail beacons with no witnesses --- iot_verifier/src/poc.rs | 15 +++--- iot_verifier/tests/runner_tests.rs | 80 +++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/iot_verifier/src/poc.rs b/iot_verifier/src/poc.rs index 1646847d3..b92d4af3d 100644 --- a/iot_verifier/src/poc.rs +++ b/iot_verifier/src/poc.rs @@ -164,12 +164,15 @@ impl Poc { .await .unwrap_or(*DEFAULT_TX_SCALE); // update 'last beacon' timestamp if the beacon has passed regular validations - LastBeacon::update_last_timestamp( - &self.pool, - beaconer_pub_key.as_ref(), - self.beacon_report.received_timestamp, - ) - .await?; + // but only if there has been at least one witness report + if !self.witness_reports.is_empty() { + LastBeacon::update_last_timestamp( + &self.pool, + beaconer_pub_key.as_ref(), + self.beacon_report.received_timestamp, + ) + .await?; + } // post regular validations, check for beacon reciprocity // if this check fails we will invalidate the beacon // even tho it has passed all regular validations diff --git a/iot_verifier/tests/runner_tests.rs b/iot_verifier/tests/runner_tests.rs index b54026b1d..eb67ee01e 100644 --- a/iot_verifier/tests/runner_tests.rs +++ b/iot_verifier/tests/runner_tests.rs @@ -841,7 +841,9 @@ async fn valid_new_gateway_beacon_first_reciprocity(pool: PgPool) -> anyhow::Res // last beacon timestamp will be updated // let beacon_to_inject = common::create_valid_beacon_report(common::BEACONER5, ctx.entropy_ts); + let witness_to_inject = common::create_valid_witness_report(common::WITNESS1, ctx.entropy_ts); common::inject_beacon_report(pool.clone(), beacon_to_inject.clone()).await?; + common::inject_witness_report(pool.clone(), witness_to_inject.clone()).await?; ctx.runner.handle_db_tick().await?; @@ -983,21 +985,48 @@ async fn valid_beacon_and_no_witnesses(pool: PgPool) -> anyhow::Result<()> { // but yet continues to submit beacon reports to the oracle // also simulates a lone wolf gateway, broadcasting and no one around to hear it // the gateway uses beaconer1 pubkey - // the gateways first activity will be to submit a beacon report - // the gateways last beacon and last witness timestamps will be valid - // and so would normally have passed the beacon reciprocity check, had the beacon been witnessed + // the gateway will not be able to successfully witness other gateways due to reciprocity + // until it has successfully had a beacon witnessed by another gateway // // step 1 - generate a beacon from beaconer1, // this beacon will be valid but will fail reciprocity check as there are no witnesses - // from other gateways for this beacon - // last beacon timestamp will be updated as the beacon itself is actually valid + // from other gateways for the beacon + // last beacon timestamp will NOT as there are no witnesses // let beacon_to_inject = common::create_valid_beacon_report(common::BEACONER1, ctx.entropy_ts); common::inject_beacon_report(pool.clone(), beacon_to_inject.clone()).await?; - // pre-seed last beacons and last witness timestamps into the DB for beaconer 1 - // this means in normal conditions the beacon would pass the reciprocity check + ctx.runner.handle_db_tick().await?; + + let invalid_beacon = ctx.invalid_beacons.receive_invalid_beacon().await; + let invalid_beacon_report = invalid_beacon.report.clone().unwrap(); + println!("{:?}", invalid_beacon); + // assert the pubkeys in the outputted reports + // match those which we injected + assert_eq!( + PublicKeyBinary::from(invalid_beacon_report.pub_key.clone()), + PublicKeyBinary::from_str(common::BEACONER1).unwrap() + ); + // assert the invalid details + assert_eq!( + InvalidReason::GatewayNoValidWitnesses as i32, + invalid_beacon.reason + ); + + // + // step 2 + // generate a beacon from beaconer5 and have it witnessed by beaconer1 + // the witness will fail reciprocity check as beaconer1 does not have + // a current last beacon timestamp + // + + let beacon_to_inject = common::create_valid_beacon_report(common::BEACONER5, ctx.entropy_ts); + let witness_to_inject = common::create_valid_witness_report(common::BEACONER1, ctx.entropy_ts); + common::inject_beacon_report(pool.clone(), beacon_to_inject.clone()).await?; + common::inject_witness_report(pool.clone(), witness_to_inject.clone()).await?; + + // inject last beacon & witness timestamps into the DB for beaconer 5 - allow it to pass reciprocity checks let mut txn = pool.begin().await?; common::inject_last_beacon( &mut txn, @@ -1015,27 +1044,43 @@ async fn valid_beacon_and_no_witnesses(pool: PgPool) -> anyhow::Result<()> { ctx.runner.handle_db_tick().await?; - let invalid_beacon = ctx.invalid_beacons.receive_invalid_beacon().await; - let invalid_beacon_report = invalid_beacon.report.clone().unwrap(); - println!("{:?}", invalid_beacon); + let valid_poc = ctx.valid_pocs.receive_valid_poc().await; + println!("{:?}", valid_poc); + assert_eq!(0, valid_poc.selected_witnesses.len()); + assert_eq!(1, valid_poc.unselected_witnesses.len()); + let valid_beacon = valid_poc.beacon_report.unwrap().report.clone().unwrap(); + let invalid_witness_report = valid_poc.unselected_witnesses[0].clone(); + let invalid_witness = invalid_witness_report.report.unwrap(); // assert the pubkeys in the outputted reports // match those which we injected assert_eq!( - PublicKeyBinary::from(invalid_beacon_report.pub_key.clone()), + PublicKeyBinary::from(valid_beacon.pub_key.clone()), + PublicKeyBinary::from_str(common::BEACONER5).unwrap() + ); + assert_eq!( + PublicKeyBinary::from(invalid_witness.pub_key.clone()), PublicKeyBinary::from_str(common::BEACONER1).unwrap() ); - // assert the invalid details + // assert the witness reports status assert_eq!( - InvalidReason::GatewayNoValidWitnesses as i32, - invalid_beacon.reason + VerificationStatus::Invalid as i32, + invalid_witness_report.status + ); + assert_eq!( + InvalidReason::GatewayNoValidBeacons as i32, + invalid_witness_report.invalid_reason + ); + assert_eq!( + InvalidParticipantSide::Witness as i32, + invalid_witness_report.participant_side ); // - // step 2 - // generate a second beacon from beaconer1 + // step 3 + // generate a second beacon attempt from beaconer1 // and witness the beacon from another gateway - // as the previous beacon attempt did result in the last beacon timestamp being updated // this beacon will pass the reciprocity check now that it has an associated witness + // the witness itself will also pass the reciprocity check as we pre seed necessary timestamps // // sleep to ensure the second beacon fits with the beaconing interval @@ -1053,7 +1098,6 @@ async fn valid_beacon_and_no_witnesses(pool: PgPool) -> anyhow::Result<()> { common::inject_witness_report(pool.clone(), witness_to_inject.clone()).await?; // seed last beacons and witness reports into the DB for witnesser - // beaconer was seeded previously let mut txn = pool.begin().await?; common::inject_last_beacon( &mut txn,