Commit f911bbd4 authored by Cédric Moreau's avatar Cédric Moreau

[fix] Add /blockchain/milestones/* URLs (cherry-picked from 1.7 branch)

parent febfdb8c
......@@ -300,7 +300,9 @@ export const CommonConstants = {
SPECIAL_BLOCK
},
BLOCK_MAX_TX_CHAINING_DEPTH: 5
BLOCK_MAX_TX_CHAINING_DEPTH: 5,
SYNC_BLOCKS_CHUNK: 250,
MILESTONES_PER_PAGE: 50,
}
function exact (regexpContent:string) {
......
......@@ -153,19 +153,6 @@ export const BmaDependency = {
if (program.upnp === true) {
conf.upnp = true;
}
// Configuration errors
if (!conf.nobma) {
if(!conf.ipv4 && !conf.ipv6){
throw new Error("No interface to listen to.");
}
if(!conf.remoteipv4 && !conf.remoteipv6 && !conf.remotehost){
throw new Error('No interface for remote contact.');
}
if (!conf.remoteport) {
throw new Error('No port for remote contact.');
}
}
},
beforeSave: async (conf:NetworkConfDTO, program:any) => {
......@@ -179,6 +166,18 @@ export const BmaDependency = {
service: {
input: (server:Server, conf:NetworkConfDTO, logger:any) => {
// Configuration errors
if (!conf.nobma) {
if(!conf.ipv4 && !conf.ipv6){
throw new Error("No interface to listen to.");
}
if(!conf.remoteipv4 && !conf.remoteipv6 && !conf.remotehost){
throw new Error('No interface for remote contact.');
}
if (!conf.remoteport) {
throw new Error('No port for remote contact.');
}
}
if (!conf.nobma) {
server.addEndpointsDefinitions(() => Promise.resolve(getEndpoint(conf)))
server.addWrongEndpointFilter((endpoints:string[]) => getWrongEndpoints(endpoints, server.conf.pair.pub))
......
......@@ -66,6 +66,8 @@ export const bma = function(server:Server, interfaces:NetworkInterface[], httpLo
httpMethods.httpPOST( '/blockchain/block', (req:any) => blockchain.parseBlock(req), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/block/:number', (req:any) => blockchain.promoted(req), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/blocks/:count/:from', (req:any) => blockchain.blocks(req), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/milestones', (req:any) => blockchain.milestones(req), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/milestones/:page', (req:any) => blockchain.milestones(req), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/current', (req:any) => blockchain.current(), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/hardship/:search', (req:any) => blockchain.hardship(req), BMALimitation.limitAsHighUsage());
httpMethods.httpGET( '/blockchain/difficulties', (req:any) => blockchain.difficulties(), BMALimitation.limitAsHighUsage());
......
......@@ -52,7 +52,8 @@ export const BMAConstants = {
NO_CURRENT_BLOCK: { httpCode: 404, uerr: { ucode: 2010, message: "No current block" }},
PEER_NOT_FOUND: { httpCode: 404, uerr: { ucode: 2012, message: "Peer not found" }},
NO_IDTY_MATCHING_PUB_OR_UID: { httpCode: 404, uerr: { ucode: 2021, message: "No identity matching this pubkey or uid" }},
TX_NOT_FOUND: { httpCode: 400, uerr: { ucode: 2034, message: 'Transaction not found' }}
TX_NOT_FOUND: { httpCode: 400, uerr: { ucode: 2034, message: 'Transaction not found' }},
INCORRECT_PAGE_NUMBER: { httpCode: 400, uerr: { ucode: 2035, message: 'Incorrect page number' }}
// New errors: range 3000-4000
}
......
......@@ -24,14 +24,14 @@ import {
HttpDifficulties,
HttpHardship,
HttpMembership,
HttpMemberships,
HttpMemberships, HttpMilestonePage,
HttpParameters,
HttpStat
} from "../dtos"
const _ = require('underscore');
const http2raw = require('../http2raw');
const toJson = require('../tojson');
import * as toJson from "../tojson"
export class BlockchainBinding extends AbstractController {
......@@ -125,6 +125,11 @@ export class BlockchainBinding extends AbstractController {
return blocks;
}
async milestones(req: any): Promise<HttpMilestonePage> {
const page = ParametersService.getPage(req)
return this.server.milestones(page)
}
async current(): Promise<HttpBlock> {
const current = await this.server.dal.getCurrentBlockOrNull();
if (!current) throw BMAConstants.ERRORS.NO_CURRENT_BLOCK;
......
......@@ -967,3 +967,25 @@ export interface HttpSandboxes {
export const LogLink = {
link: String
};
export interface HttpMilestonePage {
totalPages: number
chunkSize: number
milestonesPerPage: number
currentPage?: number
blocks?: HttpBlock[]
}
export const Milestones = {
totalPages: Number,
chunkSize: Number,
milestonesPerPage: Number,
currentPage: Number,
"blocks": [Block]
}
export const MilestonesPage = {
totalPages: Number,
chunkSize: Number,
milestonesPerPage: Number,
}
......@@ -73,6 +73,17 @@ export class ParametersService {
return parseInt(req.params.minsig)
}
static getPage(req:any): number|undefined {
if(!req.params.page){
return undefined
}
const matches = req.params.page.match(/\d+/)
if(!matches){
throw Error("`page` format is incorrect, must be an integer")
}
return parseInt(req.params.page)
}
static getPubkey = function (req:any, callback:any){
if(!req.params.pubkey){
callback('Parameter `pubkey` is required');
......
......@@ -24,7 +24,7 @@ import * as stream from "stream"
import {KeyGen, randomKey} from "./app/lib/common-libs/crypto/keyring"
import {parsers} from "./app/lib/common-libs/parsers/index"
import {Cloneable} from "./app/lib/dto/Cloneable"
import {DuniterDocument, duniterDocument2str} from "./app/lib/common-libs/constants"
import {CommonConstants, DuniterDocument, duniterDocument2str} from "./app/lib/common-libs/constants"
import {GlobalFifoPromise} from "./app/service/GlobalFifoPromise"
import {BlockchainContext} from "./app/lib/computation/BlockchainContext"
import {BlockDTO} from "./app/lib/dto/BlockDTO"
......@@ -38,6 +38,9 @@ import {OtherConstants} from "./app/lib/other_constants"
import {WS2PCluster} from "./app/modules/ws2p/lib/WS2PCluster"
import {DBBlock} from "./app/lib/db/DBBlock"
import { ProxiesConf } from './app/lib/proxy';
import {BMAConstants} from "./app/modules/bma/lib/constants"
import * as toJson from "./app/modules/bma/lib/tojson"
import {HttpMilestonePage} from "./app/modules/bma/lib/dtos"
export interface HookableServer {
generatorGetJoinData: (...args:any[]) => Promise<any>
......@@ -85,6 +88,7 @@ export class Server extends stream.Duplex implements HookableServer {
BlockchainService:BlockchainService
TransactionsService:TransactionService
private documentFIFO:GlobalFifoPromise
milestoneArray: DBBlock[] = []
constructor(home:string, memoryOnly:boolean, private overrideConf:any) {
super({ objectMode: true })
......@@ -669,4 +673,52 @@ export class Server extends stream.Duplex implements HookableServer {
resetConfigHook(): Promise<any> {
return Promise.resolve({})
}
async milestones(page?: number): Promise<HttpMilestonePage> {
const chunkSize = CommonConstants.SYNC_BLOCKS_CHUNK
const milestonesPerPage = CommonConstants.MILESTONES_PER_PAGE
const current = await this.dal.getCurrentBlockOrNull();
if (!current) {
return {
totalPages: 0,
chunkSize,
milestonesPerPage
}
}
const topNumber = current.number - this.conf.forksize
const nbMilestones = (topNumber - (topNumber % chunkSize)) / chunkSize
const totalPages = (nbMilestones - (nbMilestones % milestonesPerPage)) / milestonesPerPage
if (page === undefined) {
return {
totalPages,
chunkSize,
milestonesPerPage
}
}
if (page > totalPages || page <= 0) throw BMAConstants.ERRORS.INCORRECT_PAGE_NUMBER
while (this.milestoneArray.length < page * milestonesPerPage) {
const lastMilestoneNumber = this.milestoneArray.length
// Feed the milestones
const newMilestones: DBBlock[] = []
for (let i = 1; i <= milestonesPerPage && this.milestoneArray.length < page * milestonesPerPage; i++) {
const b = await this.dal.getBlock((lastMilestoneNumber + i) * chunkSize - 1)
if (!b) {
throw Error('MILESTONE_BLOCK_NOT_FOUND')
}
newMilestones.push(b)
}
// As the process is async, another call to "milestones()" maybe have already filled in the milestones
if (this.milestoneArray.length < page * milestonesPerPage) {
this.milestoneArray = this.milestoneArray.concat(newMilestones)
}
}
const blocks = this.milestoneArray.slice((page - 1) * milestonesPerPage, page * milestonesPerPage)
return {
totalPages,
chunkSize,
milestonesPerPage,
currentPage: page,
blocks: blocks.map(b => toJson.block(b))
}
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment