Skip to content

Commit

Permalink
fix: fix prepareProvier ballot and proposal bug and add sandbox test …
Browse files Browse the repository at this point in the history
…back
  • Loading branch information
hui-an-yang committed Dec 12, 2024
1 parent 28644cd commit d3ae08f
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 182 deletions.
29 changes: 27 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
matrix:
node:
- 'lts/iron'
- '22'
- lts/hydrogen
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/iron
node-version: lts/hydrogen
- run: npm ci
- run: npm run build
- if: ${{ !github.event.pull_request.head.repo.fork }}
Expand All @@ -62,3 +62,28 @@ jobs:
env:
# Ternary operator workaround
TEZOS_RPC_${{ matrix.testnet_uppercase }}: ${{ github.event.pull_request.head.repo.fork && format('https://{0}.ecadinfra.com', matrix.testnet) || null }}

integration-tests-tezbox:
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
include:
- testnet: parisnet
testnet_uppercase: PARISNET
flextesa_docker_image:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/hydrogen
- name: Provision Tezbox ${{ matrix.testnet }} container
run: npm -w integration-tests run sandbox:${{ matrix.testnet }}
- run: npm ci
- run: npm run build
- run: npm -w integration-tests run test __tests__/tezbox/integration-tests/__tests__/tezbox/sandbox-proposal-and-ballot-operation.spec.ts
env:
TEZOS_RPC_${{ matrix.testnet_uppercase }}: http://localhost:8732
- run: npm -w integration-tests run test __tests__/tezbox/sandbox-drain-delegate-operation.spec
env:
TEZOS_RPC_${{ matrix.testnet_uppercase }}: http://localhost:8732
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@
"tcli",
"testbox",
"testchain",
"tezbox",
"tezboxnet",
"tezbridge",
"tezos",
"Thanos",
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { CONFIGS, sleep, isSandbox } from "../../config";
import { TezosToolkit } from "@taquito/taquito";
import { InMemorySigner } from '@taquito/signer';
import { OperationContentsAndResultDrainDelegate } from '@taquito/rpc';

CONFIGS().forEach(({ rpc, protocol, createAddress }) => {
const tezboxnet = isSandbox({ rpc }) ? test : test.skip;
const alice = new TezosToolkit(rpc);
let alicePkh: string;
let delegate: TezosToolkit;
let delegatePkh: string;
let destination: TezosToolkit;
let destinationPkh: string;

describe(`Test Drain Delegate in ${protocol.substring(0, 8)}`, () => {
beforeAll(async () => {
// tezbox provision Alice account with balance, ref https://github.com/tez-capital/tezbox/blob/main/configuration/accounts.hjson
alice.setSignerProvider(new InMemorySigner('edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq'));
alicePkh = await alice.signer.publicKeyHash();
delegate = await createAddress();
delegatePkh = await delegate.signer.publicKeyHash();;
destination = await createAddress();
destinationPkh = await destination.signer.publicKeyHash();
// fund the delegate
const transferOp = await alice.contract.transfer({ to: delegatePkh, amount: 5 });
await transferOp.confirmation();
// register as delegate
const registerOp = await delegate.contract.registerDelegate({});
await registerOp.confirmation();
// update consensus key to destination
const updateOp = await delegate.contract.updateConsensusKey({ pk: await destination.signer.publicKey() });
await updateOp.confirmation();
})

tezboxnet('Should be able to prepare drainDelegate operations accepted by preapply endpoint', async () => {
// wait for more than preserved_cycles + 1 for consensus_key to be active to perform drainDelegate operation
const constants = await alice.rpc.getConstants();
await sleep(((constants.consensus_rights_delay + 2) * (constants.blocks_per_cycle) * (constants.minimal_block_delay!.toNumber())) * 1000);

const drainPrepared = await destination.prepare.drainDelegate({
consensus_key: destinationPkh,
delegate: delegatePkh,
destination: destinationPkh,
})
const drainPreapplied = await destination.rpc.preapplyOperations(await destination.prepare.toPreapply(drainPrepared));

expect(drainPreapplied).toBeInstanceOf(Array)
expect(drainPreapplied[0].contents).toBeInstanceOf(Array)
expect(drainPreapplied[0].contents[0].kind).toEqual('drain_delegate')
expect((drainPreapplied[0].contents[0] as OperationContentsAndResultDrainDelegate).consensus_key).toEqual(destinationPkh)
expect((drainPreapplied[0].contents[0] as OperationContentsAndResultDrainDelegate).delegate).toEqual(delegatePkh)
expect((drainPreapplied[0].contents[0] as OperationContentsAndResultDrainDelegate).destination).toEqual(destinationPkh)
expect((drainPreapplied[0].contents[0] as OperationContentsAndResultDrainDelegate).metadata).toBeDefined()
});
tezboxnet('Should be able to inject drain_delegate operation', async () => {
// get the delegate and destination balance before drainDelegate operation
let delegateBeforeBalance = (await delegate.rpc.getBalance(delegatePkh)).toNumber()
let destinationBeforeBalance = (await destination.rpc.getBalance(destinationPkh)).toNumber();

const drainOp = await destination.contract.drainDelegate({
consensus_key: destinationPkh,
delegate: delegatePkh,
destination: destinationPkh,
});
await drainOp.confirmation();

// get the delegate and destination balance after drainDelegate operation
let delegateAfterBalance = (await destination.rpc.getBalance(delegatePkh)).toNumber()
let destinationAfterBalance = (await destination.rpc.getBalance(destinationPkh)).toNumber()

expect(drainOp.includedInBlock).toBeDefined()
expect(drainOp.status).toBeDefined()
expect(drainOp.hash).toBeDefined()
expect(drainOp.operationResults).toBeDefined()
expect(drainOp.consensusKey).toEqual(destinationPkh)
expect(drainOp.delegate).toEqual(delegatePkh)
expect(drainOp.destination).toEqual(destinationPkh)

expect(delegateBeforeBalance).toBeGreaterThan(0);
expect(delegateAfterBalance).toBe(0);
expect(destinationBeforeBalance).toBe(0);
expect(destinationAfterBalance).toBeGreaterThan(0);
});
});
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { CONFIGS, isSandbox, sleep } from '../../config';
import { TezosToolkit } from '@taquito/taquito';
import { InMemorySigner } from '@taquito/signer';
import { OperationContentsAndResultBallot, OperationContentsAndResultProposals, VotingPeriodBlockResult, OperationContentsProposals } from '@taquito/rpc';

CONFIGS().forEach(async ({ rpc, protocol }) => {
const tezboxnet = isSandbox({ rpc }) ? test : test.skip;
const baker1 = new TezosToolkit(rpc);
const baker2 = new TezosToolkit(rpc);
const baker3 = new TezosToolkit(rpc);
const proposal = 'ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK';
const ballot = 'yay';
let blockTime: number
let currentPeriod: VotingPeriodBlockResult;

describe(`Test Proposal and Ballot operation in ${protocol.substring(0, 8)} with tezbox`, () => {
beforeAll(async () => {
// tezbox provision of 3 bakers, ref https://github.com/tez-capital/tezbox/blob/main/configuration/bakers.hjson
baker1.setSignerProvider(new InMemorySigner('edsk4ArLQgBTLWG5FJmnGnT689VKoqhXwmDPBuGx3z4cvwU9MmrPZZ'));
baker2.setSignerProvider(new InMemorySigner('edsk39qAm1fiMjgmPkw1EgQYkMzkJezLNewd7PLNHTkr6w9XA2zdfo'));
baker3.setSignerProvider(new InMemorySigner('edsk2uqQB9AY4FvioK2YMdfmyMrer5R8mGFyuaLLFfSRo8EoyNdht3'));

// get block time from protocol constants
const constants = await baker1.rpc.getConstants();
blockTime = constants.minimal_block_delay!.toNumber();
});

tezboxnet('Should be able to prepare proposal accepted by preapply endpoint', async () => {
// check if it's in proposal period to start proposal test
currentPeriod = await baker1.rpc.getCurrentPeriod();
while (currentPeriod.voting_period.kind !== 'proposal') {
await sleep(((currentPeriod.remaining + 1) * blockTime) * 1000)
currentPeriod = await baker1.rpc.getCurrentPeriod()
}

const proposalPrepared = await baker1.prepare.proposals({ proposals: [proposal] });
const proposalPreapplied = await baker1.rpc.preapplyOperations(await baker1.prepare.toPreapply(proposalPrepared));

expect(proposalPreapplied).toBeInstanceOf(Array);
expect(proposalPreapplied[0].contents).toBeInstanceOf(Array);
expect(proposalPreapplied[0].contents[0].kind).toBe('proposals');
expect((proposalPreapplied[0].contents[0] as OperationContentsAndResultProposals).source).toBe(await baker1.signer.publicKeyHash());
expect((proposalPreapplied[0].contents[0] as OperationContentsAndResultProposals).period).toBe((proposalPrepared.opOb.contents[0] as OperationContentsProposals).period);
expect((proposalPreapplied[0].contents[0] as OperationContentsAndResultProposals).proposals).toBeInstanceOf(Array);
expect((proposalPreapplied[0].contents[0] as OperationContentsAndResultProposals).proposals[0]).toEqual(proposal);
});

tezboxnet('Should be able to inject proposal operation in proposal period', async () => {
const proposalsOp = await baker1.contract.proposals({
proposals: [proposal]
});
await proposalsOp.confirmation();

expect(proposalsOp.includedInBlock).toBeDefined();
expect(proposalsOp.status).toBeDefined();
expect(proposalsOp.hash).toBeDefined();
expect(proposalsOp.operationResults).toBeDefined();
expect(proposalsOp.proposals).toEqual([proposal]);
expect(proposalsOp.period).toBeDefined();

// injecting 2 more proposals from baker baker2 and baker3 to reach above quorum
const baker2Op = await baker2.contract.proposals({ proposals: [proposal] });
await baker2Op.confirmation();
expect(baker2Op.includedInBlock).toBeDefined();
const baker3Op = await baker3.contract.proposals({ proposals: [proposal] });
await baker3Op.confirmation();
expect(baker3Op.includedInBlock).toBeDefined();
});

tezboxnet('Should be able to prepare ballot operations accepted by preapply endpoint', async () => {
// if it's still proposal period make the test sleep to get into exploration period to inject ballot operation
while (currentPeriod.voting_period.kind !== 'exploration') {
await sleep(((currentPeriod.remaining + 1) * blockTime) * 1000)
currentPeriod = await baker1.rpc.getCurrentPeriod()
}

const ballotPrepared = await baker1.prepare.ballot({ proposal, ballot });
const preappliedBallot = await baker1.rpc.preapplyOperations(await baker1.prepare.toPreapply(ballotPrepared));

expect(preappliedBallot).toBeInstanceOf(Array);
expect(preappliedBallot[0].contents).toBeInstanceOf(Array);
expect(preappliedBallot[0].contents[0].kind).toEqual('ballot');
expect((preappliedBallot[0].contents[0] as OperationContentsAndResultBallot).source).toEqual(await baker1.signer.publicKeyHash());
expect((preappliedBallot[0].contents[0] as OperationContentsAndResultBallot).proposal).toEqual(proposal);
expect((preappliedBallot[0].contents[0] as OperationContentsAndResultBallot).ballot).toEqual(ballot);
});

tezboxnet('Should be able to inject ballot operation in exploration period', async () => {
const explorationBallotOp = await baker1.contract.ballot({
proposal,
ballot
});
await explorationBallotOp.confirmation();

expect(explorationBallotOp.includedInBlock).toBeDefined();
expect(explorationBallotOp.status).toBeDefined();
expect(explorationBallotOp.hash).toBeDefined();
expect(explorationBallotOp.operationResults).toBeDefined();
expect(explorationBallotOp.proposal).toBe(proposal);
expect(explorationBallotOp.period).toBeDefined();
expect(explorationBallotOp.ballot).toBe(ballot);
});
});
});
Loading

0 comments on commit d3ae08f

Please sign in to comment.