You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.5 KiB
153 lines
4.5 KiB
3 years ago
|
import { ethers } from 'hardhat';
|
||
3 years ago
|
import { expect } from 'chai';
|
||
3 years ago
|
import { types, utils } from '@abacus-network/utils';
|
||
|
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
|
||
3 years ago
|
|
||
3 years ago
|
import { Validator } from './lib/core';
|
||
3 years ago
|
|
||
|
import {
|
||
3 years ago
|
Outbox__factory,
|
||
|
Outbox,
|
||
3 years ago
|
ValidatorManager__factory,
|
||
|
ValidatorManager,
|
||
3 years ago
|
} from '../types';
|
||
3 years ago
|
|
||
3 years ago
|
const outboxDomainHashCases = require('../../../vectors/outboxDomainHash.json');
|
||
3 years ago
|
const localDomain = 1000;
|
||
|
|
||
|
describe('ValidatorManager', async () => {
|
||
3 years ago
|
let signer: SignerWithAddress,
|
||
|
fakeSigner: SignerWithAddress,
|
||
3 years ago
|
validatorManager: ValidatorManager,
|
||
|
validator: Validator,
|
||
|
fakeValidator: Validator;
|
||
|
|
||
|
before(async () => {
|
||
|
[signer, fakeSigner] = await ethers.getSigners();
|
||
|
validator = await Validator.fromSigner(signer, localDomain);
|
||
|
fakeValidator = await Validator.fromSigner(fakeSigner, localDomain);
|
||
|
});
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
const validatorManagerFactory = new ValidatorManager__factory(signer);
|
||
|
validatorManager = await validatorManagerFactory.deploy();
|
||
3 years ago
|
await validatorManager.enrollValidator(localDomain, validator.address);
|
||
3 years ago
|
});
|
||
|
|
||
|
it('Accepts validator signature', async () => {
|
||
|
const root = ethers.utils.formatBytes32String('root');
|
||
|
const index = 1;
|
||
|
|
||
|
const { signature } = await validator.signCheckpoint(root, index);
|
||
|
const isValid = await validatorManager.isValidatorSignature(
|
||
|
localDomain,
|
||
|
root,
|
||
|
index,
|
||
|
signature,
|
||
|
);
|
||
|
expect(isValid).to.be.true;
|
||
|
});
|
||
|
|
||
|
it('Rejects non-validator signature', async () => {
|
||
|
const root = ethers.utils.formatBytes32String('root');
|
||
|
const index = 1;
|
||
|
|
||
|
const { signature } = await fakeValidator.signCheckpoint(root, index);
|
||
|
const isValid = await validatorManager.isValidatorSignature(
|
||
|
localDomain,
|
||
|
root,
|
||
|
index,
|
||
|
signature,
|
||
|
);
|
||
|
expect(isValid).to.be.false;
|
||
|
});
|
||
|
|
||
|
it('Calculated domain hash matches Rust-produced domain hash', async () => {
|
||
|
// Compare Rust output in json file to solidity output (json file matches
|
||
|
// hash for local domain of 1000)
|
||
3 years ago
|
for (let testCase of outboxDomainHashCases) {
|
||
3 years ago
|
const { expectedDomainHash } = testCase;
|
||
3 years ago
|
const domainHash = await validatorManager.domainHash(
|
||
|
testCase.outboxDomain,
|
||
|
);
|
||
3 years ago
|
expect(domainHash).to.equal(expectedDomainHash);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
describe('improper checkpoints', async () => {
|
||
3 years ago
|
let outbox: Outbox;
|
||
3 years ago
|
beforeEach(async () => {
|
||
3 years ago
|
const outboxFactory = new Outbox__factory(signer);
|
||
|
outbox = await outboxFactory.deploy(localDomain);
|
||
|
await outbox.initialize(validatorManager.address);
|
||
3 years ago
|
});
|
||
|
|
||
|
it('Accepts improper checkpoint from validator', async () => {
|
||
|
const root = ethers.utils.formatBytes32String('root');
|
||
|
const index = 1;
|
||
|
|
||
|
const { signature } = await validator.signCheckpoint(root, index);
|
||
|
// Send message with signer address as msg.sender
|
||
|
await expect(
|
||
|
validatorManager.improperCheckpoint(
|
||
3 years ago
|
outbox.address,
|
||
3 years ago
|
root,
|
||
|
index,
|
||
|
signature,
|
||
|
),
|
||
|
)
|
||
|
.to.emit(validatorManager, 'ImproperCheckpoint')
|
||
|
.withArgs(
|
||
3 years ago
|
outbox.address,
|
||
3 years ago
|
localDomain,
|
||
|
validator.address,
|
||
|
root,
|
||
|
index,
|
||
|
signature,
|
||
|
);
|
||
3 years ago
|
expect(await outbox.state()).to.equal(types.AbacusState.FAILED);
|
||
3 years ago
|
});
|
||
|
|
||
|
it('Rejects improper checkpoint from non-validator', async () => {
|
||
|
const root = ethers.utils.formatBytes32String('root');
|
||
|
const index = 1;
|
||
|
|
||
|
const { signature } = await fakeValidator.signCheckpoint(root, index);
|
||
|
// Send message with signer address as msg.sender
|
||
|
await expect(
|
||
|
validatorManager.improperCheckpoint(
|
||
3 years ago
|
outbox.address,
|
||
3 years ago
|
root,
|
||
|
index,
|
||
|
signature,
|
||
|
),
|
||
|
).to.be.revertedWith('!validator sig');
|
||
|
});
|
||
|
|
||
|
it('Rejects proper checkpoint from validator', async () => {
|
||
|
const message = `0x${Buffer.alloc(10).toString('hex')}`;
|
||
3 years ago
|
await outbox.dispatch(
|
||
3 years ago
|
localDomain,
|
||
3 years ago
|
utils.addressToBytes32(signer.address),
|
||
3 years ago
|
message,
|
||
|
);
|
||
3 years ago
|
await outbox.checkpoint();
|
||
|
const [root, index] = await outbox.latestCheckpoint();
|
||
3 years ago
|
|
||
|
const { signature } = await validator.signCheckpoint(
|
||
|
root,
|
||
|
index.toNumber(),
|
||
|
);
|
||
|
// Send message with signer address as msg.sender
|
||
|
await expect(
|
||
|
validatorManager.improperCheckpoint(
|
||
3 years ago
|
outbox.address,
|
||
3 years ago
|
root,
|
||
|
index,
|
||
|
signature,
|
||
|
),
|
||
|
).to.be.revertedWith('!improper');
|
||
|
});
|
||
|
});
|
||
|
});
|