Skip to content

Commit 401843c

Browse files
HoOngEemajecty
authored andcommitted
setup for report double vote
1 parent f6ea149 commit 401843c

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright 2019 Kodebox, Inc.
2+
// This file is part of CodeChain.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
import * as chai from "chai";
18+
import { expect } from "chai";
19+
import * as chaiAsPromised from "chai-as-promised";
20+
import { SDK } from "codechain-sdk";
21+
import * as stake from "codechain-stakeholder-sdk";
22+
import { Custom } from "codechain-sdk/lib/core/transaction/Custom";
23+
import {
24+
U64,
25+
H256,
26+
signSchnorr,
27+
blake256,
28+
H512
29+
} from "codechain-primitives/lib";
30+
import "mocha";
31+
import * as RLP from "rlp";
32+
33+
import { validators as originalValidators } from "../../tendermint.dynval/constants";
34+
import { faucetAddress, faucetSecret } from "../helper/constants";
35+
import { PromiseExpect } from "../helper/promise";
36+
import { Signer } from "../helper/spawn";
37+
38+
chai.use(chaiAsPromised);
39+
40+
const HANDLER_ID = 2;
41+
const REPORT_DOUBLE_VOTE_ACTION_ID = 5;
42+
43+
type MessageData = {
44+
height: number;
45+
view: number;
46+
step: "propose" | "prevote" | "precommit" | "commit";
47+
blockHash: H256 | null;
48+
privKey: string;
49+
signerIdx: number;
50+
};
51+
52+
function encodableMessage(data: MessageData): RLP.Input {
53+
const { height, view, step, blockHash, privKey, signerIdx } = data;
54+
const encodableStep = (stepString => {
55+
switch (stepString) {
56+
case "propose":
57+
return 0;
58+
case "prevote":
59+
return 1;
60+
case "precommit":
61+
return 2;
62+
case "commit":
63+
return 3;
64+
}
65+
})(step);
66+
const encodableVoteStep = [
67+
U64.ensure(height).toEncodeObject(),
68+
U64.ensure(view).toEncodeObject(),
69+
encodableStep
70+
];
71+
const encodableBlockHash =
72+
blockHash === null ? [] : [blockHash.toEncodeObject()];
73+
const encodableVoteOn = [encodableVoteStep, encodableBlockHash];
74+
75+
const rlpVoteOn = RLP.encode(encodableVoteOn);
76+
const messageForSchnorr = blake256(rlpVoteOn);
77+
const schnorrSignature = signSchnorr(messageForSchnorr, privKey);
78+
// pad because signSchnorr function does not guarantee the length of r and s to be 64.
79+
const encodableSchnorrSignature = new H512(
80+
schnorrSignature.r.padStart(64, "0") +
81+
schnorrSignature.s.padStart(64, "0")
82+
).toEncodeObject();
83+
84+
return [
85+
encodableVoteOn,
86+
encodableSchnorrSignature,
87+
U64.ensure(signerIdx).toEncodeObject()
88+
];
89+
}
90+
91+
function createDoubleVoteMessages(
92+
data: Omit<MessageData, "blockHash">,
93+
blockHash1: H256 | null,
94+
blockHash2: H256 | null
95+
) {
96+
return [
97+
encodableMessage({ ...data, blockHash: blockHash1 }),
98+
encodableMessage({ ...data, blockHash: blockHash2 })
99+
];
100+
}
101+
102+
function createReportDoubleVoteTransaction(
103+
sdk: SDK,
104+
message1: RLP.Input,
105+
message2: RLP.Input
106+
): Custom {
107+
return sdk.core.createCustomTransaction({
108+
handlerId: HANDLER_ID,
109+
bytes: RLP.encode([REPORT_DOUBLE_VOTE_ACTION_ID, message1, message2])
110+
});
111+
}
112+
113+
const allDynValidators = originalValidators.slice(0, 4);
114+
const [alice, ...otherDynValidators] = allDynValidators;
115+
116+
async function expectPossibleAuthors(
117+
sdk: SDK,
118+
expected: Signer[],
119+
blockNumber?: number
120+
) {
121+
const authors = (await stake.getPossibleAuthors(sdk, blockNumber))!.map(
122+
author => author.toString()
123+
);
124+
expect(authors)
125+
.to.have.lengthOf(expected.length)
126+
.and.to.include.members(
127+
expected.map(signer => signer.platformAddress.toString())
128+
);
129+
}
130+
131+
// FIXME: neeeds to use common refactored function when gets banned state accounts
132+
async function ensureAliceIsBanned(sdk: SDK, blockNumber: number) {
133+
await expectPossibleAuthors(sdk, otherDynValidators, blockNumber);
134+
const bannedAfter = (await stake.getBanned(sdk, blockNumber)).map(
135+
platformAddr => platformAddr.toString()
136+
);
137+
expect(bannedAfter).to.includes(alice.platformAddress.toString());
138+
const delegteesAfter = (await stake.getDelegations(
139+
sdk,
140+
faucetAddress,
141+
blockNumber
142+
)).map(delegation => delegation.delegatee.toString());
143+
expect(delegteesAfter).not.to.includes(alice.platformAddress.toString());
144+
}
145+
146+
describe("Report Double Vote", function() {
147+
const promiseExpect = new PromiseExpect();
148+
149+
afterEach(async function() {
150+
promiseExpect.checkFulfilled();
151+
});
152+
});

0 commit comments

Comments
 (0)