pull/334/head
Trevor Porter 3 years ago
parent a792402b1f
commit bdd1d1f94f
  1. 1
      solidity/core/contracts/Inbox.sol
  2. 3
      solidity/core/contracts/Outbox.sol
  3. 4
      solidity/core/contracts/validator-manager/InboxMultisigValidatorManager.sol
  4. 4
      solidity/core/contracts/validator-manager/OutboxMultisigValidatorManager.sol
  5. 3
      solidity/core/interfaces/IInbox.sol
  6. 7
      solidity/core/interfaces/IOutbox.sol
  7. 0
      solidity/core/test/validator-manager/inboxMultisigValidatorManager.test.ts
  8. 32
      solidity/core/test/validator-manager/multisigValidatorManager.test.ts
  9. 30
      solidity/core/test/validator-manager/utils.ts
  10. 22
      typescript/hardhat/src/TestAbacusDeploy.ts

@ -90,6 +90,7 @@ contract Inbox is IInbox, Version0, Common {
*/ */
function checkpoint(bytes32 _root, uint256 _index) function checkpoint(bytes32 _root, uint256 _index)
external external
override
onlyValidatorManager onlyValidatorManager
{ {
// Ensure that the checkpoint is more recent than the latest we've seen. // Ensure that the checkpoint is more recent than the latest we've seen.

@ -161,7 +161,7 @@ contract Outbox is IOutbox, Version0, MerkleTreeManager, Common {
* @notice Set contract state to FAILED. * @notice Set contract state to FAILED.
* @dev Called by the ValidatorManager when fraud is proven. * @dev Called by the ValidatorManager when fraud is proven.
*/ */
function fail() external onlyValidatorManager { function fail() external override onlyValidatorManager {
// set contract to FAILED // set contract to FAILED
state = States.Failed; state = States.Failed;
emit Fail(); emit Fail();
@ -177,6 +177,7 @@ contract Outbox is IOutbox, Version0, MerkleTreeManager, Common {
function isCheckpoint(bytes32 _root, uint256 _index) function isCheckpoint(bytes32 _root, uint256 _index)
external external
view view
override
returns (bool) returns (bool)
{ {
// Checkpoint indices are one-indexed. // Checkpoint indices are one-indexed.

@ -3,8 +3,8 @@ pragma solidity >=0.6.11;
pragma abicoder v2; pragma abicoder v2;
// ============ Internal Imports ============ // ============ Internal Imports ============
import {IInbox} from "../../interfaces/IInbox.sol";
import {MultisigValidatorManager} from "./MultisigValidatorManager.sol"; import {MultisigValidatorManager} from "./MultisigValidatorManager.sol";
import {Inbox} from "../Inbox.sol";
contract InboxMultisigValidatorManager is MultisigValidatorManager { contract InboxMultisigValidatorManager is MultisigValidatorManager {
// ============ Constructor ============ // ============ Constructor ============
@ -35,7 +35,7 @@ contract InboxMultisigValidatorManager is MultisigValidatorManager {
* quorum. Must be sorted in ascending order by signer address. * quorum. Must be sorted in ascending order by signer address.
*/ */
function checkpoint( function checkpoint(
Inbox _inbox, IInbox _inbox,
bytes32 _root, bytes32 _root,
uint256 _index, uint256 _index,
bytes[] calldata _signatures bytes[] calldata _signatures

@ -3,8 +3,8 @@ pragma solidity >=0.6.11;
pragma abicoder v2; pragma abicoder v2;
// ============ Internal Imports ============ // ============ Internal Imports ============
import {IOutbox} from "../../interfaces/IOutbox.sol";
import {MultisigValidatorManager} from "./MultisigValidatorManager.sol"; import {MultisigValidatorManager} from "./MultisigValidatorManager.sol";
import {Outbox} from "../Outbox.sol";
contract OutboxMultisigValidatorManager is MultisigValidatorManager { contract OutboxMultisigValidatorManager is MultisigValidatorManager {
// ============ Events ============ // ============ Events ============
@ -47,7 +47,7 @@ contract OutboxMultisigValidatorManager is MultisigValidatorManager {
// requires that the checkpoint is an improper checkpoint, // requires that the checkpoint is an improper checkpoint,
// and calls IOutbox(_outbox).fail(). (Similar behavior as existing improperCheckpoint) // and calls IOutbox(_outbox).fail(). (Similar behavior as existing improperCheckpoint)
function improperCheckpoint( function improperCheckpoint(
Outbox _outbox, IOutbox _outbox,
bytes32 _root, bytes32 _root,
uint256 _index, uint256 _index,
bytes[] calldata _signatures bytes[] calldata _signatures

@ -6,8 +6,7 @@ import {ICommon} from "./ICommon.sol";
interface IInbox is ICommon { interface IInbox is ICommon {
function checkpoint( function checkpoint(
bytes32 _root, bytes32 _root,
uint256 _index, uint256 _index
bytes calldata _signature
) external; ) external;
function remoteDomain() external returns (uint32); function remoteDomain() external returns (uint32);

@ -11,4 +11,11 @@ interface IOutbox is ICommon {
) external returns (uint256); ) external returns (uint256);
function checkpoint() external; function checkpoint() external;
function isCheckpoint(
bytes32 _root,
uint256 _index
) external returns (bool);
function fail() external;
} }

@ -1,13 +1,13 @@
import { ethers } from 'hardhat'; import { ethers } from 'hardhat';
import { expect } from 'chai'; import { expect } from 'chai';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { types } from '@abacus-network/utils'; import { Validator } from '@abacus-network/utils';
import { import {
TestMultisigValidatorManager, TestMultisigValidatorManager,
TestMultisigValidatorManager__factory, TestMultisigValidatorManager__factory,
} from '../../types'; } from '../../types';
import { Validator } from '../lib/core'; import { getCheckpointSignatures } from './utils';
const OUTBOX_DOMAIN = 1234; const OUTBOX_DOMAIN = 1234;
const OUTBOX_DOMAIN_HASH = ethers.utils.keccak256( const OUTBOX_DOMAIN_HASH = ethers.utils.keccak256(
@ -15,34 +15,6 @@ const OUTBOX_DOMAIN_HASH = ethers.utils.keccak256(
); );
const QUORUM_THRESHOLD = 1; const QUORUM_THRESHOLD = 1;
// Signs a checkpoint with the provided validators and returns
// the signatures sorted by validator addresses in ascending order
async function getCheckpointSignatures(
root: types.HexString,
index: number,
unsortedValidators: Validator[],
): Promise<string[]> {
const validators = unsortedValidators.sort((a, b) => {
const aAddress = a.address.toLowerCase();
const bAddress = b.address.toLowerCase();
if (aAddress < bAddress) {
return -1;
} else if (aAddress > bAddress) {
return 1;
} else {
return 0;
}
});
const signedCheckpoints = await Promise.all(
validators.map((validator) => validator.signCheckpoint(root, index)),
);
return signedCheckpoints.map(
(signedCheckpoint) => signedCheckpoint.signature,
);
}
describe.only('MultisigValidatorManager', async () => { describe.only('MultisigValidatorManager', async () => {
let validatorManager: TestMultisigValidatorManager, let validatorManager: TestMultisigValidatorManager,
signer: SignerWithAddress, signer: SignerWithAddress,

@ -0,0 +1,30 @@
import { types, Validator } from '@abacus-network/utils';
// Signs a checkpoint with the provided validators and returns
// the signatures sorted by validator addresses in ascending order
export async function getCheckpointSignatures(
root: types.HexString,
index: number,
unsortedValidators: Validator[],
): Promise<string[]> {
const validators = unsortedValidators.sort((a, b) => {
// Remove the checksums for accurate comparison
const aAddress = a.address.toLowerCase();
const bAddress = b.address.toLowerCase();
if (aAddress < bAddress) {
return -1;
} else if (aAddress > bAddress) {
return 1;
} else {
return 0;
}
});
const signedCheckpoints = await Promise.all(
validators.map((validator) => validator.signCheckpoint(root, index)),
);
return signedCheckpoints.map(
(signedCheckpoint) => signedCheckpoint.signature,
);
}

@ -1,5 +1,5 @@
import { ethers } from "ethers"; import { ethers } from "ethers";
import { types, Validator } from "@abacus-network/utils"; import { types } from "@abacus-network/utils";
import { import {
Outbox, Outbox,
Outbox__factory, Outbox__factory,
@ -172,21 +172,23 @@ export class TestAbacusDeploy extends TestDeploy<
) { ) {
return; return;
} }
// TODO come back to this
// Update the Outbox and Inboxes to the latest roots. // Update the Outbox and Inboxes to the latest roots.
// This is technically not necessary given that we are not proving against // This is technically not necessary given that we are not proving against
// a root in the TestInbox. // a root in the TestInbox.
const validator = await Validator.fromSigner( // const validator = await Validator.fromSigner(
this.config.signer[domain], // this.config.signer[domain],
domain // domain
); // );
const { signature } = await validator.signCheckpoint( // const { signature } = await validator.signCheckpoint(
root, // root,
index.toNumber() // index.toNumber()
); // );
for (const remote of this.remotes(domain)) { for (const remote of this.remotes(domain)) {
const inbox = this.inbox(remote, domain); const inbox = this.inbox(remote, domain);
await inbox.checkpoint(root, index, signature); await inbox.checkpoint(root, index /*, signature*/);
} }
// Find all messages dispatched on the outbox since the previous checkpoint. // Find all messages dispatched on the outbox since the previous checkpoint.

Loading…
Cancel
Save