Processing Refactor (#409)

* refactor: have proversync cache proofs upon tree update

* refactor: start introducing acceptableRoot into replica

* refactor: set confirmAt to 1 for initial root

* refactor: remove previous from replica trait

* refactor: processor no longer bails on missing proof

* tests: fix the tests

* refactor: remove last use of tokio::time::interval

* refactor: remove redundant condition in replica
buddies-main-deployment
James Prestwich 3 years ago committed by GitHub
parent 5eb7b7f174
commit 6487fcb3eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .gitignore
  2. 6
      rust/optics-base/src/macros.rs
  3. 8
      rust/optics-base/src/replica.rs
  4. 2
      rust/optics-core/src/accumulator/incremental.rs
  5. 41
      rust/optics-core/src/accumulator/merkle.rs
  6. 3
      rust/optics-core/src/traits/replica.rs
  7. 13
      rust/optics-ethereum/abis/Replica.abi.json
  8. 5
      rust/optics-ethereum/src/replica.rs
  9. 6
      rust/optics-test/src/mocks/replica.rs
  10. 72
      rust/processor/src/processor.rs
  11. 2
      rust/processor/src/prover/mod.rs
  12. 52
      rust/processor/src/prover/prover_sync.rs
  13. 32
      rust/watcher/src/watcher.rs
  14. 40
      solidity/optics-core/contracts/Replica.sol
  15. 1
      solidity/optics-core/contracts/test/TestReplica.sol
  16. 10
      solidity/optics-core/test/Replica.test.js
  17. 4
      solidity/optics-core/test/cross-chain/SimpleMessage.test.js
  18. 13
      typescript/src/typechain/optics-core/Replica.d.ts
  19. 13
      typescript/src/typechain/optics-core/TestReplica.d.ts
  20. 2
      typescript/src/typechain/optics-core/factories/GovernanceRouter__factory.ts
  21. 2
      typescript/src/typechain/optics-core/factories/Home__factory.ts
  22. 15
      typescript/src/typechain/optics-core/factories/Replica__factory.ts
  23. 2
      typescript/src/typechain/optics-core/factories/TestCommon__factory.ts
  24. 2
      typescript/src/typechain/optics-core/factories/TestGovernanceRouter__factory.ts
  25. 2
      typescript/src/typechain/optics-core/factories/TestHome__factory.ts
  26. 2
      typescript/src/typechain/optics-core/factories/TestMessage__factory.ts
  27. 15
      typescript/src/typechain/optics-core/factories/TestReplica__factory.ts
  28. 2
      typescript/src/typechain/optics-core/factories/TestXAppConnectionManager__factory.ts
  29. 2
      typescript/src/typechain/optics-core/factories/TypedMemView__factory.ts
  30. 2
      typescript/src/typechain/optics-core/factories/UpdaterManager__factory.ts
  31. 2
      typescript/src/typechain/optics-core/factories/UpgradeBeaconProxy__factory.ts
  32. 2
      typescript/src/typechain/optics-core/factories/XAppConnectionManager__factory.ts

1
.gitignore vendored

@ -5,3 +5,4 @@ config.json
typescript/tmp.ts
rust/tmp_db
rust/tmp.env
tmp.env

@ -1,7 +1,7 @@
#[macro_export]
/// Shortcut for resetting a timed loop
macro_rules! reset_loop {
($interval:ident) => {{
($interval:expr) => {{
tokio::time::sleep(std::time::Duration::from_secs($interval)).await;
continue;
}};
@ -10,12 +10,12 @@ macro_rules! reset_loop {
#[macro_export]
/// Shortcut for conditionally resetting a timed loop
macro_rules! reset_loop_if {
($condition:expr, $interval:ident) => {
($condition:expr, $interval:expr) => {
if $condition {
$crate::reset_loop!($interval);
}
};
($condition:expr, $interval:ident, $($arg:tt)*) => {
($condition:expr, $interval:expr, $($arg:tt)*) => {
if $condition {
tracing::info!($($arg)*);
$crate::reset_loop!($interval);

@ -98,14 +98,6 @@ impl Replica for Replicas {
}
}
async fn previous_root(&self) -> Result<H256, ChainCommunicationError> {
match self {
Replicas::Ethereum(replica) => replica.previous_root().await,
Replicas::Mock(mock_replica) => mock_replica.previous_root().await,
Replicas::Other(replica) => replica.previous_root().await,
}
}
async fn next_to_process(&self) -> Result<u32, ChainCommunicationError> {
match self {
Replicas::Ethereum(replica) => replica.next_to_process().await,

@ -75,7 +75,7 @@ impl IncrementalMerkle {
/// Verify a incremental merkle proof of inclusion
pub fn verify(&self, proof: &Proof) -> bool {
let computed = IncrementalMerkle::branch_root(proof.leaf, proof.path, proof.index);
let computed = IncrementalMerkle::branch_root(proof.leaf, proof.path, proof.index as usize);
computed == self.root()
}
}

@ -2,7 +2,10 @@ use ethers::core::types::H256;
use lazy_static::lazy_static;
use thiserror::Error;
use crate::accumulator::{hash_concat, EMPTY_SLICE, TREE_DEPTH, ZERO_HASHES};
use crate::{
accumulator::{hash_concat, EMPTY_SLICE, TREE_DEPTH, ZERO_HASHES},
Decode, Encode,
};
// Some code has been derived from
// https://github.com/sigp/lighthouse/blob/c6baa0eed131c5e8ecc5860778ffc7d4a4c18d2d/consensus/merkle_proof/src/lib.rs#L25
@ -48,6 +51,42 @@ pub struct Proof {
pub path: [H256; TREE_DEPTH],
}
impl Encode for Proof {
fn write_to<W>(&self, writer: &mut W) -> std::io::Result<usize>
where
W: std::io::Write,
{
writer.write_all(self.leaf.as_bytes())?;
writer.write_all(&self.index.to_be_bytes())?;
for hash in self.path.iter() {
writer.write_all(hash.as_bytes())?;
}
Ok(32 + 8 + TREE_DEPTH * 32)
}
}
impl Decode for Proof {
fn read_from<R>(reader: &mut R) -> Result<Self, crate::OpticsError>
where
R: std::io::Read,
Self: Sized,
{
let mut leaf = H256::default();
let mut index_bytes = [0u8; 8];
let mut path = [H256::default(); 32];
reader.read_exact(leaf.as_bytes_mut())?;
reader.read_exact(&mut index_bytes)?;
for item in &mut path {
reader.read_exact(item.as_bytes_mut())?;
}
let index = u64::from_be_bytes(index_bytes) as usize;
Ok(Self { leaf, index, path })
}
}
/// Error type for merkle tree ops.
#[derive(Debug, PartialEq, Clone, Error)]
pub enum MerkleTreeError {

@ -36,9 +36,6 @@ pub trait Replica: Common + Send + Sync + std::fmt::Debug {
/// Confirm the next pending root (after its timer has elapsed);
async fn confirm(&self) -> Result<TxOutcome, ChainCommunicationError>;
/// Fetch the previous root.
async fn previous_root(&self) -> Result<H256, ChainCommunicationError>;
/// Fetch the last processed sequence number
async fn next_to_process(&self) -> Result<u32, ChainCommunicationError>;

@ -313,19 +313,6 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "previous",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{

@ -211,11 +211,6 @@ where
Ok(report_tx!(tx).into())
}
#[tracing::instrument(err)]
async fn previous_root(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.previous().call().await?.into())
}
#[tracing::instrument(err)]
async fn next_to_process(&self) -> Result<u32, ChainCommunicationError> {
Ok(self.contract.next_to_process().call().await?)

@ -24,8 +24,6 @@ mock! {
pub fn _confirm(&self) -> Result<TxOutcome, ChainCommunicationError> {}
pub fn _previous_root(&self) -> Result<H256, ChainCommunicationError> {}
pub fn _next_to_process(&self) -> Result<u32, ChainCommunicationError> {}
pub fn _prove(&self, proof: &Proof) -> Result<TxOutcome, ChainCommunicationError> {}
@ -100,10 +98,6 @@ impl Replica for MockReplicaContract {
self._confirm()
}
async fn previous_root(&self) -> Result<H256, ChainCommunicationError> {
self._previous_root()
}
async fn next_to_process(&self) -> Result<u32, ChainCommunicationError> {
self._next_to_process()
}

@ -1,21 +1,23 @@
use async_trait::async_trait;
use color_eyre::{
eyre::{eyre, WrapErr},
eyre::{bail, eyre, WrapErr},
Result,
};
use futures_util::future::select_all;
use std::{collections::HashMap, sync::Arc};
use rocksdb::DB;
use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::{
sync::{oneshot::channel, RwLock},
task::JoinHandle,
time::sleep,
};
use tracing::{info, instrument, Instrument};
use tracing::{error, info, instrument, Instrument};
use optics_base::{
agent::{AgentCore, OpticsAgent},
cancel_task, decl_agent,
home::Homes,
persistence::UsingPersistence,
replica::Replicas,
reset_loop_if,
};
@ -31,33 +33,40 @@ use crate::{
#[derive(Debug)]
pub(crate) struct ReplicaProcessor {
interval_seconds: u64,
interval: u64,
replica: Arc<Replicas>,
home: Arc<Homes>,
prover: Arc<RwLock<Prover>>,
db: Arc<DB>,
}
impl UsingPersistence<usize, Proof> for ReplicaProcessor {
const KEY_PREFIX: &'static [u8] = "proof_".as_bytes();
fn key_to_bytes(key: usize) -> Vec<u8> {
key.to_be_bytes().into()
}
}
impl ReplicaProcessor {
pub(crate) fn new(
interval_seconds: u64,
interval: u64,
replica: Arc<Replicas>,
home: Arc<Homes>,
prover: Arc<RwLock<Prover>>,
db: Arc<DB>,
) -> Self {
Self {
interval_seconds,
interval,
replica,
home,
prover,
db,
}
}
#[instrument]
pub(crate) fn spawn(self) -> JoinHandle<Result<()>> {
tokio::spawn(async move {
info!("Starting processor");
info!("Starting processor for {}", self.replica.name());
let domain = self.replica.local_domain();
let interval = self.interval_seconds;
// The basic structure of this loop is as follows:
// 1. Get the last processed index
@ -77,28 +86,29 @@ impl ReplicaProcessor {
let message = self.home.message_by_sequence(domain, sequence).await?;
reset_loop_if!(
message.is_none(),
interval,
self.interval,
"Home does not contain message at {}:{}",
domain,
sequence
sequence,
);
let message = message.unwrap();
// Lock is dropped immediately
let proof_res = self.prover.read().await.prove(message.leaf_index as usize);
let proof_opt = Self::db_get(&self.db, message.leaf_index as usize)?;
reset_loop_if!(
proof_res.is_err(),
interval,
"Prover does not contain leaf at index {}",
message.leaf_index
proof_opt.is_none(),
self.interval,
"Proof not yet available for message at {}:{}",
domain,
sequence,
);
let proof = proof_res.unwrap();
let proof = proof_opt.unwrap();
if proof.leaf != message.to_leaf() {
let err = format!("Leaf in prover does not match retrieved message. Index: {}. Calculated: {}. Prover: {}.", message.leaf_index, message.to_leaf(), proof.leaf);
tracing::error!("{}", err);
color_eyre::eyre::bail!(err);
error!("{}", err);
bail!(err);
}
// Dispatch for processing
@ -108,7 +118,7 @@ impl ReplicaProcessor {
);
self.process(message, proof).await?;
sleep(std::time::Duration::from_secs(interval)).await;
sleep(Duration::from_secs(self.interval)).await;
}
}.in_current_span())
}
@ -137,7 +147,7 @@ impl ReplicaProcessor {
decl_agent!(
/// A processor agent
Processor {
interval_seconds: u64,
interval: u64,
prover: Arc<RwLock<Prover>>,
replica_tasks: RwLock<HashMap<String, JoinHandle<Result<()>>>>,
}
@ -145,9 +155,9 @@ decl_agent!(
impl Processor {
/// Instantiate a new processor
pub fn new(interval_seconds: u64, core: AgentCore) -> Self {
pub fn new(interval: u64, core: AgentCore) -> Self {
Self {
interval_seconds,
interval,
prover: Arc::new(RwLock::new(Prover::from_disk(&core.db))),
core,
replica_tasks: Default::default(),
@ -172,15 +182,15 @@ impl OpticsAgent for Processor {
fn run(&self, name: &str) -> JoinHandle<Result<()>> {
let home = self.home();
let prover = self.prover.clone();
let interval_seconds = self.interval_seconds;
let interval = self.interval;
let replica_opt = self.replica_by_name(name);
let name = name.to_owned();
let db = self.db();
tokio::spawn(async move {
let replica = replica_opt.ok_or_else(|| eyre!("No replica named {}", name))?;
ReplicaProcessor::new(interval_seconds, replica, home, prover)
ReplicaProcessor::new(interval, replica, home, db)
.spawn()
.await?
})
@ -189,12 +199,12 @@ impl OpticsAgent for Processor {
#[tracing::instrument(err)]
async fn run_many(&self, replicas: &[&str]) -> Result<()> {
let (_tx, rx) = channel();
let interval_seconds = self.interval_seconds;
let interval = self.interval;
info!("Starting ProverSync task");
let sync = ProverSync::new(self.prover.clone(), self.home(), self.db(), rx);
let sync_task = tokio::spawn(async move {
sync.poll_updates(interval_seconds)
sync.spawn(interval)
.await
.wrap_err("ProverSync task has shut down")
});

@ -109,7 +109,7 @@ impl Prover {
return Err(ProverError::IndexTooHigh(index));
}
let count = self.count();
if index >= count as usize {
if index >= count {
return Err(ProverError::ZeroProof { index, count });
}

@ -2,7 +2,7 @@ use crate::prover::{Prover, ProverError};
use ethers::core::types::H256;
use optics_base::{db::UsingPersistence, home::Homes};
use optics_core::{
accumulator::{incremental::IncrementalMerkle, INITIAL_ROOT},
accumulator::{incremental::IncrementalMerkle, merkle::Proof, INITIAL_ROOT},
traits::{ChainCommunicationError, Common, Home},
};
use rocksdb::DB;
@ -19,15 +19,23 @@ use tracing::info;
/// Struct to sync prover.
#[derive(Debug)]
pub struct ProverSync {
prover: Arc<RwLock<Prover>>,
home: Arc<Homes>,
incremental: IncrementalMerkle,
db: Arc<DB>,
prover: Arc<RwLock<Prover>>,
incremental: IncrementalMerkle,
rx: Receiver<()>,
}
impl UsingPersistence<usize, H256> for ProverSync {
const KEY_PREFIX: &'static [u8] = "index_".as_bytes();
const KEY_PREFIX: &'static [u8] = "leaf_".as_bytes();
fn key_to_bytes(key: usize) -> Vec<u8> {
key.to_be_bytes().into()
}
}
impl UsingPersistence<usize, Proof> for ProverSync {
const KEY_PREFIX: &'static [u8] = "proof_".as_bytes();
fn key_to_bytes(key: usize) -> Vec<u8> {
key.to_be_bytes().into()
@ -88,7 +96,11 @@ impl ProverSync {
}
fn store_leaf(&mut self, index: usize, leaf: H256) {
Self::db_put(&self.db, index, leaf).expect("!db_put");
Self::db_put(&self.db, index, leaf).expect("!db_put_leaf");
}
fn store_proof(&mut self, index: usize, proof: Proof) {
Self::db_put(&self.db, index, proof).expect("!db_put_proof");
}
fn retrieve_leaf(&self, index: usize) -> Option<H256> {
@ -136,9 +148,11 @@ impl ProverSync {
new_root: H256,
) -> Result<(), ProverSyncError> {
// If roots don't match by end of incremental update, will return
// MismatchedRoots error
let range = self.update_incremental(local_root, new_root).await?;
let leaves = self.get_leaf_range(range.clone()).await?;
// MismatchedRoots error.
// We destructure the range here to avoid cloning it several times
// later on.
let Range { start, end } = self.update_incremental(local_root, new_root).await?;
let leaves = self.get_leaf_range(start..end).await?;
// Check that local root still equals prover's root just in case
// another entity wrote to prover while we were building the leaf
@ -150,18 +164,30 @@ impl ProverSync {
}
// Extend in-memory tree
info!(
"Committing leaves {}..{} to prover.",
range.start, range.end
);
info!("Committing leaves {}..{} to prover.", start, end);
let leaves = leaves.into_iter();
let mut proofs = vec![];
{
// lock bounds
let mut prover = self.prover.write().await;
prover.extend(leaves.clone());
assert_eq!(new_root, prover.root());
info!("Committed {} leaves to prover.", leaves.len());
// calculate a proof under the current root for each leaf
for idx in start..end {
let proof = prover.prove(idx)?;
proofs.push((idx, proof));
}
}
// store all calculated proofs in the db
for (idx, proof) in proofs {
self.store_proof(idx, proof);
}
info!("Stored proofs for leaves {}..{}", start, end);
Ok(())
}
@ -226,7 +252,7 @@ impl ProverSync {
/// new root. Use short interval for bootup syncing and longer
/// interval for regular polling.
#[tracing::instrument(err, skip(self))]
pub async fn poll_updates(mut self, interval_seconds: u64) -> Result<(), ProverSyncError> {
pub async fn spawn(mut self, interval_seconds: u64) -> Result<(), ProverSyncError> {
loop {
let local_root = self.local_root().await;
let signed_update_opt = self.home.signed_update_by_old_root(local_root).await?;

@ -8,11 +8,11 @@ use thiserror::Error;
use ethers::core::types::H256;
use futures_util::future::{join, join_all};
use rocksdb::DB;
use std::{collections::HashMap, sync::Arc};
use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::{
sync::{mpsc, RwLock},
task::JoinHandle,
time::{interval, Interval},
time::sleep,
};
use optics_base::{
@ -40,7 +40,7 @@ pub struct ContractWatcher<C>
where
C: Common + ?Sized + 'static,
{
interval_seconds: u64,
interval: u64,
current_root: H256,
tx: mpsc::Sender<SignedUpdate>,
contract: Arc<C>,
@ -51,23 +51,19 @@ where
C: Common + ?Sized + 'static,
{
pub fn new(
interval_seconds: u64,
interval: u64,
from: H256,
tx: mpsc::Sender<SignedUpdate>,
contract: Arc<C>,
) -> Self {
Self {
interval_seconds,
interval,
current_root: from,
tx,
contract,
}
}
fn interval(&self) -> Interval {
interval(std::time::Duration::from_secs(self.interval_seconds))
}
async fn poll_and_send_update(&mut self) -> Result<()> {
let update_opt = self
.contract
@ -88,11 +84,9 @@ where
#[tracing::instrument]
fn spawn(mut self) -> JoinHandle<Result<()>> {
tokio::spawn(async move {
let mut interval = self.interval();
loop {
self.poll_and_send_update().await?;
interval.tick().await;
sleep(Duration::from_secs(self.interval)).await;
}
})
}
@ -103,7 +97,7 @@ pub struct HistorySync<C>
where
C: Common + ?Sized + 'static,
{
interval_seconds: u64,
interval: u64,
current_root: H256,
tx: mpsc::Sender<SignedUpdate>,
contract: Arc<C>,
@ -114,7 +108,7 @@ where
C: Common + ?Sized + 'static,
{
pub fn new(
interval_seconds: u64,
interval: u64,
from: H256,
tx: mpsc::Sender<SignedUpdate>,
contract: Arc<C>,
@ -123,14 +117,10 @@ where
current_root: from,
tx,
contract,
interval_seconds,
interval,
}
}
fn interval(&self) -> Interval {
interval(std::time::Duration::from_secs(self.interval_seconds))
}
async fn update_history(&mut self) -> Result<()> {
let previous_update = self
.contract
@ -159,8 +149,6 @@ where
#[tracing::instrument]
fn spawn(mut self) -> JoinHandle<Result<()>> {
tokio::spawn(async move {
let mut interval = self.interval();
loop {
let res = self.update_history().await;
if res.is_err() {
@ -168,7 +156,7 @@ where
break;
}
interval.tick().await;
sleep(Duration::from_secs(self.interval)).await;
}
Ok(())

@ -36,8 +36,6 @@ contract Replica is Initializable, Common, QueueManager {
/// @notice Index of last processed message's leaf in home's merkle tree
uint32 public nextToProcess;
bytes32 public previous; // to smooth over witness invalidation
/// @notice Mapping of enqueued roots to allowable confirmation times
mapping(bytes32 => uint256) public confirmAt;
@ -51,6 +49,14 @@ contract Replica is Initializable, Common, QueueManager {
constructor(uint32 _localDomain) Common(_localDomain) {} // solhint-disable-line no-empty-blocks
function acceptableRoot(bytes32 _root) internal view returns (bool) {
uint256 _time = confirmAt[_root];
if (_time == 0) {
return false;
}
return block.timestamp >= _time;
}
function initialize(
uint32 _remoteDomain,
address _updater,
@ -63,6 +69,7 @@ contract Replica is Initializable, Common, QueueManager {
queue.initialize();
current = _current;
confirmAt[_current] = 1;
optimisticSeconds = _optimisticSeconds;
nextToProcess = _nextToProcess;
@ -111,21 +118,21 @@ contract Replica is Initializable, Common, QueueManager {
* @dev Reverts if queue started as empty (i.e. no roots to confirm)
**/
function confirm() external notFailed {
require(queue.length() != 0, "no pending");
require(queue.length() != 0, "!pending");
bytes32 _pending;
uint256 _timestamp = block.timestamp;
// Traverse the queue by peeking each iterm to see if it ought to be
// confirmed. If so, dequeue it
uint256 _remaining = queue.length();
while (_remaining > 0 && _timestamp >= confirmAt[queue.peek()]) {
while (_remaining > 0 && acceptableRoot(queue.peek())) {
_pending = queue.dequeue();
delete confirmAt[_pending];
_remaining -= 1;
}
// This condition is hit if the while loop is never executed, because
// the first queue item has not hit its timer yet
require(_pending != bytes32(0), "not time");
require(_pending != bytes32(0), "!time");
_beforeConfirm();
@ -165,6 +172,9 @@ contract Replica is Initializable, Common, QueueManager {
if (queue.length() != 0) {
_pending = queue.peek();
_confirmAt = confirmAt[_pending];
} else {
_pending = current;
_confirmAt = confirmAt[current];
}
}
@ -173,8 +183,7 @@ contract Replica is Initializable, Common, QueueManager {
* root in the queue and false if otherwise.
**/
function canConfirm() external view returns (bool) {
return
queue.length() != 0 && block.timestamp >= confirmAt[queue.peek()];
return queue.length() != 0 && acceptableRoot(queue.peek());
}
/**
@ -254,9 +263,9 @@ contract Replica is Initializable, Common, QueueManager {
bytes32 _actual = MerkleLib.branchRoot(_leaf, _proof, _index);
// NB:
// For convenience, we allow proving against the previous root.
// This means that witnesses don't need to be updated for the new root
if (_actual == current || _actual == previous) {
// For convenience, we allow proving against any previous root.
// This means that witnesses never need to be updated for the new root
if (acceptableRoot(_actual)) {
messages[_leaf] = MessageStatus.Pending;
return true;
}
@ -273,10 +282,9 @@ contract Replica is Initializable, Common, QueueManager {
_setFailed();
}
/// @notice Sets `previous` to `current` root before updating `current`
function _beforeConfirm() internal {
previous = current;
}
/// @notice Hook for potential future use
// solhint-disable-next-line no-empty-blocks
function _beforeConfirm() internal {}
/// @notice Hook for potential future use
// solhint-disable-next-line no-empty-blocks

@ -29,6 +29,7 @@ contract TestReplica is Replica {
function setCurrentRoot(bytes32 _newRoot) external {
current = _newRoot;
confirmAt[_newRoot] = 1;
}
function timestamp() external view returns (uint256) {

@ -138,10 +138,10 @@ describe('Replica', async () => {
expect(confirmAt).to.equal(beforeTimestamp.add(optimisticSeconds));
});
it('Returns empty update values when queue is empty', async () => {
it('Returns the current value when the queue is empty', async () => {
const [pending, confirmAt] = await replica.nextPending();
expect(pending).to.equal(ethers.utils.formatBytes32String(0));
expect(confirmAt).to.equal(0);
expect(pending).to.equal(await replica.current());
expect(confirmAt).to.equal(1);
});
it('Rejects update with invalid signature', async () => {
@ -238,7 +238,7 @@ describe('Replica', async () => {
const length = await replica.queueLength();
expect(length).to.equal(0);
await expect(replica.confirm()).to.be.revertedWith('no pending');
await expect(replica.confirm()).to.be.revertedWith('!pending');
});
it('Rejects an early confirmation attempt', async () => {
@ -251,7 +251,7 @@ describe('Replica', async () => {
await testUtils.increaseTimestampBy(provider, optimisticSeconds - 2);
expect(await replica.canConfirm()).to.be.false;
await expect(replica.confirm()).to.be.revertedWith('not time');
await expect(replica.confirm()).to.be.revertedWith('!time');
});
it('Proves a valid message', async () => {

@ -87,8 +87,8 @@ describe('SimpleCrossChainMessage', async () => {
expect(length).to.equal(0);
const [pending, confirmAt] = await replica.nextPending();
expect(pending).to.equal(ethers.utils.formatBytes32String(0));
expect(confirmAt).to.equal(0);
expect(pending).to.equal(await replica.current());
expect(confirmAt).to.equal(1);
}
}
}

@ -35,7 +35,6 @@ interface ReplicaInterface extends ethers.utils.Interface {
"nextPending()": FunctionFragment;
"nextToProcess()": FunctionFragment;
"optimisticSeconds()": FunctionFragment;
"previous()": FunctionFragment;
"process(bytes)": FunctionFragment;
"prove(bytes32,bytes32[32],uint256)": FunctionFragment;
"proveAndProcess(bytes,bytes32[32],uint256)": FunctionFragment;
@ -95,7 +94,6 @@ interface ReplicaInterface extends ethers.utils.Interface {
functionFragment: "optimisticSeconds",
values?: undefined
): string;
encodeFunctionData(functionFragment: "previous", values?: undefined): string;
encodeFunctionData(functionFragment: "process", values: [BytesLike]): string;
encodeFunctionData(
functionFragment: "prove",
@ -237,7 +235,6 @@ interface ReplicaInterface extends ethers.utils.Interface {
functionFragment: "optimisticSeconds",
data: BytesLike
): Result;
decodeFunctionResult(functionFragment: "previous", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "process", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "prove", data: BytesLike): Result;
decodeFunctionResult(
@ -363,8 +360,6 @@ export class Replica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<[BigNumber]>;
previous(overrides?: CallOverrides): Promise<[string]>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }
@ -518,8 +513,6 @@ export class Replica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<BigNumber>;
previous(overrides?: CallOverrides): Promise<string>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }
@ -670,8 +663,6 @@ export class Replica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<BigNumber>;
previous(overrides?: CallOverrides): Promise<string>;
process(_message: BytesLike, overrides?: CallOverrides): Promise<boolean>;
prove(
@ -855,8 +846,6 @@ export class Replica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<BigNumber>;
previous(overrides?: CallOverrides): Promise<BigNumber>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }
@ -1015,8 +1004,6 @@ export class Replica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<PopulatedTransaction>;
previous(overrides?: CallOverrides): Promise<PopulatedTransaction>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }

@ -35,7 +35,6 @@ interface TestReplicaInterface extends ethers.utils.Interface {
"nextPending()": FunctionFragment;
"nextToProcess()": FunctionFragment;
"optimisticSeconds()": FunctionFragment;
"previous()": FunctionFragment;
"process(bytes)": FunctionFragment;
"prove(bytes32,bytes32[32],uint256)": FunctionFragment;
"proveAndProcess(bytes,bytes32[32],uint256)": FunctionFragment;
@ -104,7 +103,6 @@ interface TestReplicaInterface extends ethers.utils.Interface {
functionFragment: "optimisticSeconds",
values?: undefined
): string;
encodeFunctionData(functionFragment: "previous", values?: undefined): string;
encodeFunctionData(functionFragment: "process", values: [BytesLike]): string;
encodeFunctionData(
functionFragment: "prove",
@ -310,7 +308,6 @@ interface TestReplicaInterface extends ethers.utils.Interface {
functionFragment: "optimisticSeconds",
data: BytesLike
): Result;
decodeFunctionResult(functionFragment: "previous", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "process", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "prove", data: BytesLike): Result;
decodeFunctionResult(
@ -463,8 +460,6 @@ export class TestReplica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<[BigNumber]>;
previous(overrides?: CallOverrides): Promise<[string]>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }
@ -691,8 +686,6 @@ export class TestReplica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<BigNumber>;
previous(overrides?: CallOverrides): Promise<string>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }
@ -916,8 +909,6 @@ export class TestReplica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<BigNumber>;
previous(overrides?: CallOverrides): Promise<string>;
process(_message: BytesLike, overrides?: CallOverrides): Promise<boolean>;
prove(
@ -1169,8 +1160,6 @@ export class TestReplica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<BigNumber>;
previous(overrides?: CallOverrides): Promise<BigNumber>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }
@ -1402,8 +1391,6 @@ export class TestReplica extends BaseContract {
optimisticSeconds(overrides?: CallOverrides): Promise<PopulatedTransaction>;
previous(overrides?: CallOverrides): Promise<PopulatedTransaction>;
process(
_message: BytesLike,
overrides?: Overrides & { from?: string | Promise<string> }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -23,7 +23,7 @@ const _abi = [
];
const _bytecode =
"0x60cd610025600b82828239805160001a60731461001857fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b603e6073565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000009092168252519081900360200190f35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000008156fea2646970667358221220b07daa2cfa732a0712e14f333f7fb26a0736db4a4fce155c515a5dd1fc062de564736f6c63430007060033";
"0x60cd610025600b82828239805160001a60731461001857fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b603e6073565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000009092168252519081900360200190f35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000008156fea2646970667358221220a623dd463064745d0b95728d000c3710b30fc8eaa3436afe93e3e0b67ac098ea64736f6c63430007060033";
export class TypedMemView__factory extends ContractFactory {
constructor(signer?: Signer) {

@ -147,7 +147,7 @@ const _abi = [
];
const _bytecode =
"0x608060405260405161091d38038061091d8339818101604052602081101561002657600080fd5b505160006100326100a1565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180546001600160a01b0319166001600160a01b03929092169190911790556100a5565b3390565b610869806100b46000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80638da5cb5b1161005b5780638da5cb5b146100f25780639d54f41914610123578063df034cd014610156578063f2fde38b1461015e5761007d565b80635b3c2cbf146100825780636ef0f37f146100b7578063715018a6146100ea575b600080fd5b6100b56004803603602081101561009857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610191565b005b6100b5600480360360208110156100cd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661021a565b6100b56103af565b6100fa6104c6565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100b56004803603602081101561013957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166104e2565b6100fa610646565b6100b56004803603602081101561017457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610662565b60025473ffffffffffffffffffffffffffffffffffffffff16331461021757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f21686f6d65000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b50565b610222610803565b73ffffffffffffffffffffffffffffffffffffffff166102406104c6565b73ffffffffffffffffffffffffffffffffffffffff16146102c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6102cb81610807565b61033657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f21636f6e747261637420686f6d65000000000000000000000000000000000000604482015290519081900360640190fd5b6002805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517fa6c230e5615262e310dcb42eaf014e813e5d8580abf5b00d2186ca8e9833de219181900360200190a150565b6103b7610803565b73ffffffffffffffffffffffffffffffffffffffff166103d56104c6565b73ffffffffffffffffffffffffffffffffffffffff161461045757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b6104ea610803565b73ffffffffffffffffffffffffffffffffffffffff166105086104c6565b73ffffffffffffffffffffffffffffffffffffffff161461058a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604080517f9d54f419000000000000000000000000000000000000000000000000000000008152600481019390935251921691639d54f4199160248082019260009290919082900301818387803b15801561062b57600080fd5b505af115801561063f573d6000803e3d6000fd5b5050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1690565b61066a610803565b73ffffffffffffffffffffffffffffffffffffffff166106886104c6565b73ffffffffffffffffffffffffffffffffffffffff161461070a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061080e6026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b3b15159056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a26469706673582212207d494e921d13c83f29d903d92591dcdfbb8e79583c18294155f886cb6936392564736f6c63430007060033";
"0x608060405260405161091d38038061091d8339818101604052602081101561002657600080fd5b505160006100326100a1565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180546001600160a01b0319166001600160a01b03929092169190911790556100a5565b3390565b610869806100b46000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80638da5cb5b1161005b5780638da5cb5b146100f25780639d54f41914610123578063df034cd014610156578063f2fde38b1461015e5761007d565b80635b3c2cbf146100825780636ef0f37f146100b7578063715018a6146100ea575b600080fd5b6100b56004803603602081101561009857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610191565b005b6100b5600480360360208110156100cd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661021a565b6100b56103af565b6100fa6104c6565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100b56004803603602081101561013957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166104e2565b6100fa610646565b6100b56004803603602081101561017457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610662565b60025473ffffffffffffffffffffffffffffffffffffffff16331461021757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f21686f6d65000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b50565b610222610803565b73ffffffffffffffffffffffffffffffffffffffff166102406104c6565b73ffffffffffffffffffffffffffffffffffffffff16146102c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6102cb81610807565b61033657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f21636f6e747261637420686f6d65000000000000000000000000000000000000604482015290519081900360640190fd5b6002805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517fa6c230e5615262e310dcb42eaf014e813e5d8580abf5b00d2186ca8e9833de219181900360200190a150565b6103b7610803565b73ffffffffffffffffffffffffffffffffffffffff166103d56104c6565b73ffffffffffffffffffffffffffffffffffffffff161461045757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b6104ea610803565b73ffffffffffffffffffffffffffffffffffffffff166105086104c6565b73ffffffffffffffffffffffffffffffffffffffff161461058a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604080517f9d54f419000000000000000000000000000000000000000000000000000000008152600481019390935251921691639d54f4199160248082019260009290919082900301818387803b15801561062b57600080fd5b505af115801561063f573d6000803e3d6000fd5b5050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1690565b61066a610803565b73ffffffffffffffffffffffffffffffffffffffff166106886104c6565b73ffffffffffffffffffffffffffffffffffffffff161461070a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061080e6026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b3b15159056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a26469706673582212205034ee41aaa8631037793728d4106a61e02443aab3780223e2875fb85813c6f664736f6c63430007060033";
export class UpdaterManager__factory extends ContractFactory {
constructor(signer?: Signer) {

@ -44,7 +44,7 @@ const _abi = [
];
const _bytecode =
"0x60a060405260405161058b38038061058b8339818101604052604081101561002657600080fd5b81516020830180516040519294929383019291908464010000000082111561004d57600080fd5b90830190602082018581111561006257600080fd5b825164010000000081118282018810171561007c57600080fd5b82525081516020918201929091019080838360005b838110156100a9578181015183820152602001610091565b50505050905090810190601f1680156100d65780820380516001836020036101000a031916815260200191505b506040525050506100f0826101d060201b6100291760201c565b610134576040805162461bcd60e51b815260206004820152601060248201526f18995858dbdb880858dbdb9d1c9858dd60821b604482015290519081900360640190fd5b6001600160601b0319606083901b166080526000610151836101d6565b9050610166816101d060201b6100291760201c565b6101b7576040805162461bcd60e51b815260206004820152601f60248201527f626561636f6e20696d706c656d656e746174696f6e2021636f6e747261637400604482015290519081900360640190fd5b8151156101c8576101c881836102d6565b50505061038f565b3b151590565b604051600090819081906001600160a01b0385169082818181855afa9150503d8060008114610221576040519150601f19603f3d011682016040523d82523d6000602084013e610226565b606091505b50915091508181906102b65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561027b578181015183820152602001610263565b50505050905090810190601f1680156102a85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156102cc57600080fd5b5051949350505050565b6000826001600160a01b0316826040518082805190602001908083835b602083106103125780518252601f1990920191602091820191016102f3565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610372576040519150601f19603f3d011682016040523d82523d6000602084013e610377565b606091505b505090508061038a573d6000803e3d6000fd5b505050565b60805160601c6101e06103ab60003980603652506101e06000f3fe60806040523661001357610011610017565b005b6100115b61002761002261002f565b61005f565b565b3b151590565b600061005a7f0000000000000000000000000000000000000000000000000000000000000000610083565b905090565b3660008037600080366000845af43d6000803e80801561007e573d6000f35b3d6000fd5b6040516000908190819073ffffffffffffffffffffffffffffffffffffffff85169082818181855afa9150503d80600081146100db576040519150601f19603f3d011682016040523d82523d6000602084013e6100e0565b606091505b509150915081819061018a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561014f578181015183820152602001610137565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156101a057600080fd5b505194935050505056fea26469706673582212200ccc213e78666f21a7da451ada9602a16ad43ec64773b1306248299b199fa4b264736f6c63430007060033";
"0x60a060405260405161058b38038061058b8339818101604052604081101561002657600080fd5b81516020830180516040519294929383019291908464010000000082111561004d57600080fd5b90830190602082018581111561006257600080fd5b825164010000000081118282018810171561007c57600080fd5b82525081516020918201929091019080838360005b838110156100a9578181015183820152602001610091565b50505050905090810190601f1680156100d65780820380516001836020036101000a031916815260200191505b506040525050506100f0826101d060201b6100291760201c565b610134576040805162461bcd60e51b815260206004820152601060248201526f18995858dbdb880858dbdb9d1c9858dd60821b604482015290519081900360640190fd5b6001600160601b0319606083901b166080526000610151836101d6565b9050610166816101d060201b6100291760201c565b6101b7576040805162461bcd60e51b815260206004820152601f60248201527f626561636f6e20696d706c656d656e746174696f6e2021636f6e747261637400604482015290519081900360640190fd5b8151156101c8576101c881836102d6565b50505061038f565b3b151590565b604051600090819081906001600160a01b0385169082818181855afa9150503d8060008114610221576040519150601f19603f3d011682016040523d82523d6000602084013e610226565b606091505b50915091508181906102b65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561027b578181015183820152602001610263565b50505050905090810190601f1680156102a85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156102cc57600080fd5b5051949350505050565b6000826001600160a01b0316826040518082805190602001908083835b602083106103125780518252601f1990920191602091820191016102f3565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610372576040519150601f19603f3d011682016040523d82523d6000602084013e610377565b606091505b505090508061038a573d6000803e3d6000fd5b505050565b60805160601c6101e06103ab60003980603652506101e06000f3fe60806040523661001357610011610017565b005b6100115b61002761002261002f565b61005f565b565b3b151590565b600061005a7f0000000000000000000000000000000000000000000000000000000000000000610083565b905090565b3660008037600080366000845af43d6000803e80801561007e573d6000f35b3d6000fd5b6040516000908190819073ffffffffffffffffffffffffffffffffffffffff85169082818181855afa9150503d80600081146100db576040519150601f19603f3d011682016040523d82523d6000602084013e6100e0565b606091505b509150915081819061018a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561014f578181015183820152602001610137565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508080602001905160208110156101a057600080fd5b505194935050505056fea26469706673582212206e09ff7f9608a23721cfbbaf58504d076cc9a541fbbe30119427adeac8008dd564736f6c63430007060033";
export class UpgradeBeaconProxy__factory extends ContractFactory {
constructor(signer?: Signer) {

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save