Skip to content

Commit

Permalink
Merge remote-tracking branch 'ArkEcosystem/core/develop' into blockid
Browse files Browse the repository at this point in the history
* ArkEcosystem/core/develop:
  feat(core-api): add active delegates endpoint (#2205)
  fix(core-tester-cli): set crypto network for debug commands (#2204)
  • Loading branch information
vasild committed Mar 7, 2019
2 parents dddcb6e + 7889947 commit 84f3710
Show file tree
Hide file tree
Showing 22 changed files with 288 additions and 114 deletions.
144 changes: 84 additions & 60 deletions .circleci/config.yml

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions __tests__/integration/core-api/v2/handlers/delegates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,37 @@ describe("API 2.0 - Delegates", () => {
);
});

describe("GET /delegates/active", () => {
describe.each([["API-Version", "request"], ["Accept", "requestWithAcceptHeader"]])(
"using the %s header",
(header, request) => {
it("should GET all the active delegates at the current network height", async () => {
const activeDelegates = app.getConfig().getMilestone().activeDelegates;

const response = await utils[request]("GET", "delegates/active");
expect(response).toBeSuccessfulResponse();
expect(response.data.data).toBeArray();
expect(response.data.data).toHaveLength(activeDelegates);

response.data.data.forEach(utils.expectDelegate);
expect(response.data.data.sort((a, b) => a.rank < b.rank)).toEqual(response.data.data);
});

it("should GET all the active delegates at the specified height", async () => {
const activeDelegates = app.getConfig().getMilestone(1).activeDelegates;

const response = await utils[request]("GET", "delegates/active", { height: 1 });
expect(response).toBeSuccessfulResponse();
expect(response.data.data).toBeArray();
expect(response.data.data).toHaveLength(activeDelegates);

response.data.data.forEach(utils.expectDelegate);
expect(response.data.data.sort((a, b) => a.rank < b.rank)).toEqual(response.data.data);
});
},
);
});

describe("GET /delegates/:id", () => {
describe.each([["API-Version", "request"], ["Accept", "requestWithAcceptHeader"]])(
"using the %s header",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,7 @@ describe("Delegate Repository", () => {

expect(results).toBeArray();
expect(results[0].username).toBeString();
expect(results[0].approval).toBeNumber();
expect(results[0].productivity).toBeNumber();
expect(results[0].approval).toBe(delegateCalculator.calculateApproval(delegate, height));
expect(results[0].productivity).toBe(delegateCalculator.calculateProductivity(delegate));
expect(results[0].username).toEqual(delegate.username);
});
});
});
22 changes: 19 additions & 3 deletions __tests__/unit/core-tester-cli/commands/debug/deserialize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ describe("Commands - Deserialize", () => {
const fixtureTransaction = require("../../__fixtures__/transaction.json");

it("should deserialize a block (not-full)", async () => {
const actual = JSON.parse(await DeserializeCommand.run(["--data", fixtureBlock.serialized, "--type", "block"]));
const actual = JSON.parse(
await DeserializeCommand.run(["--data", fixtureBlock.serialized, "--type", "block", "--network", "devnet"]),
);

expect(actual.data.version).toBe(fixtureBlock.data.version);
expect(actual.data.timestamp).toBe(fixtureBlock.data.timestamp);
Expand All @@ -25,7 +27,14 @@ describe("Commands - Deserialize", () => {

it("should deserialize a block (full)", async () => {
const actual = JSON.parse(
await DeserializeCommand.run(["--data", fixtureBlock.serializedFull, "--type", "block"]),
await DeserializeCommand.run([
"--data",
fixtureBlock.serializedFull,
"--type",
"block",
"--network",
"devnet",
]),
);

expect(actual.data.version).toBe(fixtureBlock.data.version);
Expand All @@ -45,7 +54,14 @@ describe("Commands - Deserialize", () => {

it("should deserialize a transaction", async () => {
const actual = JSON.parse(
await DeserializeCommand.run(["--data", fixtureTransaction.serialized, "--type", "transaction"]),
await DeserializeCommand.run([
"--data",
fixtureTransaction.serialized,
"--type",
"transaction",
"--network",
"devnet",
]),
);

expect(actual.type).toBe(fixtureTransaction.data.type);
Expand Down
39 changes: 30 additions & 9 deletions __tests__/unit/core-tester-cli/commands/debug/identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ describe("Commands - Identity", async () => {
address: "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
};

expect(await IdentityCommand.run(["--data", fixtureIdentities.passphrase, "--type", "passphrase"])).toEqual(
expected,
);
expect(
await IdentityCommand.run([
"--data",
fixtureIdentities.passphrase,
"--type",
"passphrase",
"--network",
"devnet",
]),
).toEqual(expected);
});

it("should return identities from privateKey", async () => {
Expand All @@ -25,9 +32,16 @@ describe("Commands - Identity", async () => {
address: "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
};

expect(await IdentityCommand.run(["--data", fixtureIdentities.privateKey, "--type", "privateKey"])).toEqual(
expected,
);
expect(
await IdentityCommand.run([
"--data",
fixtureIdentities.privateKey,
"--type",
"privateKey",
"--network",
"devnet",
]),
).toEqual(expected);
});

it("should return identities from publicKey", async () => {
Expand All @@ -36,8 +50,15 @@ describe("Commands - Identity", async () => {
address: "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
};

expect(await IdentityCommand.run(["--data", fixtureIdentities.publicKey, "--type", "publicKey"])).toEqual(
expected,
);
expect(
await IdentityCommand.run([
"--data",
fixtureIdentities.publicKey,
"--type",
"publicKey",
"--network",
"devnet",
]),
).toEqual(expected);
});
});
32 changes: 27 additions & 5 deletions __tests__/unit/core-tester-cli/commands/debug/serialize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,42 @@ describe("Commands - Serialize", () => {
const fixtureTransaction = require("../../__fixtures__/transaction.json");

it("should serialize a block (not-full)", async () => {
expect(await SerializeCommand.run(["--data", JSON.stringify(fixtureBlock.data), "--type", "block"])).toEqual(
fixtureBlock.serialized,
);
expect(
await SerializeCommand.run([
"--data",
JSON.stringify(fixtureBlock.data),
"--type",
"block",
"--network",
"devnet",
]),
).toEqual(fixtureBlock.serialized);
});

it("should serialize a block (full)", async () => {
expect(
await SerializeCommand.run(["--data", JSON.stringify(fixtureBlock.data), "--type", "block", "--full"]),
await SerializeCommand.run([
"--data",
JSON.stringify(fixtureBlock.data),
"--type",
"block",
"--full",
"--network",
"devnet",
]),
).toEqual(fixtureBlock.serializedFull);
});

it("should serialize a transaction", async () => {
expect(
await SerializeCommand.run(["--data", JSON.stringify(fixtureTransaction.data), "--type", "transaction"]),
await SerializeCommand.run([
"--data",
JSON.stringify(fixtureTransaction.data),
"--type",
"transaction",
"--network",
"devnet",
]),
).toEqual(fixtureTransaction.serialized);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ describe("Commands - Verify Second", () => {
fixtureTransaction.serialized,
"--publicKey",
"03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609",
"--network",
"devnet",
]),
).toBeTrue();
});
Expand Down
15 changes: 13 additions & 2 deletions __tests__/unit/core-tester-cli/commands/debug/verify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@ describe("Commands - Verify", () => {
const fixtureTransaction = require("../../__fixtures__/transaction.json");

it("should verify a block", async () => {
expect(await VerifyCommand.run(["--data", fixtureBlock.serializedFull, "--type", "block"])).toBeTrue();
expect(
await VerifyCommand.run(["--data", fixtureBlock.serializedFull, "--type", "block", "--network", "devnet"]),
).toBeTrue();
});

it("should verify a transaction", async () => {
expect(await VerifyCommand.run(["--data", fixtureTransaction.serialized, "--type", "transaction"])).toBeTrue();
expect(
await VerifyCommand.run([
"--data",
fixtureTransaction.serialized,
"--type",
"transaction",
"--network",
"devnet",
]),
).toBeTrue();
});
});
11 changes: 11 additions & 0 deletions packages/core-api/src/versions/2/delegates/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ export class DelegatesController extends Controller {
}
}

public async active(request: Hapi.Request, h: Hapi.ResponseToolkit) {
try {
// @ts-ignore
const data = await request.server.methods.v2.delegates.active(request);

return super.respondWithCache(data, h);
} catch (error) {
return Boom.badImplementation(error);
}
}

public async show(request: Hapi.Request, h: Hapi.ResponseToolkit) {
try {
// @ts-ignore
Expand Down
23 changes: 21 additions & 2 deletions packages/core-api/src/versions/2/delegates/methods.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { app } from "@arkecosystem/core-container";
import { Database } from "@arkecosystem/core-interfaces";
import { Blockchain, Database } from "@arkecosystem/core-interfaces";
import { orderBy } from "@arkecosystem/utils";
import Boom from "boom";
import { blocksRepository } from "../../../repositories";
import { ServerCache } from "../../../services";
import { paginate, respondWithResource, toPagination } from "../utils";
import { paginate, respondWithResource, respondWithCollection, toPagination } from "../utils";

const config = app.getConfig();
const databaseService = app.resolvePlugin<Database.IDatabaseService>("database");
const blockchain = app.resolvePlugin<Blockchain.IBlockchain>("blockchain");

const index = async request => {
const delegates = await databaseService.delegates.findAll({
Expand All @@ -17,6 +19,18 @@ const index = async request => {
return toPagination(request, delegates, "delegate");
};

const active = async request => {
const delegates = await databaseService.delegates.getActiveAtHeight(
request.query.height || blockchain.getLastHeight()
);

if (!delegates.length) {
return Boom.notFound("Delegates not found");
}

return respondWithCollection(request, delegates, "delegate");
};

const show = async request => {
const delegate = await databaseService.delegates.findById(request.params.id);

Expand Down Expand Up @@ -82,11 +96,16 @@ const voterBalances = async request => {
};

export function registerMethods(server) {
const { activeDelegates, blocktime } = config.getMilestone();

ServerCache.make(server)
.method("v2.delegates.index", index, 8, request => ({
...request.query,
...paginate(request),
}))
.method("v2.delegates.active", active, activeDelegates * blocktime, request => ({
...request.query
}))
.method("v2.delegates.show", show, 8, request => ({ id: request.params.id }))
.method("v2.delegates.search", search, 30, request => ({
...request.payload,
Expand Down
9 changes: 9 additions & 0 deletions packages/core-api/src/versions/2/delegates/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ export function registerRoutes(server: Hapi.Server): void {
},
});

server.route({
method: "GET",
path: "/delegates/active",
handler: controller.active,
options: {
validate: Schema.active,
},
});

server.route({
method: "GET",
path: "/delegates/{id}",
Expand Down
8 changes: 8 additions & 0 deletions packages/core-api/src/versions/2/delegates/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ export const index: object = {
},
};

export const active: object = {
query: {
height: Joi.number()
.integer()
.min(1),
}
};

export const show: object = {
params: {
id: schemaIdentifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,7 @@ export class DelegatesBusinessRepository implements Database.IDelegatesBusinessR
const delegates = await this.databaseServiceProvider().getActiveDelegates(height);

return delegates.map(delegate => {
const wallet = this.databaseServiceProvider().wallets.findById(delegate.publicKey);

return {
username: wallet.username,
approval: delegateCalculator.calculateApproval(delegate, height),
productivity: delegateCalculator.calculateProductivity(wallet),
};
return this.databaseServiceProvider().wallets.findById(delegate.publicKey);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ export interface IDelegatesBusinessRepository {

findById(id: string): models.Wallet;

getActiveAtHeight(height: number): Promise<Array<{ username: string; approval: number; productivity: number }>>;
getActiveAtHeight(height: number): Promise<models.Wallet[]>;
}
6 changes: 3 additions & 3 deletions packages/core-p2p/src/peer-verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ export class PeerVerifier {
// the last block in a round (so that the delegates calculations are still the same for
// both chains).

const delegates = await this.getDelegates(round);
const delegates = await this.getDelegatesByRound(round);

const hisBlocksByHeight = {};

Expand All @@ -324,10 +324,10 @@ export class PeerVerifier {

/**
* Get the delegates for the given round.
* @param {Object} round round to get delegates for
* @param {Object} round to get delegates for
* @return {Object} a map of { publicKey: delegate, ... } of all delegates for the given round
*/
private async getDelegates(round: any): Promise<any> {
private async getDelegatesByRound(round: any): Promise<any> {
const numDelegates = round.maxDelegates;

const heightOfFirstBlockInRound = (round.round - 1) * numDelegates + 1;
Expand Down
Loading

0 comments on commit 84f3710

Please sign in to comment.