Commit 100c0667 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[fix] #1037 Migrating Entity Block 2/2

parent 8573c0d1
......@@ -9,7 +9,6 @@ import {CHECK} from "../rules/index"
const _ = require('underscore')
const common = require('duniter-common')
const Block = require('../entity/block')
const Identity = require('../entity/identity')
const Certification = require('../entity/certification')
const Membership = require('../entity/membership')
......@@ -161,7 +160,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain {
async pushTheBlock(obj:BlockDTO, index:IndexEntry[], HEAD:DBHead | null, conf:ConfDTO, dal:any, logger:any) {
const start = Date.now();
const block = new Block(obj);
const block = BlockDTO.fromJSONObject(obj)
try {
const currentBlock = await dal.getCurrentBlockOrNull();
block.fork = false;
......@@ -248,7 +247,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain {
async saveParametersForRoot(block:BlockDTO, conf:ConfDTO, dal:any) {
if (block.parameters) {
const bconf = Block.statics.getConf(block);
const bconf = BlockDTO.getConf(block)
conf.c = bconf.c;
conf.dt = bconf.dt;
conf.ud0 = bconf.ud0;
......@@ -504,7 +503,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain {
async pushSideBlock(obj:BlockDTO, dal:any, logger:any) {
const start = Date.now();
const block = new Block(obj);
const block = DBBlock.fromBlockDTO(BlockDTO.fromJSONObject(obj))
block.fork = true;
try {
// Saves the block (DAL)
......
......@@ -6,7 +6,6 @@ import {DBHead} from "../db/DBHead"
const _ = require('underscore');
const indexer = require('../indexer').Indexer
const constants = require('../constants');
const Block = require('../entity/block');
export class BlockchainContext {
......@@ -51,7 +50,7 @@ export class BlockchainContext {
} else {
block = { version: this.vHEAD_1.version };
}
this.vHEAD = await indexer.completeGlobalScope(Block.statics.fromJSON(block), this.conf, [], this.dal);
this.vHEAD = await indexer.completeGlobalScope(BlockDTO.fromJSONObject(block), this.conf, [], this.dal);
})()
return this.HEADrefreshed;
}
......
......@@ -3,11 +3,10 @@ import {DuniterBlockchain} from "../blockchain/DuniterBlockchain"
import {BlockDTO} from "../dto/BlockDTO"
import {DBTransaction} from "../db/DBTransaction"
import {Indexer} from "../indexer"
import {ConfDTO} from "../dto/ConfDTO"
import {CurrencyConfDTO} from "../dto/ConfDTO"
const _ = require('underscore')
const constants = require('../constants')
const Block = require('../entity/block')
let sync_bindex: any [] = [];
let sync_iindex: any[] = [];
......@@ -18,7 +17,7 @@ let sync_bindexSize = 0;
let sync_allBlocks: BlockDTO[] = [];
let sync_expires: number[] = [];
let sync_nextExpiring = 0;
let sync_currConf: ConfDTO;
let sync_currConf: CurrencyConfDTO;
const sync_memoryWallets: any = {}
const sync_memoryDAL = {
getWallet: (conditions: string) => Promise.resolve(sync_memoryWallets[conditions] || { conditions, balance: 0 }),
......@@ -99,7 +98,7 @@ export class QuickSynchronizer {
const dto = BlockDTO.fromJSONObject(block)
if (block.number == 0) {
sync_currConf = Block.statics.getConf(block);
sync_currConf = BlockDTO.getConf(block);
}
if (block.number != to) {
......
import {AbstractSQLite} from "./AbstractSQLite";
import {SQLiteDriver} from "../drivers/SQLiteDriver";
import {ConfDTO} from "../../dto/ConfDTO";
import {SindexEntry} from "../../indexer";
import {hashf} from "../../common";
import {TransactionDTO} from "../../dto/TransactionDTO";
import {BlockDAL} from "./BlockDAL";
import {IdentityDAL} from "./IdentityDAL";
import {SIndexDAL} from "./index/SIndexDAL";
import {WalletDAL} from "./WalletDAL";
import {MIndexDAL} from "./index/MIndexDAL";
import {AbstractSQLite} from "./AbstractSQLite"
import {SQLiteDriver} from "../drivers/SQLiteDriver"
import {ConfDTO} from "../../dto/ConfDTO"
import {SindexEntry} from "../../indexer"
import {hashf} from "../../common"
import {TransactionDTO} from "../../dto/TransactionDTO"
import {BlockDAL} from "./BlockDAL"
import {IdentityDAL} from "./IdentityDAL"
import {SIndexDAL} from "./index/SIndexDAL"
import {WalletDAL} from "./WalletDAL"
import {MIndexDAL} from "./index/MIndexDAL"
import {DBBlock} from "../../db/DBBlock"
const _ = require('underscore')
const logger = require('../../logger').NewLogger('metaDAL');
......@@ -135,13 +136,26 @@ export class MetaDAL extends AbstractSQLite<DBMeta> {
let blockDAL = new BlockDAL(this.driverCopy)
let sindexDAL = new SIndexDAL(this.driverCopy)
const blocks = await blockDAL.query('SELECT * FROM block WHERE NOT fork');
const Block = require('../../../lib/entity/block');
const Identity = require('../../../lib/entity/identity');
const amountsPerKey:any = {};
type AmountPerKey = {
amounts: {
amount: number
comment:string
}[],
sources: {
amount:number
base:number
identifier:string
pos:number,
conditions:string
block:DBBlock,
tx:string|null
}[]
}
const amountsPerKey:{ [pub:string]: AmountPerKey[] } = {}
const members = [];
for (const block of blocks) {
const b = new Block(block);
const amountsInForBlockPerKey:any = {};
for (const b of blocks) {
const amountsInForBlockPerKey: { [pub:string]: AmountPerKey } = {};
for (const idty of b.identities) {
members.push(Identity.statics.fromInline(idty).pubkey);
}
......@@ -149,31 +163,42 @@ export class MetaDAL extends AbstractSQLite<DBMeta> {
for (const member of members) {
amountsInForBlockPerKey[member] = amountsInForBlockPerKey[member] || { amounts: [], sources: [] };
amountsInForBlockPerKey[member].amounts.push({ amount: b.dividend * Math.pow(10, b.unitbase), comment: 'Dividend' });
amountsInForBlockPerKey[member].sources.push({ type: 'D', amount: b.dividend, base: b.unitbase, identifier: member, pos: b.number, block: b, tx: null });
amountsInForBlockPerKey[member].sources.push({ amount: b.dividend, base: b.unitbase, identifier: member, pos: b.number, block: b, tx: null, conditions: 'SIG(' + member + ')' });
}
}
const txs = b.getTransactions();
const txs = b.transactions
for (let i = 0; i < txs.length; i++) {
const tx = txs[i];
tx.hash = hashf(rawer.getTransaction(b.transactions[i]))
for (const input of tx.inputs) {
input.tx = tx.hash;
input.block = b;
for (const input of tx.inputsAsObjects()) {
amountsInForBlockPerKey[tx.issuers[0]] = amountsInForBlockPerKey[tx.issuers[0]] || { amounts: [], sources: [] };
amountsInForBlockPerKey[tx.issuers[0]].amounts.push({ amount: -input.amount * Math.pow(10, input.base), comment: tx.comment || '######' });
amountsInForBlockPerKey[tx.issuers[0]].sources.push(input);
amountsInForBlockPerKey[tx.issuers[0]].sources.push({
amount: input.amount,
base: input.base,
identifier: input.identifier,
pos: input.pos,
conditions: "",
block: b,
tx: tx.hash
})
}
for (let j = 0; j < tx.outputs.length; j++) {
const output = tx.outputs[j];
const outputObjects = tx.outputsAsObjects()
for (let j = 0; j < outputObjects.length; j++) {
const output = outputObjects[j]
const conditions = output.conditions.match(/^SIG\((.+)\)$/);
if (conditions) {
output.tx = tx.hash;
output.identifier = tx.hash;
output.pos = j;
output.block = b;
amountsInForBlockPerKey[conditions[1]] = amountsInForBlockPerKey[conditions[1]] || { amounts: [], sources: [] };
amountsInForBlockPerKey[conditions[1]].amounts.push({ amount: output.amount * Math.pow(10, output.base), comment: tx.comment || '######' });
amountsInForBlockPerKey[conditions[1]].sources.push(output);
amountsInForBlockPerKey[conditions[1]].sources.push({
amount: output.amount,
base: output.base,
identifier: tx.hash,
pos: j,
conditions: output.conditions,
block: b,
tx: tx.hash
})
}
}
}
......@@ -205,8 +230,8 @@ export class MetaDAL extends AbstractSQLite<DBMeta> {
if (balance > 0 && balance < 100) {
const sourcesToDelete = [];
for (const k of Object.keys(amountsPerKey)) {
for (const amPerBlock of Object.keys(amountsPerKey[k])) {
for (const src of amountsPerKey[k][amPerBlock].sources) {
for (const packet of amountsPerKey[k]) {
for (const src of packet.sources) {
const id = [src.identifier, src.pos].join('-');
if (src.conditions == 'SIG(' + key + ')' && allCreates[id]) {
sourcesToDelete.push(src);
......
import {TransactionDTO} from "./TransactionDTO"
import {CurrencyConfDTO} from "./ConfDTO"
export class BlockDTO {
version: number
......@@ -36,6 +37,65 @@ export class BlockDTO {
constructor(
) {}
json() {
return {
version: this.version,
nonce: this.nonce,
number: this.number,
powMin: this.powMin,
time: this.time,
medianTime: this.medianTime,
membersCount: this.membersCount,
monetaryMass: this.monetaryMass,
unitbase: this.unitbase,
issuersCount: this.issuersCount,
issuersFrame: this.issuersFrame,
issuersFrameVar: this.issuersFrameVar,
len: this.len,
currency: this.currency,
issuer: this.issuer,
signature: this.signature,
hash: this.hash,
parameters: this.parameters,
previousHash: this.previousHash,
previousIssuer: this.previousIssuer,
inner_hash: this.inner_hash,
dividend: this.dividend,
identities: this.identities,
joiners: this.joiners,
actives: this.actives,
leavers: this.leavers,
revoked: this.revoked,
excluded: this.excluded,
certifications: this.certifications,
transactions: this.transactions.map((tx) => {
return {
version: tx.version,
currency: tx.currency,
locktime: tx.locktime,
blockstamp: tx.blockstamp,
blockstampTime: tx.blockstampTime,
issuers: tx.issuers,
inputs: tx.inputs,
outputs: tx.outputs,
unlocks: tx.unlocks,
signatures: tx.signatures,
comment: tx.comment
}
})
}
}
get len() {
return this.identities.length +
this.joiners.length +
this.actives.length +
this.leavers.length +
this.revoked.length +
this.certifications.length +
this.transactions.reduce((sum, tx) => sum + tx.getLen(), 0)
}
getInlineIdentity(pubkey:string): string | null {
let i = 0;
let found = null;
......@@ -132,14 +192,14 @@ export class BlockDTO {
dto.issuersCount = parseInt(obj.issuersCount)
dto.issuersFrame = parseInt(obj.issuersFrame)
dto.issuersFrameVar = parseInt(obj.issuersFrameVar)
dto.identities = obj.identities
dto.joiners = obj.joiners
dto.actives = obj.actives
dto.leavers = obj.leavers
dto.revoked = obj.revoked
dto.excluded = obj.excluded
dto.certifications = obj.certifications
dto.transactions = obj.transactions.map(TransactionDTO.fromJSONObject)
dto.identities = obj.identities || []
dto.joiners = obj.joiners || []
dto.actives = obj.actives || []
dto.leavers = obj.leavers || []
dto.revoked = obj.revoked || []
dto.excluded = obj.excluded || []
dto.certifications = obj.certifications || []
dto.transactions = (obj.transactions || []).map(TransactionDTO.fromJSONObject)
dto.medianTime = parseInt(obj.medianTime)
dto.fork = !!obj.fork
dto.parameters = obj.parameters
......@@ -147,4 +207,32 @@ export class BlockDTO {
dto.nonce = parseInt(obj.nonce)
return dto
}
static getConf(block:BlockDTO): CurrencyConfDTO {
const sp = block.parameters.split(':');
return {
c: parseFloat(sp[0]),
dt: parseInt(sp[1]),
ud0: parseInt(sp[2]),
sigPeriod: parseInt(sp[3]),
sigStock: parseInt(sp[4]),
sigWindow: parseInt(sp[5]),
sigValidity: parseInt(sp[6]),
sigQty: parseInt(sp[7]),
idtyWindow: parseInt(sp[8]),
msWindow: parseInt(sp[9]),
xpercent: parseFloat(sp[10]),
msValidity: parseInt(sp[11]),
stepMax: parseInt(sp[12]),
medianTimeBlocks: parseInt(sp[13]),
avgGenTime: parseInt(sp[14]),
dtDiffEval: parseInt(sp[15]),
percentRot: parseFloat(sp[16]),
udTime0: parseInt(sp[17]),
udReevalTime0: parseInt(sp[18]),
dtReeval: parseInt(sp[19]),
// New parameter, defaults to msWindow
msPeriod: parseInt(sp[9])
}
}
}
\ No newline at end of file
......@@ -3,7 +3,30 @@ export interface Keypair {
sec: string
}
export class ConfDTO {
export interface CurrencyConfDTO {
c: number
dt: number
ud0: number
sigPeriod: number
sigStock: number
sigWindow: number
sigValidity: number
sigQty: number
idtyWindow: number
msWindow: number
msPeriod: number
xpercent: number
msValidity: number
stepMax: number
medianTimeBlocks: number
avgGenTime: number
dtDiffEval: number
percentRot: number
udTime0: number
udReevalTime0: number
dtReeval: number
}
export class ConfDTO implements CurrencyConfDTO {
constructor(
public loglevel: string,
......
......@@ -46,6 +46,14 @@ export class TransactionDTO {
}
}
getLen() {
return 2 // header + blockstamp
+ this.issuers.length * 2 // issuers + signatures
+ this.inputs.length * 2 // inputs + unlocks
+ (this.comment ? 1 : 0)
+ this.outputs.length
}
getHash() {
const raw = TransactionDTO.toRAW(this)
return hashf(raw)
......
"use strict";
const _ = require('underscore');
const common = require('duniter-common')
const document = common.document;
const hashf = common.hashf;
const Transaction = require('./transaction');
module.exports = Block;
function Block(json) {
this.documentType = 'block';
this.transactions = this.transactions || [];
this.excluded = this.excluded || [];
this.actives = this.actives || [];
this.leavers = this.leavers || [];
this.revoked = this.revoked || [];
this.identities = this.identities || [];
this.joiners = this.joiners || [];
this.certifications = this.certifications || [];
_(json || {}).keys().forEach((key) => {
let value = json[key];
if (
key == "number"
|| key == "medianTime"
|| key == "time"
|| key == "version"
|| key == "nonce"
|| key == "powMin"
|| key == "membersCount"
|| key == "dividend"
|| key == "unitbase"
|| key == "issuersCount"
|| key == "issuersFrame"
|| key == "issuersFrameVar"
|| key == "len"
|| key == "UDTime"
) {
if (typeof value == "string") {
value = parseInt(value);
}
if (isNaN(value) || value === null) {
value = 0;
}
}
this[key] = value;
});
[
"dividend"
].forEach((field) => {
this[field] = parseInt(this[field]) || null;
});
this.json = () => {
const b = document.Block.fromJSON(this)
return b.json()
}
this.getHash = () => {
if (!this.hash) {
this.hash = hashf(this.getProofOfWorkPart()).toUpperCase();
}
return this.hash;
};
this.getRawInnerPart = () => {
return require('duniter-common').rawer.getBlockInnerPart(this);
};
this.getRaw = () => {
return require('duniter-common').rawer.getBlockWithInnerHashAndNonce(this);
};
this.getSignedPart = () => {
return require('duniter-common').rawer.getBlockInnerHashAndNonce(this);
};
this.getProofOfWorkPart = () => {
return require('duniter-common').rawer.getBlockInnerHashAndNonceWithSignature(this);
};
this.getRawSigned = () => {
return require('duniter-common').rawer.getBlock(this);
};
this.quickDescription = () => {
let desc = '#' + this.number + ' (';
desc += this.identities.length + ' newcomers, ' + this.certifications.length + ' certifications)';
return desc;
};
this.getInlineIdentity = (pubkey) => {
let i = 0;
let found = false;
while (!found && i < this.identities.length) {
if (this.identities[i].match(new RegExp('^' + pubkey)))
found = this.identities[i];
i++;
}
return found;
};
this.getTransactions = () => {
const transactions = [];
const currency = this.currency;
this.transactions.forEach((simpleTx) => {
const tx = {};
tx.issuers = simpleTx.issuers || [];
tx.signatures = simpleTx.signatures || [];
// Inputs
tx.inputs = [];
(simpleTx.inputs || []).forEach((input) => {
const sp = input.split(':');
tx.inputs.push({
amount: sp[0],
base: sp[1],
type: sp[2],
identifier: sp[3],
pos: parseInt(sp[4]),
raw: input
});
});
// Unlocks
tx.unlocks = simpleTx.unlocks;
// Outputs
tx.outputs = [];
(simpleTx.outputs || []).forEach((output) => {
const sp = output.split(':');
tx.outputs.push({
amount: parseInt(sp[0]),
base: parseInt(sp[1]),
conditions: sp[2],
raw: output
});
});
tx.comment = simpleTx.comment;
tx.version = simpleTx.version;
tx.currency = currency;
tx.locktime = parseInt(simpleTx.locktime);
tx.blockstamp = simpleTx.blockstamp;
transactions.push(tx);
});
return transactions;
};
}
Block.statics = {};
Block.statics.fromJSON = (json) => new Block(json);
Block.statics.getLen = (block) => block.identities.length +
block.joiners.length +
block.actives.length +
block.leavers.length +
block.revoked.length +
block.certifications.length +
block.transactions.reduce((sum, tx) => sum + Transaction.statics.getLen(tx), 0);
Block.statics.getHash = (block) => {
const entity = Block.statics.fromJSON(block);
return entity.getHash();
};
Block.statics.getConf = (block) => {
const sp = block.parameters.split(':');
const bconf = {};
bconf.c = parseFloat(sp[0]);
bconf.dt = parseInt(sp[1]);
bconf.ud0 = parseInt(sp[2]);
bconf.sigPeriod = parseInt(sp[3]);
bconf.sigStock = parseInt(sp[4]);
bconf.sigWindow = parseInt(sp[5]);
bconf.sigValidity = parseInt(sp[6]);
bconf.sigQty = parseInt(sp[7]);
bconf.idtyWindow = parseInt(sp[8]);
bconf.msWindow = parseInt(sp[9]);
bconf.xpercent = parseFloat(sp[10]);
bconf.msValidity = parseInt(sp[11]);
bconf.stepMax = parseInt(sp[12]);
bconf.medianTimeBlocks = parseInt(sp[13]);
bconf.avgGenTime = parseInt(sp[14]);
bconf.dtDiffEval = parseInt(sp[15]);
bconf.percentRot = parseFloat(sp[16]);
bconf.udTime0 = parseInt(sp[17]);
bconf.udReevalTime0 = parseInt(sp[18]);
bconf.dtReeval = parseInt(sp[19]);
return bconf;
};
"use strict";
import {BlockDTO} from "./dto/BlockDTO"
import {ConfDTO} from "./dto/ConfDTO"
import {ConfDTO, CurrencyConfDTO} from "./dto/ConfDTO"
import {IdentityDTO} from "./dto/IdentityDTO"
import {RevocationDTO} from "./dto/RevocationDTO"
import {CertificationDTO} from "./dto/CertificationDTO"
......@@ -129,7 +129,7 @@ function pushCindex(index: any[], entry: CindexEntry): void {
export class Indexer {
static localIndex(block:BlockDTO, conf:ConfDTO): IndexEntry[] {
static localIndex(block:BlockDTO, conf:CurrencyConfDTO): IndexEntry[] {
/********************
* GENERAL BEHAVIOR
......@@ -411,7 +411,7 @@ export class Indexer {