Skip to content

Commit

Permalink
fix(core-transactions): allow unvoting a resigned delegate (#3201)
Browse files Browse the repository at this point in the history
  • Loading branch information
dated authored and spkjp committed Nov 5, 2019
1 parent 1b3c5b6 commit f361a79
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 25 deletions.
78 changes: 60 additions & 18 deletions __tests__/functional/transaction-forging/vote.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,66 @@ beforeAll(support.setUp);
afterAll(support.tearDown);

describe("Transaction Forging - Vote", () => {
it("should broadcast, accept and forge it [Signed with 1 Passphase]", async () => {
// Initial Funds
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();

// Submit a vote
const transactions = TransactionFactory.vote(Identities.PublicKey.fromPassphrase(secrets[0]))
.withPassphrase(passphrase)
.createOne();

await expect(transactions).toBeAccepted();
await support.snoozeForBlock(1);
await expect(transactions.id).toBeForged();
describe("Signed with 1 Passphase", () => {
it("should broadcast, accept and forge it", async () => {
// Initial Funds
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 delegate
const registration = TransactionFactory.delegateRegistration()
.withPassphrase(passphrase)
.createOne();

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

// Submit a vote
const vote = TransactionFactory.vote(Identities.PublicKey.fromPassphrase(passphrase))
.withPassphrase(passphrase)
.createOne();

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

it("should broadcast, accept and forge it if unvoting a resigned delegate", async () => {
// Resign a delegate
const resignation = TransactionFactory.delegateResignation()
.withPassphrase(passphrase)
.createOne();

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

// Submit an unvote
const unvote = TransactionFactory.unvote(Identities.PublicKey.fromPassphrase(passphrase))
.withPassphrase(passphrase)
.createOne();

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

it("should broadcast, reject and not forge it if voting for a resigned delegate", async () => {
// Submit a vote
const vote = TransactionFactory.vote(Identities.PublicKey.fromPassphrase(passphrase))
.withPassphrase(passphrase)
.createOne();

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

it("should broadcast, accept and forge it [Signed with 2 Passphrases]", async () => {
Expand Down
15 changes: 8 additions & 7 deletions packages/core-transactions/src/handlers/vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,21 @@ export class VoteTransactionHandler extends TransactionHandler {
walletManager: State.IWalletManager,
): Promise<void> {
const { data }: Interfaces.ITransaction = transaction;

const vote: string = data.asset.votes[0];
const walletVote: string = wallet.getAttribute("vote");

const delegatePublicKey: string = vote.slice(1);
const delegateWallet: State.IWallet = walletManager.findByPublicKey(delegatePublicKey);

if (vote.startsWith("+")) {
if (walletVote) {
throw new AlreadyVotedError();
}

if (delegateWallet.hasAttribute("delegate.resigned")) {
throw new VotedForResignedDelegateError(vote);
}
} else {
if (!walletVote) {
throw new NoVoteError();
Expand All @@ -77,17 +85,10 @@ export class VoteTransactionHandler extends TransactionHandler {
}
}

const delegatePublicKey: string = vote.slice(1);
const delegateWallet: State.IWallet = walletManager.findByPublicKey(delegatePublicKey);

if (!delegateWallet.isDelegate()) {
throw new VotedForNonDelegateError(vote);
}

if (delegateWallet.hasAttribute("delegate.resigned")) {
throw new VotedForResignedDelegateError(vote);
}

return super.throwIfCannotBeApplied(transaction, wallet, walletManager);
}

Expand Down

0 comments on commit f361a79

Please sign in to comment.