Skip to content

Commit

Permalink
refactor: reject V1 transactions after milestone (#2879)
Browse files Browse the repository at this point in the history
  • Loading branch information
spkjp authored and faustbrian committed Aug 21, 2019
1 parent f3ed2f9 commit 5df769b
Show file tree
Hide file tree
Showing 77 changed files with 728 additions and 454 deletions.
2 changes: 1 addition & 1 deletion __tests__/e2e/lib/config/docker/ark-network-start.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
echo "Starting ark --network-start" >> output.log
CORE_DB_HOST=postgres CORE_DB_DATABASE=ark_testnet CORE_DB_USERNAME=ark ARK_LOG_FILE=ark.log CORE_PATH_CONFIG=./packages/core/bin/config/testnet CORE_PATH_DATA=./packages/core/bin/config/testnet ./packages/core/bin/run core:run --networkStart >> output.log 2> errors.log
CORE_DB_HOST=postgres CORE_DB_DATABASE=ark_testnet CORE_DB_USERNAME=ark ARK_LOG_FILE=ark.log CORE_PATH_CONFIG=./packages/core/bin/config/testnet CORE_PATH_DATA=./packages/core/bin/config/testnet ./packages/core/bin/run core:run --networkStart --env=test >> output.log 2> errors.log
echo "Started ark --network-start" >> output.log
2 changes: 1 addition & 1 deletion __tests__/e2e/lib/config/docker/ark.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
echo "Starting ark" >> output.log
CORE_DB_HOST=postgres CORE_DB_DATABASE=ark_testnet CORE_DB_USERNAME=ark ARK_LOG_FILE=ark.log CORE_PATH_CONFIG=./packages/core/bin/config/testnet CORE_PATH_DATA=./packages/core/bin/config/testnet ./packages/core/bin/run core:run >> output.log 2> errors.log &
CORE_DB_HOST=postgres CORE_DB_DATABASE=ark_testnet CORE_DB_USERNAME=ark ARK_LOG_FILE=ark.log CORE_PATH_CONFIG=./packages/core/bin/config/testnet CORE_PATH_DATA=./packages/core/bin/config/testnet ./packages/core/bin/run core:run --env=test >> output.log 2> errors.log &
echo kill -2 $! > killpid.sh
pwd >> output.log
cat killpid.sh >> output.log
Expand Down
15 changes: 14 additions & 1 deletion __tests__/functional/transaction-forging/__support__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import "jest-extended";
import { Container, Database, State } from "@arkecosystem/core-interfaces";
import { Wallets } from "@arkecosystem/core-state";
import { Identities, Managers, Utils } from "@arkecosystem/crypto";
import { Crypto } from "@arkecosystem/crypto";
import delay from "delay";
import cloneDeep from "lodash.clonedeep";
import { secrets } from "../../../utils/config/testnet/delegates.json";
import { setUpContainer } from "../../../utils/helpers/container";

Expand All @@ -12,6 +14,8 @@ jest.setTimeout(1200000);
let app: Container.IContainer;
export const setUp = async (): Promise<void> => {
try {
process.env.CORE_RESET_DATABASE = "1";

app = await setUpContainer({
include: [
"@arkecosystem/core-event-emitter",
Expand Down Expand Up @@ -57,9 +61,18 @@ export const tearDown = async (): Promise<void> => {

export const snoozeForBlock = async (sleep: number = 0, height: number = 1): Promise<void> => {
const blockTime = Managers.configManager.getMilestone(height).blocktime * 1000;
const remainingTimeInSlot = Crypto.Slots.getTimeInMsUntilNextSlot();
const sleepTime = sleep * 1000;

return delay(blockTime + sleepTime);
return delay(blockTime + remainingTimeInSlot + sleepTime);
};

export const injectMilestone = (index: number, milestone: Record<string, any>): void => {
(Managers.configManager as any).milestones.splice(
index,
0,
Object.assign(cloneDeep(Managers.configManager.getMilestone()), milestone),
);
};

export const getLastHeight = (): number => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe("Transaction Forging - Delegate Registration", () => {
.withPassphraseList(passphrases)
.createOne();

await expect(delegateRegistration.id).toBeRejected();
await expect(delegateRegistration).toBeRejected();
await support.snoozeForBlock(1);
await expect(delegateRegistration.id).not.toBeForged();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ describe("Transaction Forging - Delegate Resignation", () => {
.withPassphrasePair({ passphrase, secondPassphrase })
.createOne();

await expect(transactionsResign.id).toBeRejected();
await expect(transactionsResign).toBeRejected();
await support.snoozeForBlock(1);
await expect(transactionsResign.id).not.toBeForged();
});
Expand Down Expand Up @@ -230,7 +230,7 @@ describe("Transaction Forging - Delegate Resignation", () => {
.withPassphrasePair({ passphrase, secondPassphrase })
.createOne();

await expect(transactionsResign2.id).toBeRejected();
await expect(transactionsResign2).toBeRejected();
await support.snoozeForBlock(1);
await expect(transactionsResign2.id).not.toBeForged();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Identities } from "@arkecosystem/crypto";
import { Identities, Managers } from "@arkecosystem/crypto";
import { TransactionFactory } from "../../helpers/transaction-factory";
import { secrets } from "../../utils/config/testnet/delegates.json";
import * as support from "./__support__";
Expand Down Expand Up @@ -74,4 +74,45 @@ describe("Transaction Forging - Multi Signature Registration", () => {
await support.snoozeForBlock(1);
await expect(multiSignature.id).toBeForged();
});

it("should reject before AIP11 milestone and accept after AIP11 milestone", async () => {
const passphrase = secrets[6];
const initialFunds = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase), 100 * 1e8)
.withPassphrase(secrets[0])
.createOne();

await expect(initialFunds).toBeAccepted();
await support.snoozeForBlock(1);
await expect(initialFunds.id).toBeForged();

// Register a multi signature wallet with defaults
const passphrases = [passphrase, secrets[3], secrets[4]];
const participants = [
Identities.PublicKey.fromPassphrase(passphrases[0]),
Identities.PublicKey.fromPassphrase(passphrases[1]),
Identities.PublicKey.fromPassphrase(passphrases[2]),
];

const multiSignature = TransactionFactory.multiSignature(participants, 3)
.withPassphraseList(passphrases)
.withPassphrase(passphrase)
.createOne();

Managers.configManager.getMilestone().aip11 = false;

support.injectMilestone(1, {
height: support.getLastHeight() + 1,
aip11: true,
});

await expect(multiSignature).toBeRejected();
await support.snoozeForBlock(1);
await expect(multiSignature.id).not.toBeForged();

expect(Managers.configManager.getMilestone().aip11).toBeTrue();

await expect(multiSignature).toBeAccepted();
await support.snoozeForBlock(1);
await expect(multiSignature.id).toBeForged();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe("Transaction Forging - Second Signature Registration", () => {
.withPassphraseList(passphrases)
.createOne();

await expect(secondSignature.id).toBeRejected();
await expect(secondSignature).toBeRejected();
await support.snoozeForBlock(1);
await expect(secondSignature.id).not.toBeForged();

Expand Down
46 changes: 36 additions & 10 deletions __tests__/functional/transaction-forging/transfer.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Identities } from "@arkecosystem/crypto";
import { Identities, Managers } from "@arkecosystem/crypto";
import { TransactionFactory } from "../../helpers/transaction-factory";
import { secrets } from "../../utils/config/testnet/delegates.json";
import * as support from "./__support__";
Expand Down Expand Up @@ -124,28 +124,54 @@ describe("Transaction Forging - Transfer", () => {
.withExpiration(support.getLastHeight() + 1)
.createOne();

await expect(transfer.id).toBeRejected();
await expect(transfer2.id).toBeRejected();
await expect(transfer).toBeRejected();
await expect(transfer2).toBeRejected();
await support.snoozeForBlock(1);
await expect(transfer.id).not.toBeForged();
});

it("should broadcast, accept and forge it [Legacy, Without Nonce]", async () => {
const transferWithNonce = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase))
it("should accept V1 before AIP11 milestone and reject after AIP11 milestone", async () => {
const transfer = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase))
.withPassphrase(secrets[0])
.createOne();

await expect(transferWithNonce).toBeAccepted();
await expect(transfer).toBeAccepted();
await support.snoozeForBlock(1);
await expect(transferWithNonce.id).toBeForged();
await expect(transfer.id).toBeForged();

const transferLegacyWithoutNonce = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase))
const transfersLegacyWithoutNonce = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase))
.withVersion(1)
.withPassphrase(secrets[0])
.create(2);

Managers.configManager.getMilestone().aip11 = false;

support.injectMilestone(1, {
height: support.getLastHeight() + 1,
aip11: true,
});

// Still accepts 1 height before milestone
await expect(transfersLegacyWithoutNonce[0]).toBeAccepted();
await support.snoozeForBlock(1);
await expect(transfersLegacyWithoutNonce[0].id).toBeForged();

// Now got activated
expect(Managers.configManager.getMilestone().aip11).toBeTrue();

// Rejects V1
await expect(transfersLegacyWithoutNonce[1]).toBeRejected();
await support.snoozeForBlock(1);
await expect(transfersLegacyWithoutNonce[1].id).not.toBeForged();

// and accepts V2
const transferWithNonce = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase))
.withPassphrase(secrets[1])
.createOne();

await expect(transferLegacyWithoutNonce).toBeAccepted();
expect(transferWithNonce.version).toBe(2);
await expect(transferWithNonce).toBeAccepted();
await support.snoozeForBlock(1);
await expect(transferLegacyWithoutNonce.id).toBeForged();
await expect(transferWithNonce.id).toBeForged();
});
});
17 changes: 17 additions & 0 deletions __tests__/helpers/block-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Delegate } from "@arkecosystem/core-forger";
import { Interfaces, Networks, Utils } from "@arkecosystem/crypto";
import { delegates, genesisBlock } from "../utils/fixtures/unitnet";

export class BlockFactory {
public static createDummy(transactions: Interfaces.ITransactionData[] = []): Interfaces.IBlock {
const delegate = new Delegate(delegates[0].passphrase, Networks.unitnet.network);
return delegate.forge(transactions, {
timestamp: 12345689,
previousBlock: {
id: genesisBlock.id,
height: 1,
},
reward: Utils.BigNumber.ZERO,
});
}
}
1 change: 1 addition & 0 deletions __tests__/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./rest-client";
export * from "./transaction-factory";
export * from "./block-factory";
19 changes: 17 additions & 2 deletions __tests__/helpers/transaction-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ export class TransactionFactory {
this.builder.version(this.version);
}

if (this.builder.data.version > 1 && Managers.configManager.getMilestone().aip11) {
if (this.builder.data.version > 1) {
nonce = nonce.plus(1);
this.builder.nonce(nonce);
}
Expand Down Expand Up @@ -317,15 +317,30 @@ export class TransactionFactory {
}
}

const testnet: boolean = ["unitnet", "testnet"].includes(Managers.configManager.get("network.name"));

if (sign) {
const aip11: boolean = Managers.configManager.getMilestone().aip11;
if (this.builder.data.version === 1 && aip11) {
Managers.configManager.getMilestone().aip11 = false;
} else if (testnet) {
Managers.configManager.getMilestone().aip11 = true;
}

this.builder.sign(this.passphrase);

if (this.secondPassphrase) {
this.builder.secondSign(this.secondPassphrase);
}
}

transactions.push(this.builder[method]());
const transaction = this.builder[method]();

if (testnet) {
Managers.configManager.getMilestone().aip11 = true;
}

transactions.push(transaction);
}

return transactions;
Expand Down
6 changes: 2 additions & 4 deletions __tests__/integration/core-api/handlers/transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import "../../../utils";
import { setUp, tearDown } from "../__support__/setup";
import { utils } from "../utils";

import { Address } from "../../../../packages/crypto/src/identities";
import { Identities } from "@arkecosystem/crypto";
import { TransactionFactory } from "../../../helpers/transaction-factory";
import { genesisBlock } from "../../../utils/config/testnet/genesisBlock";
import { delegates } from "../../../utils/fixtures/testnet/delegates";
Expand Down Expand Up @@ -44,7 +44,7 @@ beforeAll(async () => {
wrongType = 3;
version = 1;
senderPublicKey = genesisTransaction.senderPublicKey;
senderAddress = Address.fromPublicKey(genesisTransaction.senderPublicKey, 23);
senderAddress = Identities.Address.fromPublicKey(genesisTransaction.senderPublicKey, 23);
recipientAddress = genesisTransaction.recipientId;
timestamp = genesisTransaction.timestamp;
timestampFrom = timestamp;
Expand Down Expand Up @@ -539,12 +539,10 @@ describe("API 2.0 - Transactions", () => {
const lastAmountPlusFee = +sender.balance - (txNumber - 1) * amountPlusFee;

const transactions = TransactionFactory.transfer(receivers[0].address, amountPlusFee - transferFee)
.withNetwork("testnet")
.withPassphrase(sender.secret)
.create(txNumber - 1);

const lastTransaction = TransactionFactory.transfer(receivers[0].address, lastAmountPlusFee - transferFee)
.withNetwork("testnet")
.withNonce(transactions[transactions.length - 1].nonce)
.withPassphrase(sender.secret)
.create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import transactionRaw from "./transaction-raw.json";
import transactionTransformed from "./transaction-transformed.json";

Managers.configManager.setFromPreset("testnet");

Managers.configManager.getMilestone().aip11 = false;
const genesisTransaction = Transactions.TransactionFactory.fromData(genesisBlock.transactions[0]);
delete genesisBlock.transactions;

Expand Down
13 changes: 6 additions & 7 deletions __tests__/integration/core-blockchain/blockchain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Blocks, Crypto, Identities, Interfaces, Utils } from "@arkecosystem/cry
import delay from "delay";
import { Blockchain } from "../../../packages/core-blockchain/src/blockchain";
import { TransactionFactory } from "../../helpers/transaction-factory";
import { genesisBlock as GB } from "../../utils/config/testnet/genesisBlock";
import { blocks101to155 } from "../../utils/fixtures/testnet/blocks101to155";
import { blocks2to100 } from "../../utils/fixtures/testnet/blocks2to100";
import { delegates } from "../../utils/fixtures/testnet/delegates";
Expand All @@ -23,9 +22,8 @@ const resetBlocksInCurrentRound = async () => {
};

const resetToHeight1 = async () => {
const lastBlock = await blockchain.database.getLastBlock();

if (lastBlock) {
if (blockchain.getLastHeight() > 1) {
const lastBlock = await blockchain.database.getLastBlock();
// Make sure the wallet manager has been fed or else revertRound
// cannot determine the previous delegates. This is only necessary, because
// the database is not dropped after the unit tests are done.
Expand Down Expand Up @@ -74,9 +72,10 @@ describe("Blockchain", () => {

blockchain = container.resolvePlugin("blockchain");

// Create the genesis block after the setup has finished or else it uses a potentially
// wrong network config.
genesisBlock = Blocks.BlockFactory.fromData(GB);
genesisBlock = container
.resolvePlugin("state")
.getStore()
.getGenesisBlock();

configManager = container.getConfig();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { app } from "@arkecosystem/core-container";
import { Managers } from "@arkecosystem/crypto";
import { plugin } from "../../../../packages/core-database-postgres/src/plugin";
import { plugin as pluginDatabase } from "../../../../packages/core-database/src/plugin";
import { registerWithContainer, setUpContainer } from "../../../utils/helpers/container";
Expand All @@ -13,6 +14,8 @@ export const setUp = async () => {

process.env.CORE_RESET_DATABASE = "1";

Managers.configManager.getMilestone().aip11 = false;

await registerWithContainer(pluginDatabase);

await registerWithContainer(plugin, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import "jest-extended";

import { app } from "@arkecosystem/core-container";
import { Database, State } from "@arkecosystem/core-interfaces";
import { Blocks, Interfaces } from "@arkecosystem/crypto";
import { Blocks, Interfaces, Managers } from "@arkecosystem/crypto";
import { genesisBlock } from "../../utils/config/testnet/genesisBlock";
import { setUp, tearDown } from "./__support__/setup";

Expand All @@ -12,11 +12,7 @@ let databaseService: Database.IDatabaseService;

beforeAll(async () => {
await setUp();

databaseService = app.resolvePlugin<Database.IDatabaseService>("database");

await databaseService.deleteBlocks([genesisBlock]);
await databaseService.saveBlock(BlockFactory.fromData(genesisBlock));
});

afterAll(async () => {
Expand Down Expand Up @@ -53,7 +49,9 @@ describe("Connection", () => {

describe("getLastBlock", () => {
it("should get the genesis block as last block", async () => {
Managers.configManager.getMilestone().aip11 = false;
await expect(databaseService.getLastBlock()).resolves.toEqual(BlockFactory.fromData(genesisBlock));
Managers.configManager.getMilestone().aip11 = true;
});
});
});
Loading

0 comments on commit 5df769b

Please sign in to comment.