Commit 65adbcfe authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[fix] #1037 Migrating Entity Membership

parent f5830efd
......@@ -9,10 +9,10 @@ import {CHECK} from "../rules/index"
import {RevocationDTO} from "../dto/RevocationDTO"
import {IdentityDTO} from "../dto/IdentityDTO"
import {CertificationDTO} from "../dto/CertificationDTO"
import {MembershipDTO} from "../dto/MembershipDTO"
const _ = require('underscore')
const common = require('duniter-common')
const Membership = require('../entity/membership')
const Transaction = require('../entity/transaction')
export class DuniterBlockchain extends MiscIndexedBlockchain {
......@@ -292,7 +292,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain {
async updateMembers(block:BlockDTO, dal:any) {
// Joiners (come back)
for (const inlineMS of block.joiners) {
let ms = Membership.statics.fromInline(inlineMS);
let ms = MembershipDTO.fromInline(inlineMS)
const idty = await dal.getWrittenIdtyByPubkey(ms.issuer);
dal.wotb.setEnabled(true, idty.wotb_id);
}
......@@ -435,8 +435,11 @@ export class DuniterBlockchain extends MiscIndexedBlockchain {
async removeMembershipsFromSandbox(block:BlockDTO, dal:any) {
const mss = block.joiners.concat(block.actives).concat(block.leavers);
for (const inlineMS of mss) {
let ms = Membership.statics.fromInline(inlineMS);
await dal.deleteMS(ms);
let ms = MembershipDTO.fromInline(inlineMS)
await dal.deleteMS({
issuer: ms.issuer,
signature: ms.signature
});
}
}
......
......@@ -12,6 +12,7 @@ import {DBCert} from "./sqliteDAL/CertDAL"
import {DBWallet} from "./sqliteDAL/WalletDAL"
import {DBTx} from "./sqliteDAL/TxsDAL"
import {DBBlock} from "../db/DBBlock"
import {DBMembership} from "./sqliteDAL/MembershipDAL"
const fs = require('fs')
const path = require('path')
......@@ -676,7 +677,7 @@ export class FileDAL {
return true;
}
savePendingMembership(ms:any) {
savePendingMembership(ms:DBMembership) {
return this.msDAL.savePendingMembership(ms)
}
......
import {IdentityDTO} from "./IdentityDTO"
import * as moment from "moment"
const DEFAULT_DOCUMENT_VERSION = 10
export class MembershipDTO {
sigDate?:number
date?:number
constructor(
public version: number,
public currency: string,
public issuer: string,
public type: string,
public blockstamp:string,
public userid:string,
public certts:string,
public signature:string
) {}
get pubkey() {
return this.issuer
}
get pub() {
return this.issuer
}
get membership() {
return this.type
}
get fpr() {
return this.blockstamp.split('-')[1]
}
get number() {
return parseInt(this.blockstamp)
}
get block_number() {
return parseInt(this.blockstamp)
}
getIdtyHash() {
return IdentityDTO.getTargetHash({
buid: this.certts,
uid: this.userid,
pubkey: this.issuer
})
}
getRaw() {
let raw = ""
raw += "Version: " + this.version + "\n"
raw += "Type: Membership\n"
raw += "Currency: " + this.currency + "\n"
raw += "Issuer: " + this.issuer + "\n"
raw += "Block: " + this.blockstamp + "\n"
raw += "Membership: " + this.type + "\n"
raw += "UserID: " + this.userid + "\n"
raw += "CertTS: " + this.certts + "\n"
return raw
}
getRawSigned() {
return this.getRaw() + this.signature + "\n"
}
json() {
return {
signature: this.signature,
membership: {
version: this.version,
currency: this.currency,
issuer: this.issuer,
membership: this.type,
date: this.date && moment(this.date).unix(),
sigDate: this.sigDate && moment(this.sigDate).unix(),
raw: this.getRaw()
}
};
}
static fromInline(inlineMS:string, type:string = "", currency:string = "") {
const [issuer, sig, blockstamp, certts, userid] = inlineMS.split(':');
return new MembershipDTO(
DEFAULT_DOCUMENT_VERSION,
currency,
issuer,
type,
blockstamp,
userid,
certts,
sig
)
}
static fromJSONObject(obj:any) {
return new MembershipDTO(
obj.version,
obj.currency,
obj.issuer || obj.pubkey,
obj.type || obj.membership,
obj.blockstamp || obj.block,
obj.userid,
obj.certts,
obj.signature
)
}
}
"use strict";
const _ = require('underscore');
const moment = require('moment');
const rawer = require('duniter-common').rawer;
const constants = require('../constants');
const Membership = function(json) {
_(json).keys().forEach((key) => {
this[key] = json[key];
});
this.blockNumber = isNaN(this.number) ? this.number : parseInt(this.number);
this.blockHash = this.fpr;
this.version = constants.DOCUMENTS_VERSION;
this.keyID = () => this.issuer && this.issuer.length > 24 ? "0x" + this.issuer.substring(24) : "0x?";
this.copyValues = (to) => {
const obj = this;
["version", "currency", "issuer", "membership", "amNumber", "hash", "signature", "sigDate"].forEach(function (key) {
to[key] = obj[key];
});
};
this.json = () => {
const obj = {};
["version", "currency", "issuer", "membership"].forEach((key) => {
obj[key] = this[key];
});
obj.date = this.date && moment(this.date).unix();
obj.sigDate = this.sigDate && moment(this.sigDate).unix();
obj.raw = this.getRaw();
return { signature: this.signature, membership: obj };
};
this.getRaw = () => rawer.getMembershipWithoutSignature(this);
this.getRawSigned = () => rawer.getMembership(this);
};
Membership.statics = {};
Membership.statics.fromInline = function (inlineMS, type, currency) {
const sp = inlineMS.split(':');
return new Membership({
version: constants.DOCUMENTS_VERSION,
currency: currency,
issuer: sp[0],
membership: type,
type: type,
number: parseInt(sp[2]),
fpr: sp[2].split('-')[1],
block: sp[2],
certts: sp[3],
userid: sp[4],
signature: sp[1]
});
};
Membership.statics.toInline = function (entity) {
return [entity.issuer, entity.signature, entity.number, entity.fpr, entity.certts, entity.userid].join(':');
};
Membership.statics.fromJSON = (json) => new Membership(json);
module.exports = Membership;
......@@ -5,11 +5,11 @@ import {BlockDTO} from "../dto/BlockDTO"
import {RevocationDTO} from "../dto/RevocationDTO"
import {IdentityDTO} from "../dto/IdentityDTO"
import {CertificationDTO} from "../dto/CertificationDTO"
import {MembershipDTO} from "../dto/MembershipDTO"
const request = require('request');
const constants = require('../../lib/constants');
const Peer = require('../../lib/entity/peer');
const Membership = require('../../lib/entity/membership');
const Transaction = require('../../lib/entity/transaction');
const logger = require('../logger').NewLogger('multicaster');
......@@ -124,10 +124,10 @@ export class Multicaster extends stream.Transform {
async msForward(doc:any, peers:DBPeer[]) {
return this.forward({
transform: Membership.statics.fromJSON,
transform: (obj:any) => MembershipDTO.fromJSONObject(obj),
type: 'Membership',
uri: '/blockchain/membership',
getObj: (membership:any) => {
getObj: (membership:MembershipDTO) => {
return {
"membership": membership.getRaw(),
"signature": membership.signature
......
......@@ -4,10 +4,10 @@ import {ConfDTO} from "../lib/dto/ConfDTO"
import {FileDAL} from "../lib/dal/fileDAL"
import {LOCAL_RULES_HELPERS} from "../lib/rules/local_rules"
import {GLOBAL_RULES_HELPERS} from "../lib/rules/global_rules"
import {MembershipDTO} from "../lib/dto/MembershipDTO"
const hashf = require('duniter-common').hashf;
const constants = require('../lib/constants');
const Membership = require('../lib/entity/membership');
export class MembershipService {
......@@ -27,17 +27,16 @@ export class MembershipService {
submitMembership(ms:any) {
return GlobalFifoPromise.pushFIFO(async () => {
const entry = new Membership(ms);
const entry = MembershipDTO.fromJSONObject(ms)
// Force usage of local currency name, do not accept other currencies documents
entry.currency = this.conf.currency || entry.currency;
entry.idtyHash = (hashf(entry.userid + entry.certts + entry.issuer) + "").toUpperCase();
this.logger.info('⬇ %s %s', entry.issuer, entry.membership);
if (!LOCAL_RULES_HELPERS.checkSingleMembershipSignature(entry)) {
throw constants.ERRORS.WRONG_SIGNATURE_MEMBERSHIP;
}
// Get already existing Membership with same parameters
const mostRecentNumber = await this.dal.getMostRecentMembershipNumberForIssuer(entry.issuer);
const thisNumber = parseInt(entry.block);
const thisNumber = entry.number
if (mostRecentNumber == thisNumber) {
throw constants.ERRORS.ALREADY_RECEIVED_MEMBERSHIP;
} else if (mostRecentNumber > thisNumber) {
......@@ -51,15 +50,31 @@ export class MembershipService {
}
const current = await this.dal.getCurrentBlockOrNull();
const basedBlock = await GLOBAL_RULES_HELPERS.checkMembershipBlock(entry, current, this.conf, this.dal);
if (basedBlock) {
entry.expires_on = basedBlock.medianTime + this.conf.msWindow;
}
entry.pubkey = entry.issuer;
if (!(await this.dal.msDAL.sandbox.acceptNewSandBoxEntry(entry, this.conf.pair && this.conf.pair.pub))) {
if (!(await this.dal.msDAL.sandbox.acceptNewSandBoxEntry({
pubkey: entry.pubkey,
block_number: entry.block_number
}, this.conf.pair && this.conf.pair.pub))) {
throw constants.ERRORS.SANDBOX_FOR_MEMERSHIP_IS_FULL;
}
// Saves entry
await this.dal.savePendingMembership(entry);
await this.dal.savePendingMembership({
membership: entry.membership,
issuer: entry.issuer,
number: entry.number,
blockNumber: entry.number,
blockHash: entry.fpr,
userid: entry.userid,
certts: entry.certts,
block: entry.blockstamp,
fpr: entry.fpr,
idtyHash: entry.getIdtyHash(),
written: false,
written_number: null,
expires_on: basedBlock ? basedBlock.medianTime + this.conf.msWindow : null,
signature: entry.signature,
expired: false,
block_number: entry.number
});
this.logger.info('✔ %s %s', entry.issuer, entry.membership);
return entry;
})
......
......@@ -11,7 +11,7 @@ const keyring = common.keyring;
const rawer = common.rawer;
const constants = require('../../../app/lib/constants');
const CertificationDTO = require('../../../app/lib/dto/CertificationDTO').CertificationDTO
const Membership = require('../../../app/lib/entity/membership');
const MembershipDTO = require('../../../app/lib/dto/MembershipDTO').MembershipDTO
const RevocationDTO = require('../../../app/lib/dto/RevocationDTO').RevocationDTO
const Peer = require('../../../app/lib/entity/peer');
const Transaction = require('../../../app/lib/entity/transaction');
......@@ -146,7 +146,7 @@ function User (uid, options, node) {
_.extend(join, overrideProps || {});
const rawJoin = rawer.getMembershipWithoutSignature(join);
join.signature = keyring.Key(pub, sec).signSync(rawJoin);
return Membership.statics.fromJSON(join);
return MembershipDTO.fromJSONObject(join)
});
this.sendMembership = (type) => co(function*() {
......
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