Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create epoch duration oracle to get on-ledger epoch duration estimation #18

Merged
merged 7 commits into from
May 30, 2022

Conversation

hypr2771
Copy link
Contributor

epoch_duration_oracle

The goal of this oracle is to provide an on-ledger duration of all passed epoch since creation of the component as well as a way to compute time elapsed between an epoch and the current epoch.

This does not mean to be a precise clock ticking every seconds, but more of an on-ledger information on whether a time milestone was reached or not. This can not be used as a precise timer for short delays, but can show useful to request time between multiple epochs (the bigger the range, the less significant will be the potential error).

All durations are currently in milliseconds.

Use cases

An example of usage could be a timed auction. We would:

  • create the auction with a duration
  • during creation, mark the current epoch
  • when doing various auction actions, we could call the oracle to know whether the time spent between current timestamp and creation timestamp is higher than auction duration, in which case we would end the auction

Instead of providing an "erratic" epoch duration, this would make that auction more precise in terms of human intelligible duration.

Running

Feed the oracle

To run and test the epoch oracle, you can run one of the following:

  • update the oracle only once per epoch (epochs are synchronized with PTE):
me@os:~$ (cd scrypto/epoch_duration_oracle && ./tick_on_epoch.sh)
    Current epoch 633, last epoch 633...
    Current epoch 633, last epoch 633...
    Current epoch set!
    Transaction Status: SUCCESS
    Execution Time: 16 ms
    Instructions:
    ├─ CallMethod { component_address: 020d3869346218a5e8deaaf2001216dc00fcacb79fb43e30ded79a, method: "create_proof_by_amount", args: [Decimal("1"), ResourceAddress("03f1820412ec5c07b54ff0407eb00bfc54f58d0784f3eabc2df9c7")] }
    └─ CallMethod { component_address: 028b858b202333e09f6bf24756b17e51cb6f6882d8bde08a47bdf1, method: "tick", args: [1035068u64] }
    Instruction Outputs:
    ├─ Proof(1024u32)
    └─ 634u64
    Logs: 0
    New Entities: 0
    Current epoch 634, last epoch 634...
    Current epoch 634, last epoch 634...
  • update the oracle each second (starts with epoch from PTE then increments epoch each seconds):
me@os:~$ (cd scrypto/epoch_duration_oracle && ./tick_asap.sh)
    Current epoch set!
    Transaction Status: SUCCESS
    Execution Time: 14 ms
    Instructions:
    ├─ CallMethod { component_address: 020d3869346218a5e8deaaf2001216dc00fcacb79fb43e30ded79a, method: "create_proof_by_amount", args: >     [Decimal("1"), ResourceAddress("0384a3fa191c5506fe5df8a4622cb6eead59deab9d7fc48f64fc98")] }
    └─ CallMethod { component_address: 0244e8cb7761a9b1980e52d70999b4075f182839cec77bfffc1f6c, method: "tick", args: [781u64] }
    Instruction Outputs:
    ├─ Proof(1024u32)
    └─ 10u64
    Logs: 0
    New Entities: 0
    Current epoch set!
    Transaction Status: SUCCESS
    Execution Time: 17 ms
    Instructions:
    ├─ CallMethod { component_address: 020d3869346218a5e8deaaf2001216dc00fcacb79fb43e30ded79a, method: "create_proof_by_amount", args: >     [Decimal("1"), ResourceAddress("0384a3fa191c5506fe5df8a4622cb6eead59deab9d7fc48f64fc98")] }
    └─ CallMethod { component_address: 0244e8cb7761a9b1980e52d70999b4075f182839cec77bfffc1f6c, method: "tick", args: [1063u64] }
    Instruction Outputs:
    ├─ Proof(1024u32)
    └─ 10u64
    Logs: 0
    New Entities: 0

Query time since epoch

To query from the start of the oracle state, you can use:

resim run scrypto/epoch_duration_oracle/manifests/since_epoch_0.manifest

To see the difference, there is also a since_epoch_{current_epoch_on_pte01 + 1}.manifest to compute time elapsed from different epoch and a since_epoch_0.manifest to query elapsed time from the start of the oracle.

e.g.:

resim run scrypto/epoch_duration_oracle/manifests/since_epoch_9.manifest | grep 'Instruction Outputs' -A 1;
resim run scrypto/epoch_duration_oracle/manifests/since_epoch_10.manifest | grep 'Instruction Outputs' -A 1;

ABI

The available functions are:

  • EpochDurationOracle::new: creates a new oracle starting from now and disregarding already elapsed time (does not consider elapsed time of the passed epochs).
  • EpochDurationOracle::new_with_bootstrap(last_epoch: u64, millis_in_last_epoch: u64): creates a new oracle starting from last_epoch which lasted millis_in_last_epoch. This is useful if you want to start the oracle at a given point in time (but after January 1st 1970).

The available method for oracle creator is:

  • EpochDurationOracle::tick(millis_since_last_tick: u64): ticks the internal clock by the provided milliseconds. This can:
    • end the current epoch, categorize it with its duration and start counting down for a new epoch if previous epoch just ended
    • add the tick amount to the epoch being currently counted down
    • this always return the current ledger epoch

The available open methods are:

  • EpochDurationOracle::millis_since_epoch(epoch: u64): measure time passed between provided epoch and current epoch. This can give birth to few cases:

    • the provided epoch is higher than on-ledger epoch: we will return an error
    • the provided epoch is equal to the on-ledger epoch: we will return the time spent on the current epoch
    • the provided epoch is lower than the on-ledger epoch: we will return the time spent between provided epoch and current epoch
    • the provided epoch does not appear for oracle was not created yet: we will return the time spent from the closest lower bound epoch and current epoch (e.g.: if you request time spent from epoch 10 and oracle missed it, but we have epoch 11 and 12 and are in epoch 13, we will compute time spent between epoch 13 and 11 and consider epoch 10 lasted 0. This is acceptable since we are using timestamp, the actual duration will remain correct)
  • EpochDurationOracle::millis_in_epoch(epoch: u64): measure duration of provided epoch. This can give birth to few cases:

    • the provided epoch is higher than on-ledger epoch: we return an error
    • the provided epoch is equal to the on-ledger epoch: we will return the time spent on the current epoch
    • the provided epoch is lower than the on-ledger epoch: we will return the time spent between provided epoch and current epoch
    • the provided epoch is passed but not present on oracle: we will return 0 and suggest calling the millis_since_epoch method

Note: we will be adding a method to get duration between two epochs provided.

@hypr2771 hypr2771 changed the title Create epoch duration oracle Create epoch duration oracle to get on-ledger epoch duration estimation May 25, 2022
Comment on lines +83 to +93
let elapsed: &u64 = self.epochs_duration_millis.get(&epoch)
.unwrap_or_else(|| {
warn!("Epoch was not registered on the oracle, sorry for the inconvenience. We are returning 0 and suggest you call millis_since_epoch or contact an administrator if you absolutely need this epoch duration.");
&0u64
});

if self.epochs_duration_millis.contains_key(&epoch){
return elapsed + self.millis_in_current_epoch
}

*elapsed
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One would guess I ain't no Rust developer, I am pretty sure this part could be improved.

@hypr2771 hypr2771 force-pushed the create_epoch_duration_oracle branch 2 times, most recently from e1043f0 to 1e8edd5 Compare May 25, 2022 22:58
@klembee klembee merged commit e1ea008 into radixdlt:main May 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants