Skip to content

Commit

Permalink
Merge pull request #744 from helium/andymck/andymck/fail-beacon-with-…
Browse files Browse the repository at this point in the history
…no-witnesses-2

fail beacons with no witnesses
  • Loading branch information
andymck authored Feb 26, 2024
2 parents d9ffe4f + d8ca5ad commit 40101d2
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 24 deletions.
15 changes: 9 additions & 6 deletions iot_verifier/src/poc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
80 changes: 62 additions & 18 deletions iot_verifier/tests/runner_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;

Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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,
Expand Down

0 comments on commit 40101d2

Please sign in to comment.