diff --git a/README.md b/README.md index 50715a55c7daccb32d8fcc9da8417edcd08ebe04..0b387b757b48739fc903b5442abcb898524c7687 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ If you wish to participate/debate on Duniter, you can: ### Developement Duniter is using modules on different git repositories: +- [Common](https://github.com/duniter/duniter-common): commons tools for Duniter core and modules. - [Crawler](https://github.com/duniter/duniter-crawler): network crawler. - [Prover](https://github.com/duniter/duniter-prover): handle Proof-of-Work. - [BMA API](https://github.com/duniter/duniter-bma): Basic Merkled API. @@ -61,6 +62,7 @@ Duniter is using modules on different git repositories: - [Web admin](https://github.com/duniter/duniter-ui): web administration interface (optional). Optional modules: +- [Currency monit](https://github.com/duniter/duniter-currency-monit): charts to monitor currency and web of trust state. - [Remuniter](https://github.com/duniter/remuniter): service to remunerate blocks issuers. - [Wot explorer](https://github.com/c-geek/wotex): Web of Trust explorer. diff --git a/app/lib/computation/blockchainContext.js b/app/lib/computation/blockchainContext.js index 2753350b16b40625a0b44467731d8408b2ac27d2..87cf93d00daa666eca5ff5565756ff15a01e8cf1 100644 --- a/app/lib/computation/blockchainContext.js +++ b/app/lib/computation/blockchainContext.js @@ -2,18 +2,19 @@ const _ = require('underscore'); const co = require('co'); const Q = require('q'); -const indexer = require('../dup/indexer'); +const common = require('duniter-common'); +const indexer = require('duniter-common').indexer; const constants = require('../constants'); -const rules = require('../rules/index'); +const rules = require('duniter-common').rules; const Identity = require('../entity/identity'); const Certification = require('../entity/certification'); const Membership = require('../entity/membership'); const Block = require('../entity/block'); const Transaction = require('../entity/transaction'); -module.exports = () => { return new BlockchainContext() }; +module.exports = (BlockchainService) => { return new BlockchainContext(BlockchainService) }; -function BlockchainContext() { +function BlockchainContext(BlockchainService) { const that = this; let conf, dal, logger; @@ -53,7 +54,7 @@ function BlockchainContext() { } else { block = { version: vHEAD_1.version }; } - vHEAD = yield indexer.completeGlobalScope(Block.statics.fromJSON(block).json(), conf, [], dal); + vHEAD = yield indexer.completeGlobalScope(Block.statics.fromJSON(block), conf, [], dal); }); return HEADrefreshed; } @@ -153,6 +154,8 @@ function BlockchainContext() { if (indexer.ruleIdentityWritability(iindex, conf) === false) throw Error('ruleIdentityWritability'); // BR_G64 if (indexer.ruleMembershipWritability(mindex, conf) === false) throw Error('ruleMembershipWritability'); + // BR_G108 + if (indexer.ruleMembershipPeriod(mindex) === false) throw Error('ruleMembershipPeriod'); // BR_G65 if (indexer.ruleCertificationWritability(cindex, conf) === false) throw Error('ruleCertificationWritability'); // BR_G66 @@ -274,7 +277,7 @@ function BlockchainContext() { for (const entry of writtenOn) { const from = yield dal.getWrittenIdtyByPubkey(entry.issuer); const to = yield dal.getWrittenIdtyByPubkey(entry.receiver); - if (entry.op == constants.IDX_CREATE) { + if (entry.op == common.constants.IDX_CREATE) { // We remove the created link dal.wotb.removeLink(from.wotb_id, to.wotb_id, true); } else { @@ -297,6 +300,12 @@ function BlockchainContext() { // Set the block as SIDE block (equivalent to removal from main branch) yield dal.blockDAL.setSideBlock(number, previousBlock); + const REVERSE_BALANCE = true + const sindexOfBlock = yield dal.sindexDAL.getWrittenOn(blockstamp) + + // Revert the balances variations for this block + yield that.updateWallets(sindexOfBlock, dal, REVERSE_BALANCE) + // Remove any source created for this block (both Dividend and Transaction). yield dal.removeAllSourcesOfBlock(blockstamp); @@ -353,6 +362,9 @@ function BlockchainContext() { // Create/Update nodes in wotb yield that.updateMembers(block); + // Update the wallets' blances + yield that.updateWallets(indexes.sindex, dal) + const TAIL = yield dal.bindexDAL.tail(); const bindexSize = [ block.issuersCount, @@ -413,7 +425,7 @@ function BlockchainContext() { this.createNewcomers = (iindex) => co(function*() { for (const entry of iindex) { - if (entry.op == constants.IDX_CREATE) { + if (entry.op == common.constants.IDX_CREATE) { // Reserves a wotb ID entry.wotb_id = dal.wotb.addNode(); logger.trace('%s was affected wotb_id %s', entry.uid, entry.wotb_id); @@ -447,13 +459,33 @@ function BlockchainContext() { }); }); + this.updateWallets = (sindex, dal, reverse) => co(function *() { + return co(function *() { + const differentConditions = _.uniq(sindex.map((entry) => entry.conditions)) + for (const conditions of differentConditions) { + const creates = _.filter(sindex, (entry) => entry.conditions === conditions && entry.op === common.constants.IDX_CREATE) + const updates = _.filter(sindex, (entry) => entry.conditions === conditions && entry.op === common.constants.IDX_UPDATE) + const positives = creates.reduce((sum, src) => sum + src.amount * Math.pow(10, src.base), 0) + const negatives = updates.reduce((sum, src) => sum + src.amount * Math.pow(10, src.base), 0) + const wallet = yield dal.getWallet(conditions) + let variation = positives - negatives + if (reverse) { + // To do the opposite operations, for a reverted block + variation *= -1 + } + wallet.balance += variation + yield dal.saveWallet(wallet) + } + }); + }); + function undoMembersUpdate (blockstamp) { return co(function *() { const joiners = yield dal.iindexDAL.getWrittenOn(blockstamp); for (const entry of joiners) { // Undo 'join' which can be either newcomers or comebackers // => equivalent to i_index.member = true AND i_index.op = 'UPDATE' - if (entry.member === true && entry.op === constants.IDX_UPDATE) { + if (entry.member === true && entry.op === common.constants.IDX_UPDATE) { const idty = yield dal.getWrittenIdtyByPubkey(entry.pub); dal.wotb.setEnabled(false, idty.wotb_id); } @@ -462,7 +494,7 @@ function BlockchainContext() { for (const entry of newcomers) { // Undo newcomers // => equivalent to i_index.op = 'CREATE' - if (entry.op === constants.IDX_CREATE) { + if (entry.op === common.constants.IDX_CREATE) { // Does not matter which one it really was, we pop the last X identities dal.wotb.removeNode(); } @@ -471,7 +503,7 @@ function BlockchainContext() { for (const entry of excluded) { // Undo excluded (make them become members again in wotb) // => equivalent to m_index.member = false - if (entry.member === false && entry.op === constants.IDX_UPDATE) { + if (entry.member === false && entry.op === common.constants.IDX_UPDATE) { const idty = yield dal.getWrittenIdtyByPubkey(entry.pub); dal.wotb.setEnabled(true, idty.wotb_id); } @@ -600,4 +632,197 @@ function BlockchainContext() { yield dal.removeTxByHash(txHash); } }); + + let bindex = []; + let iindex = []; + let mindex = []; + let cindex = []; + let sindex = []; + let bindexSize = 0; + let allBlocks = []; + let expires = []; + let nextExpiring = 0; + let currConf = {}; + const memoryWallets = {} + const memoryDAL = { + getWallet: (conditions) => Promise.resolve(memoryWallets[conditions] || { conditions, balance: 0 }), + saveWallet: (wallet) => co(function*() { + // Make a copy + memoryWallets[wallet.conditions] = { + conditions: wallet.conditions, + balance: wallet.balance + } + }) + } + + this.quickApplyBlocks = (blocks, to) => co(function*() { + + memoryDAL.sindexDAL = { getAvailableForConditions: dal.sindexDAL.getAvailableForConditions } + const ctx = that + let blocksToSave = []; + + for (const block of blocks) { + allBlocks.push(block); + + if (block.number == 0) { + currConf = Block.statics.getConf(block); + } + + if (block.number != to) { + blocksToSave.push(block); + const index = indexer.localIndex(block, currConf); + const local_iindex = indexer.iindex(index); + const local_cindex = indexer.cindex(index); + const local_sindex = indexer.sindex(index); + const local_mindex = indexer.mindex(index); + iindex = iindex.concat(local_iindex); + cindex = cindex.concat(local_cindex); + mindex = mindex.concat(local_mindex); + + const HEAD = yield indexer.quickCompleteGlobalScope(block, currConf, bindex, iindex, mindex, cindex, { + getBlock: (number) => { + return Promise.resolve(allBlocks[number]); + }, + getBlockByBlockstamp: (blockstamp) => { + return Promise.resolve(allBlocks[parseInt(blockstamp)]); + } + }); + bindex.push(HEAD); + + // Remember expiration dates + for (const entry of index) { + if (entry.op === 'CREATE' && (entry.expires_on || entry.revokes_on)) { + expires.push(entry.expires_on || entry.revokes_on); + } + } + expires = _.uniq(expires); + + yield ctx.createNewcomers(local_iindex); + + if (block.dividend + || block.joiners.length + || block.actives.length + || block.revoked.length + || block.excluded.length + || block.certifications.length + || block.transactions.length + || block.medianTime >= nextExpiring) { + // logger.warn('>> Block#%s', block.number) + + for (let i = 0; i < expires.length; i++) { + let expire = expires[i]; + if (block.medianTime > expire) { + expires.splice(i, 1); + i--; + } + } + let currentNextExpiring = nextExpiring + nextExpiring = expires.reduce((max, value) => max ? Math.min(max, value) : value, nextExpiring); + const nextExpiringChanged = currentNextExpiring !== nextExpiring + + // Fills in correctly the SINDEX + yield _.where(sindex.concat(local_sindex), { op: 'UPDATE' }).map((entry) => co(function*() { + if (!entry.conditions) { + const src = yield dal.sindexDAL.getSource(entry.identifier, entry.pos); + entry.conditions = src.conditions; + } + })) + + // Flush the INDEX (not bindex, which is particular) + yield dal.mindexDAL.insertBatch(mindex); + yield dal.iindexDAL.insertBatch(iindex); + yield dal.sindexDAL.insertBatch(sindex); + yield dal.cindexDAL.insertBatch(cindex); + mindex = []; + iindex = []; + cindex = []; + sindex = local_sindex; + + sindex = sindex.concat(yield indexer.ruleIndexGenDividend(HEAD, dal)); + sindex = sindex.concat(yield indexer.ruleIndexGarbageSmallAccounts(HEAD, sindex, memoryDAL)); + if (nextExpiringChanged) { + cindex = cindex.concat(yield indexer.ruleIndexGenCertificationExpiry(HEAD, dal)); + mindex = mindex.concat(yield indexer.ruleIndexGenMembershipExpiry(HEAD, dal)); + iindex = iindex.concat(yield indexer.ruleIndexGenExclusionByMembership(HEAD, mindex, dal)); + iindex = iindex.concat(yield indexer.ruleIndexGenExclusionByCertificatons(HEAD, cindex, local_iindex, conf, dal)); + mindex = mindex.concat(yield indexer.ruleIndexGenImplicitRevocation(HEAD, dal)); + } + // Update balances with UD + local garbagings + yield that.updateWallets(sindex, memoryDAL) + + // --> Update links + yield dal.updateWotbLinks(local_cindex.concat(cindex)); + + // Flush the INDEX again + yield dal.mindexDAL.insertBatch(mindex); + yield dal.iindexDAL.insertBatch(iindex); + yield dal.sindexDAL.insertBatch(sindex); + yield dal.cindexDAL.insertBatch(cindex); + mindex = []; + iindex = []; + cindex = []; + sindex = []; + + // Create/Update nodes in wotb + yield ctx.updateMembers(block); + } + + // Trim the bindex + bindexSize = [ + block.issuersCount, + block.issuersFrame, + conf.medianTimeBlocks, + conf.dtDiffEval, + blocks.length + ].reduce((max, value) => { + return Math.max(max, value); + }, 0); + + if (bindexSize && bindex.length >= 2 * bindexSize) { + // We trim it, not necessary to store it all (we already store the full blocks) + bindex.splice(0, bindexSize); + + // Process triming continuously to avoid super long ending of sync + yield dal.trimIndexes(bindex[0].number); + } + } else { + + if (blocksToSave.length) { + yield BlockchainService.saveBlocksInMainBranch(blocksToSave); + } + blocksToSave = []; + + // Save the INDEX + yield dal.bindexDAL.insertBatch(bindex); + yield dal.mindexDAL.insertBatch(mindex); + yield dal.iindexDAL.insertBatch(iindex); + yield dal.sindexDAL.insertBatch(sindex); + yield dal.cindexDAL.insertBatch(cindex); + + // Save the intermediary table of wallets + const conditions = _.keys(memoryWallets) + const nonEmptyKeys = _.filter(conditions, (k) => memoryWallets[k] && memoryWallets[k].balance > 0) + const walletsToRecord = nonEmptyKeys.map((k) => memoryWallets[k]) + yield dal.walletDAL.insertBatch(walletsToRecord) + + // Last block: cautious mode to trigger all the INDEX expiry mechanisms + yield BlockchainService.submitBlock(block, true, true); + + // Clean temporary variables + bindex = []; + iindex = []; + mindex = []; + cindex = []; + sindex = []; + bindexSize = 0; + allBlocks = []; + expires = []; + nextExpiring = 0; + currConf = {}; + } + } + if (blocksToSave.length) { + yield BlockchainService.saveBlocksInMainBranch(blocksToSave); + } + }) } diff --git a/app/lib/constants.js b/app/lib/constants.js index 4418b4da7fe62afddd218b6f2070cccc6063d28e..0e8e784f760cdf63cd7aacf54edd5680e815f8ce 100644 --- a/app/lib/constants.js +++ b/app/lib/constants.js @@ -1,42 +1,18 @@ "use strict"; -const CURRENCY = "[a-zA-Z0-9-_ ]{2,50}"; +const common = require('duniter-common') + const UDID2 = "udid2;c;([A-Z-]*);([A-Z-]*);(\\d{4}-\\d{2}-\\d{2});(e\\+\\d{2}\\.\\d{2}(\\+|-)\\d{3}\\.\\d{2});(\\d+)(;?)"; -const USER_ID = "[A-Za-z0-9_-]{2,100}"; -const BASE58 = "[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+"; -const PUBKEY = "[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}"; -const SIG = "[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}"; -const TIMESTAMP = "[1-9][0-9]{0,18}"; -const POSITIVE_INT = "[1-9][0-9]{0,18}"; -const DIVIDEND = "[1-9][0-9]{0,5}"; -const ZERO_OR_POSITIVE_INT = "0|[1-9][0-9]{0,18}"; -const INTEGER = "(0|[1-9]\\d{0,18})"; -const CLTV_INTEGER = "([0-9]{1,10})"; -const CSV_INTEGER = "([0-9]{1,8})"; -const XUNLOCK = "[a-zA-Z0-9]{1,64}"; -const RELATIVE_INTEGER = "(0|-?[1-9]\\d{0,18})"; -const FLOAT = "\\d+\.\\d+"; -const BOOLEAN = "[01]"; -const BLOCK_VERSION = "(10)"; -const TX_VERSION = "(10)"; -const SIGNATURE = "[A-Za-z0-9+\\/=]{87,88}"; -const FINGERPRINT = "[A-F0-9]{64}"; -const COMMENT = "[ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]{0,255}"; -const UNLOCK = "(SIG\\(" + INTEGER + "\\)|XHX\\(" + XUNLOCK + "\\))"; -const CONDITIONS = "(&&|\\|\\|| |[()]|(SIG\\(" + SIG + "\\)|(XHX\\([A-F0-9]{64}\\)|CLTV\\(" + CLTV_INTEGER + "\\)|CSV\\(" + CSV_INTEGER + "\\))))*"; -const BLOCK_UID = INTEGER + "-" + FINGERPRINT; -const META_TS = "META:TS:" + BLOCK_UID; +const PUBKEY = common.constants.FORMATS.PUBKEY +const TIMESTAMP = common.constants.FORMATS.TIMESTAMP -const BMA_REGEXP = /^BASIC_MERKLED_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))$/; const IPV4_REGEXP = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/; const IPV6_REGEXP = /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(([0-9A-Fa-f]{1,4}:){0,5}:((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(::([0-9A-Fa-f]{1,4}:){0,5}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/; -const MAXIMUM_LEN_OF_COMPACT_TX = 100; -const MAXIMUM_LEN_OF_OUTPUT = 2000; -const MAXIMUM_LEN_OF_UNLOCK = MAXIMUM_LEN_OF_OUTPUT; - module.exports = { + TIME_TO_TURN_ON_BRG_107: 1498860000, + ERROR: { PEER: { @@ -55,7 +31,7 @@ module.exports = { UNHANDLED: { httpCode: 500, uerr: { ucode: 1002, message: "An unhandled error occured" }}, SIGNATURE_DOES_NOT_MATCH: { httpCode: 400, uerr: { ucode: 1003, message: "Signature does not match" }}, ALREADY_UP_TO_DATE: { httpCode: 400, uerr: { ucode: 1004, message: "Already up-to-date" }}, - WRONG_DOCUMENT: { httpCode: 400, uerr: { ucode: 1005, message: "Document has unkown fields or wrong line ending format" }}, + WRONG_DOCUMENT: common.constants.ERRORS.WRONG_DOCUMENT, SANDBOX_FOR_IDENTITY_IS_FULL: { httpCode: 503, uerr: { ucode: 1007, message: "The identities' sandbox is full. Please retry with another document or retry later." }}, SANDBOX_FOR_CERT_IS_FULL: { httpCode: 503, uerr: { ucode: 1008, message: "The certifications' sandbox is full. Please retry with another document or retry later." }}, SANDBOX_FOR_MEMERSHIP_IS_FULL: { httpCode: 503, uerr: { ucode: 1009, message: "The memberships' sandbox is full. Please retry with another document or retry later." }}, @@ -75,156 +51,50 @@ module.exports = { MEMBERSHIP_A_NON_MEMBER_CANNOT_LEAVE: { httpCode: 400, uerr: { ucode: 2008, message: "A non-member cannot leave" }}, NOT_A_MEMBER: { httpCode: 400, uerr: { ucode: 2009, message: "Not a member" }}, BLOCK_NOT_FOUND: { httpCode: 404, uerr: { ucode: 2011, message: "Block not found" }}, - WRONG_UNLOCKER: { httpCode: 400, uerr: { ucode: 2013, message: "Wrong unlocker in transaction" }}, - LOCKTIME_PREVENT: { httpCode: 400, uerr: { ucode: 2014, message: "Locktime not elapsed yet" }}, - SOURCE_ALREADY_CONSUMED: { httpCode: 400, uerr: { ucode: 2015, message: "Source already consumed" }}, - WRONG_AMOUNTS: { httpCode: 400, uerr: { ucode: 2016, message: "Sum of inputs must equal sum of outputs" }}, - WRONG_OUTPUT_BASE: { httpCode: 400, uerr: { ucode: 2017, message: "Wrong unit base for outputs" }}, - CANNOT_ROOT_BLOCK_NO_MEMBERS: { httpCode: 400, uerr: { ucode: 2018, message: "Wrong new block: cannot make a root block without members" }}, - IDENTITY_WRONGLY_SIGNED: { httpCode: 400, uerr: { ucode: 2019, message: "Weird, the signature is wrong and in the database." }}, - TOO_OLD_IDENTITY: { httpCode: 400, uerr: { ucode: 2020, message: "Identity has expired and cannot be written in the blockchain anymore." }}, + WRONG_UNLOCKER: common.constants.ERRORS.WRONG_UNLOCKER, + LOCKTIME_PREVENT: common.constants.ERRORS.LOCKTIME_PREVENT, + SOURCE_ALREADY_CONSUMED: common.constants.ERRORS.SOURCE_ALREADY_CONSUMED, + WRONG_AMOUNTS: common.constants.ERRORS.WRONG_AMOUNTS, + WRONG_OUTPUT_BASE: common.constants.ERRORS.WRONG_OUTPUT_BASE, + CANNOT_ROOT_BLOCK_NO_MEMBERS: common.constants.ERRORS.CANNOT_ROOT_BLOCK_NO_MEMBERS, + IDENTITY_WRONGLY_SIGNED: common.constants.ERRORS.IDENTITY_WRONGLY_SIGNED, + TOO_OLD_IDENTITY: common.constants.ERRORS.TOO_OLD_IDENTITY, NO_IDTY_MATCHING_PUB_OR_UID: { httpCode: 404, uerr: { ucode: 2021, message: "No identity matching this pubkey or uid" }}, NEWER_PEER_DOCUMENT_AVAILABLE: { httpCode: 409, uerr: { ucode: 2022, message: "A newer peer document is available" }}, PEER_DOCUMENT_ALREADY_KNOWN: { httpCode: 400, uerr: { ucode: 2023, message: "Peer document already known" }}, - TX_INPUTS_OUTPUTS_NOT_EQUAL: { httpCode: 400, uerr: { ucode: 2024, message: "Transaction inputs sum must equal outputs sum" }}, - TX_OUTPUT_SUM_NOT_EQUALS_PREV_DELTAS: { httpCode: 400, uerr: { ucode: 2025, message: "Transaction output base amount does not equal previous base deltas" }}, - BLOCKSTAMP_DOES_NOT_MATCH_A_BLOCK: { httpCode: 400, uerr: { ucode: 2026, message: "Blockstamp does not match a block" }}, - A_TRANSACTION_HAS_A_MAX_SIZE: { httpCode: 400, uerr: { ucode: 2027, message: 'A transaction has a maximum size of ' + MAXIMUM_LEN_OF_COMPACT_TX + ' lines' }}, + TX_INPUTS_OUTPUTS_NOT_EQUAL: common.constants.ERRORS.TX_INPUTS_OUTPUTS_NOT_EQUAL, + TX_OUTPUT_SUM_NOT_EQUALS_PREV_DELTAS: common.constants.ERRORS.TX_OUTPUT_SUM_NOT_EQUALS_PREV_DELTAS, + BLOCKSTAMP_DOES_NOT_MATCH_A_BLOCK: common.constants.ERRORS.BLOCKSTAMP_DOES_NOT_MATCH_A_BLOCK, + A_TRANSACTION_HAS_A_MAX_SIZE: common.constants.ERRORS.A_TRANSACTION_HAS_A_MAX_SIZE, BLOCK_ALREADY_PROCESSED: { httpCode: 400, uerr: { ucode: 2028, message: 'Already processed' }}, - TOO_OLD_MEMBERSHIP: { httpCode: 400, uerr: { ucode: 2029, message: "Too old membership." }}, + TOO_OLD_MEMBERSHIP: common.constants.ERRORS.TOO_OLD_MEMBERSHIP, TX_ALREADY_PROCESSED: { httpCode: 400, uerr: { ucode: 2030, message: "Transaction already processed" }}, A_MORE_RECENT_MEMBERSHIP_EXISTS: { httpCode: 400, uerr: { ucode: 2031, message: "A more recent membership already exists" }}, - MAXIMUM_LEN_OF_OUTPUT: { httpCode: 400, uerr: { ucode: 2032, message: 'A transaction output has a maximum size of ' + MAXIMUM_LEN_OF_OUTPUT + ' characters' }}, - MAXIMUM_LEN_OF_UNLOCK: { httpCode: 400, uerr: { ucode: 2033, message: 'A transaction unlock has a maximum size of ' + MAXIMUM_LEN_OF_UNLOCK + ' characters' }} + MAXIMUM_LEN_OF_OUTPUT: common.constants.ERRORS.MAXIMUM_LEN_OF_OUTPUT, + MAXIMUM_LEN_OF_UNLOCK: common.constants.ERRORS.MAXIMUM_LEN_OF_UNLOCK }, DEBUG: { LONG_DAL_PROCESS: 50 }, - BMA_REGEXP: BMA_REGEXP, + BMA_REGEXP: common.constants.BMA_REGEXP, IPV4_REGEXP: IPV4_REGEXP, IPV6_REGEXP: IPV6_REGEXP, - INTEGER: /^\d+$/, - FINGERPRINT: exact(FINGERPRINT), TIMESTAMP: exact(TIMESTAMP), - USER_ID: exact(USER_ID), // Any format, by default UDID2_FORMAT: exact(UDID2), - BASE58: exact(BASE58), PUBLIC_KEY: exact(PUBKEY), - SIG: exact(SIGNATURE), - BLOCK_UID: exact(BLOCK_UID), - DOCUMENTS_VERSION_REGEXP: /^10$/, - DOCUMENTS_BLOCK_VERSION_REGEXP: new RegExp("^" + BLOCK_VERSION + "$"), - BLOCKSTAMP_REGEXP: new RegExp("^" + BLOCK_UID + "$"), - DOCUMENTS_TRANSACTION_VERSION_REGEXP: /^(10)$/, - DOCUMENTS_VERSION: 10, - BLOCK_GENERATED_VERSION: 10, + DOCUMENTS_VERSION: common.constants.DOCUMENTS_VERSION, + BLOCK_GENERATED_VERSION: common.constants.BLOCK_GENERATED_VERSION, LAST_VERSION_FOR_TX: 10, - TRANSACTION_VERSION: 10, + TRANSACTION_VERSION: common.constants.TRANSACTION_VERSION, - REVOCATION_FACTOR: 2, // This is protocol fixed value - NB_DIGITS_UD: 4, // This is protocol fixed value + REVOCATION_FACTOR: common.constants.REVOCATION_FACTOR, // This is protocol fixed value FIRST_UNIT_BASE: 0, - TX_WINDOW: 3600 * 24 * 7, - - CERT: { - SELF: { - UID: exact("UID:" + USER_ID), - META: exact(META_TS) - }, - REVOKE: exact("UID:REVOKE"), - OTHER: { - META: exact(META_TS), - INLINE: exact(PUBKEY + ":" + PUBKEY + ":" + INTEGER + ":" + SIGNATURE) - } - }, - IDENTITY: { - INLINE: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + USER_ID), - IDTY_TYPE: find('Type: (Identity)'), - IDTY_UID: find('UniqueID: (' + USER_ID + ')') - }, - DOCUMENTS: { - DOC_VERSION: find('Version: (10)'), - DOC_CURRENCY: find('Currency: (' + CURRENCY + ')'), - DOC_ISSUER: find('Issuer: (' + PUBKEY + ')'), - TIMESTAMP: find('Timestamp: (' + BLOCK_UID + ')') - }, - CERTIFICATION: { - CERT_TYPE: find('Type: (Certification)'), - IDTY_ISSUER: find('IdtyIssuer: (' + PUBKEY + ')'), - IDTY_UID: find('IdtyUniqueID: (' + USER_ID + ')'), - IDTY_TIMESTAMP: find('IdtyTimestamp: (' + BLOCK_UID + ')'), - IDTY_SIG: find('IdtySignature: (' + SIGNATURE + ')'), - CERT_TIMESTAMP: find('CertTimestamp: (' + BLOCK_UID + ')') - }, - REVOCATION: { - REVOC_TYPE: find('Type: (Certification)'), - IDTY_ISSUER: find('IdtyIssuer: (' + PUBKEY + ')'), - IDTY_UID: find('IdtyUniqueID: (' + USER_ID + ')'), - IDTY_TIMESTAMP: find('IdtyTimestamp: (' + BLOCK_UID + ')'), - IDTY_SIG: find('IdtySignature: (' + SIGNATURE + ')') - }, - MEMBERSHIP: { - BLOCK: find('Block: (' + BLOCK_UID + ')'), - VERSION: find('Version: (10)'), - CURRENCY: find('Currency: (' + CURRENCY + ')'), - ISSUER: find('Issuer: (' + PUBKEY + ')'), - MEMBERSHIP: find('Membership: (IN|OUT)'), - USERID: find('UserID: (' + USER_ID + ')'), - CERTTS: find('CertTS: (' + BLOCK_UID + ')') - }, - BLOCK: { - NONCE: find("Nonce: (" + ZERO_OR_POSITIVE_INT + ")"), - VERSION: find("Version: " + BLOCK_VERSION), - TYPE: find("Type: (Block)"), - CURRENCY: find("Currency: (" + CURRENCY + ")"), - BNUMBER: find("Number: (" + ZERO_OR_POSITIVE_INT + ")"), - POWMIN: find("PoWMin: (" + ZERO_OR_POSITIVE_INT + ")"), - TIME: find("Time: (" + TIMESTAMP + ")"), - MEDIAN_TIME: find("MedianTime: (" + TIMESTAMP + ")"), - UD: find("UniversalDividend: (" + DIVIDEND + ")"), - UNIT_BASE: find("UnitBase: (" + INTEGER + ")"), - PREV_HASH: find("PreviousHash: (" + FINGERPRINT + ")"), - PREV_ISSUER: find("PreviousIssuer: (" + PUBKEY + ")"), - MEMBERS_COUNT:find("MembersCount: (" + ZERO_OR_POSITIVE_INT + ")"), - BLOCK_ISSUER:find('Issuer: (' + PUBKEY + ')'), - BLOCK_ISSUERS_FRAME:find('IssuersFrame: (' + INTEGER + ')'), - BLOCK_ISSUERS_FRAME_VAR:find('IssuersFrameVar: (' + RELATIVE_INTEGER + ')'), - DIFFERENT_ISSUERS_COUNT:find('DifferentIssuersCount: (' + INTEGER + ')'), - PARAMETERS: find("Parameters: (" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ")"), - JOINER: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + BLOCK_UID + ":" + USER_ID), - ACTIVE: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + BLOCK_UID + ":" + USER_ID), - LEAVER: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + BLOCK_UID + ":" + USER_ID), - REVOCATION: exact(PUBKEY + ":" + SIGNATURE), - EXCLUDED: exact(PUBKEY), - INNER_HASH: find("InnerHash: (" + FINGERPRINT + ")"), - SPECIAL_HASH: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', - SPECIAL_BLOCK: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' - }, - TRANSACTION: { - HEADER: exact("TX:" + TX_VERSION + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + BOOLEAN + ":" + INTEGER), - SENDER: exact(PUBKEY), - SOURCE_V3: exact("(" + POSITIVE_INT + ":" + INTEGER + ":T:" + FINGERPRINT + ":" + INTEGER + "|" + POSITIVE_INT + ":" + INTEGER + ":D:" + PUBKEY + ":" + POSITIVE_INT + ")"), - UNLOCK: exact(INTEGER + ":" + UNLOCK + "( (" + UNLOCK + "))*"), - TARGET: exact(POSITIVE_INT + ":" + INTEGER + ":" + CONDITIONS), - BLOCKSTAMP:find('Blockstamp: (' + BLOCK_UID + ')'), - COMMENT: find("Comment: (" + COMMENT + ")"), - LOCKTIME:find("Locktime: (" + INTEGER + ")"), - INLINE_COMMENT: exact(COMMENT), - OUTPUT_CONDITION: exact(CONDITIONS) - }, - PEER: { - BLOCK: find("Block: (" + INTEGER + "-" + FINGERPRINT + ")"), - SPECIAL_BLOCK: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' - }, - STATUS: { - BLOCK: find("Block: (" + INTEGER + "-" + FINGERPRINT + ")"), - SPECIAL_BLOCK: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' - }, + PEER: common.constants.PEER, NETWORK: { MAX_MEMBERS_TO_FORWARD_TO_FOR_SELF_DOCUMENTS: 10, MAX_NON_MEMBERS_TO_FORWARD_TO_FOR_SELF_DOCUMENTS: 6, @@ -241,26 +111,8 @@ module.exports = { } }, PROOF_OF_WORK: { - MINIMAL_TO_SHOW_IN_LOGS: 3, EVALUATION: 1000, - UPPER_BOUND: [ - '9A-F', - '9A-E', - '9A-D', - '9A-C', - '9A-B', - '9A', - '9', - '8', - '7', - '6', - '5', - '4', - '3', - '2', - '1', - '1' // In case remainder 15 happens for some reason - ] + UPPER_BOUND: common.constants.PROOF_OF_WORK.UPPER_BOUND.slice() }, DEFAULT_CURRENCY_NAME: "no_currency", @@ -274,6 +126,7 @@ module.exports = { STEPMAX: 3, SIGDELAY: 3600 * 24 * 365 * 5, SIGPERIOD: 0, // Instant + MSPERIOD: 0, // Instant SIGSTOCK: 40, SIGWINDOW: 3600 * 24 * 7, // a week SIGVALIDITY: 3600 * 24 * 365, @@ -312,37 +165,12 @@ module.exports = { SANDBOX_SIZE_CERTIFICATIONS: 12, SANDBOX_SIZE_MEMBERSHIPS: 5000, - MAXIMUM_LEN_OF_COMPACT_TX: MAXIMUM_LEN_OF_COMPACT_TX, - MAXIMUM_LEN_OF_OUTPUT, - MAXIMUM_LEN_OF_UNLOCK, - CURRENT_BLOCK_CACHE_DURATION: 10 * 1000, // 30 seconds - CORES_MAXIMUM_USE_IN_PARALLEL: 8, // For more cores, we need to use a better PoW synchronization algorithm - - ENGINE_IDLE_INTERVAL: 5000, - - POW_DIFFICULTY_RANGE_RATIO: 1.189, - - TRANSACTION_MAX_TRIES: 10, - - ACCOUNT_MINIMUM_CURRENT_BASED_AMOUNT: 100, // With `logs` command, the number of tail lines to show - NB_INITIAL_LINES_TO_SHOW: 100, - - // INDEXES - M_INDEX: 'MINDEX', - I_INDEX: 'IINDEX', - S_INDEX: 'SINDEX', - C_INDEX: 'CINDEX', - IDX_CREATE: 'CREATE', - IDX_UPDATE: 'UPDATE' + NB_INITIAL_LINES_TO_SHOW: 100 }; function exact (regexpContent) { return new RegExp("^" + regexpContent + "$"); } - -function find (regexpContent) { - return new RegExp(regexpContent); -} diff --git a/app/lib/dal/drivers/sqlite.js b/app/lib/dal/drivers/sqlite.js index 107004f80e594c35be2e767cfad9532ef33c3c80..0e19b0be4ae5cb5d54327cb518db9fa730349eb9 100644 --- a/app/lib/dal/drivers/sqlite.js +++ b/app/lib/dal/drivers/sqlite.js @@ -22,7 +22,16 @@ function SQLiteDriver(path) { logger.debug('Opening SQLite database "%s"...', path); let sqlite = new sqlite3.Database(path); yield new Promise((resolve) => sqlite.once('open', resolve)); - // Database is opened and ready + // Database is opened + + // Force case sensitiveness on LIKE operator + const sql = 'PRAGMA case_sensitive_like=ON;' + yield new Promise((resolve, reject) => sqlite.exec(sql, (err) => { + if (err) return reject(Error('SQL error "' + err.message + '" on INIT queries "' + sql + '"')) + return resolve() + })); + + // Database is ready return sqlite; })); } diff --git a/app/lib/dal/fileDAL.js b/app/lib/dal/fileDAL.js index b69b0dee9cb1d4ba7440df0e2cc3105f0fcda600..9742f9f40bd75955963a7b54ab18770fb9305b40 100644 --- a/app/lib/dal/fileDAL.js +++ b/app/lib/dal/fileDAL.js @@ -2,7 +2,8 @@ const Q = require('q'); const co = require('co'); const _ = require('underscore'); -const indexer = require('../dup/indexer'); +const common = require('duniter-common'); +const indexer = require('duniter-common').indexer; const logger = require('../logger')('filedal'); const Configuration = require('../entity/configuration'); const Merkle = require('../entity/merkle'); @@ -36,6 +37,7 @@ function FileDAL(params) { this.idtyDAL = new (require('./sqliteDAL/IdentityDAL'))(sqliteDriver); this.certDAL = new (require('./sqliteDAL/CertDAL'))(sqliteDriver); this.msDAL = new (require('./sqliteDAL/MembershipDAL'))(sqliteDriver); + this.walletDAL = new (require('./sqliteDAL/WalletDAL'))(sqliteDriver); this.bindexDAL = new (require('./sqliteDAL/index/BIndexDAL'))(sqliteDriver); this.mindexDAL = new (require('./sqliteDAL/index/MIndexDAL'))(sqliteDriver); this.iindexDAL = new (require('./sqliteDAL/index/IIndexDAL'))(sqliteDriver); @@ -52,6 +54,7 @@ function FileDAL(params) { 'peerDAL': that.peerDAL, 'confDAL': that.confDAL, 'statDAL': that.statDAL, + 'walletDAL': that.walletDAL, 'bindexDAL': that.bindexDAL, 'mindexDAL': that.mindexDAL, 'iindexDAL': that.iindexDAL, @@ -59,14 +62,14 @@ function FileDAL(params) { 'cindexDAL': that.cindexDAL }; - this.init = () => co(function *() { + this.init = (conf) => co(function *() { const dalNames = _.keys(that.newDals); for (const dalName of dalNames) { const dal = that.newDals[dalName]; yield dal.init(); } logger.debug("Upgrade database..."); - yield that.metaDAL.upgradeDatabase(); + yield that.metaDAL.upgradeDatabase(conf); const latestMember = yield that.iindexDAL.getLatestMember(); if (latestMember && that.wotb.getWoTSize() > latestMember.wotb_id + 1) { logger.warn('Maintenance: cleaning wotb...'); @@ -226,6 +229,7 @@ function FileDAL(params) { idty.memberships = mss.concat(mssFromMindex.map((ms) => { const sp = ms.created_on.split('-'); return { + blockstamp: ms.created_on, membership: ms.leaving ? 'OUT' : 'IN', number: sp[0], fpr: sp[1], @@ -370,9 +374,19 @@ function FileDAL(params) { return _(pending).sortBy((ms) => -ms.number)[0]; }); - this.findNewcomers = () => co(function*() { - const mss = yield that.msDAL.getPendingIN(); - return _.chain(mss).sortBy((ms) => -ms.sigDate).value(); + this.findNewcomers = (blockMedianTime) => co(function*() { + const pending = yield that.msDAL.getPendingIN() + const mss = yield pending.map(p => co(function*() { + const reduced = yield that.mindexDAL.getReducedMS(p.issuer) + if (!reduced || !reduced.chainable_on || blockMedianTime >= reduced.chainable_on || blockMedianTime < constants.TIME_TO_TURN_ON_BRG_107) { + return p + } + return null + })) + return _.chain(mss) + .filter(ms => ms) + .sortBy((ms) => -ms.sigDate) + .value() }); this.findLeavers = () => co(function*() { @@ -540,7 +554,7 @@ function FileDAL(params) { for (const entry of cindex) { const from = yield that.getWrittenIdtyByPubkey(entry.issuer); const to = yield that.getWrittenIdtyByPubkey(entry.receiver); - if (entry.op == constants.IDX_CREATE) { + if (entry.op == common.constants.IDX_CREATE) { that.wotb.addLink(from.wotb_id, to.wotb_id); } else { // Update = removal @@ -562,7 +576,7 @@ function FileDAL(params) { yield that.certDAL.trimExpiredCerts(block.medianTime); yield that.msDAL.trimExpiredMemberships(block.medianTime); yield that.idtyDAL.trimExpiredIdentities(block.medianTime); - yield that.txsDAL.trimExpiredNonWrittenTxs(block.medianTime - constants.TX_WINDOW); + yield that.txsDAL.trimExpiredNonWrittenTxs(block.medianTime - common.constants.TX_WINDOW); return true; }); @@ -704,6 +718,20 @@ function FileDAL(params) { }); }; + /*********************** + * WALLETS + **********************/ + + this.getWallet = (conditions) => co(function*() { + let wallet = yield that.walletDAL.getWallet(conditions) + if (!wallet) { + wallet = { conditions, balance: 0 } + } + return wallet + }) + + this.saveWallet = (wallet) => this.walletDAL.saveWallet(wallet) + /*********************** * STATISTICS **********************/ diff --git a/app/lib/dal/sqliteDAL/AbstractIndex.js b/app/lib/dal/sqliteDAL/AbstractIndex.js index 4ad733031a71368ad4ab55a686e7f000ecc43c1b..bfb355658447f250f4693d80d94cef2005bca271 100644 --- a/app/lib/dal/sqliteDAL/AbstractIndex.js +++ b/app/lib/dal/sqliteDAL/AbstractIndex.js @@ -4,7 +4,7 @@ const _ = require('underscore'); const co = require('co'); -const indexer = require('../../dup/indexer'); +const indexer = require('duniter-common').indexer; module.exports = AbstractIndex; diff --git a/app/lib/dal/sqliteDAL/AbstractSQLite.js b/app/lib/dal/sqliteDAL/AbstractSQLite.js index 2551ce2ea1a894220bdcf6dece97f946217071aa..2dfad01c62360fd653529f16fb0832bcaa64dc50 100644 --- a/app/lib/dal/sqliteDAL/AbstractSQLite.js +++ b/app/lib/dal/sqliteDAL/AbstractSQLite.js @@ -69,7 +69,7 @@ function AbstractSQLite(driver) { this.sqlFindLikeAny = (obj, sort) => co(function *() { const keys = _.keys(obj); - return that.query('SELECT * FROM ' + that.table + ' WHERE ' + keys.map((k) => '`' + k + '` like ?').join(' or '), keys.map((k) => obj[k].toUpperCase()), sort); + return that.query('SELECT * FROM ' + that.table + ' WHERE ' + keys.map((k) => 'UPPER(`' + k + '`) like ?').join(' or '), keys.map((k) => obj[k].toUpperCase()), sort); }); this.sqlRemoveWhere = (obj) => co(function *() { diff --git a/app/lib/dal/sqliteDAL/MetaDAL.js b/app/lib/dal/sqliteDAL/MetaDAL.js index 35f84658bd740c9334dd1bd5036ce7817bfb81f0..b90353c54f50dd8a3246428bd8b036c3903527e7 100644 --- a/app/lib/dal/sqliteDAL/MetaDAL.js +++ b/app/lib/dal/sqliteDAL/MetaDAL.js @@ -7,6 +7,7 @@ const co = require('co'); const logger = require('../../logger')('metaDAL'); const AbstractSQLite = require('./AbstractSQLite'); +const common = require('duniter-common'); const hashf = require('duniter-common').hashf; const rawer = require('duniter-common').rawer; const constants = require('./../../constants'); @@ -215,7 +216,7 @@ function MetaDAL(driver) { amountMissing += src.amount; const block = src.block; sourcesMovements.push({ - op: constants.IDX_CREATE, + op: common.constants.IDX_CREATE, tx: src.tx, identifier: src.identifier, pos: src.pos, @@ -248,7 +249,40 @@ function MetaDAL(driver) { 19: 'BEGIN;' + // Add a `removed` column 'ALTER TABLE idty ADD COLUMN removed BOOLEAN NULL DEFAULT 0;' + - 'COMMIT;' + 'COMMIT;', + + /** + * Feeds the table of wallets with balances + */ + 20: () => co(function*() { + let walletDAL = new (require('./WalletDAL'))(driver); + let sindexDAL = new (require('./index/SIndexDAL'))(driver); + const conditions = yield sindexDAL.query('SELECT DISTINCT(conditions) FROM s_index') + for (const row of conditions) { + const wallet = { + conditions: row.conditions, + balance: 0 + } + const amountsRemaining = yield sindexDAL.getAvailableForConditions(row.conditions) + wallet.balance = amountsRemaining.reduce((sum, src) => sum + src.amount * Math.pow(10, src.base), 0) + yield walletDAL.saveWallet(wallet) + } + }), + + /** + * Feeds the m_index.chainable_on + */ + 21: (conf) => co(function*() { + let blockDAL = new (require('./BlockDAL'))(driver); + let mindexDAL = new (require('./index/MIndexDAL'))(driver); + yield mindexDAL.exec('ALTER TABLE m_index ADD COLUMN chainable_on INTEGER NULL;') + const memberships = yield mindexDAL.query('SELECT * FROM m_index WHERE op = ?', [common.constants.IDX_CREATE]) + for (const ms of memberships) { + const reference = yield blockDAL.getBlock(parseInt(ms.written_on.split('-')[0])) + const updateQuery = 'UPDATE m_index SET chainable_on = ' + (reference.medianTime + conf.msPeriod) + ' WHERE pub = \'' + ms.pub + '\' AND op = \'CREATE\'' + yield mindexDAL.exec(updateQuery) + } + }) }; this.init = () => co(function *() { @@ -261,7 +295,7 @@ function MetaDAL(driver) { 'COMMIT;', []); }); - function executeMigration(migration) { + function executeMigration(migration, conf) { return co(function *() { try { if (typeof migration == "string") { @@ -272,7 +306,7 @@ function MetaDAL(driver) { } else if (typeof migration == "function") { // JS function to execute - yield migration(); + yield migration(conf); } } catch (e) { @@ -281,10 +315,10 @@ function MetaDAL(driver) { }); } - this.upgradeDatabase = () => co(function *() { + this.upgradeDatabase = (conf) => co(function *() { let version = yield that.getVersion(); while(migrations[version]) { - yield executeMigration(migrations[version]); + yield executeMigration(migrations[version], conf); // Automated increment yield that.exec('UPDATE meta SET version = version + 1'); version++; diff --git a/app/lib/dal/sqliteDAL/WalletDAL.js b/app/lib/dal/sqliteDAL/WalletDAL.js new file mode 100644 index 0000000000000000000000000000000000000000..88c5eb215a2c86ea3068c2552ffa992e2402db5b --- /dev/null +++ b/app/lib/dal/sqliteDAL/WalletDAL.js @@ -0,0 +1,47 @@ +/** + * Created by cgeek on 22/08/15. + */ + +const co = require('co'); +const AbstractSQLite = require('./AbstractSQLite'); + +module.exports = WalletDAL; + +/** + * Facility table saving the current state of a wallet. + * @param driver SQL driver for making SQL requests. + * @constructor + */ +function WalletDAL(driver) { + + "use strict"; + + AbstractSQLite.call(this, driver); + + const that = this; + + this.table = 'wallet'; + this.fields = [ + 'conditions', + 'balance' + ]; + this.arrays = []; + this.booleans = []; + this.pkFields = ['conditions']; + this.translated = {}; + + this.init = () => co(function *() { + return that.exec('BEGIN;' + + 'CREATE TABLE IF NOT EXISTS ' + that.table + ' (' + + 'conditions TEXT NOT NULL,' + + 'balance INTEGER NOT NULL,' + + 'PRIMARY KEY (conditions)' + + ');' + + 'CREATE INDEX IF NOT EXISTS wallet_balance ON wallet(balance);' + + 'COMMIT;', []); + }); + + this.getWallet = (conditions) => this.sqlFindOne({ conditions }); + + this.saveWallet = (wallet) => this.saveEntity(wallet); +} diff --git a/app/lib/dal/sqliteDAL/index/CIndexDAL.js b/app/lib/dal/sqliteDAL/index/CIndexDAL.js index cd4e99a3737b5dde1afe442ed6b02daceb645270..e3f2c76e00516aad814235d782885a21b86e676d 100644 --- a/app/lib/dal/sqliteDAL/index/CIndexDAL.js +++ b/app/lib/dal/sqliteDAL/index/CIndexDAL.js @@ -4,7 +4,8 @@ const co = require('co'); const constants = require('./../../../constants'); -const indexer = require('./../../../dup/indexer'); +const common = require('duniter-common'); +const indexer = require('duniter-common').indexer; const AbstractSQLite = require('./../AbstractSQLite'); const AbstractIndex = require('./../AbstractIndex'); @@ -85,7 +86,7 @@ function CIndexDAL(driver) { ' AND c1.receiver = c2.receiver' + ' AND c1.created_on = c2.created_on' + ' AND c2.op = ?' + - ')', [medianTime, constants.IDX_UPDATE]); + ')', [medianTime, common.constants.IDX_UPDATE]); this.getValidLinksTo = (receiver) => that.query('SELECT * FROM ' + that.table + ' c1 ' + 'WHERE c1.receiver = ? ' + @@ -96,7 +97,7 @@ function CIndexDAL(driver) { ' AND c1.receiver = c2.receiver' + ' AND c1.created_on = c2.created_on' + ' AND c2.op = ?' + - ')', [receiver, constants.IDX_UPDATE]); + ')', [receiver, common.constants.IDX_UPDATE]); this.getValidLinksFrom = (issuer) => that.query('SELECT * FROM ' + that.table + ' c1 ' + 'WHERE c1.issuer = ? ' + @@ -107,7 +108,7 @@ function CIndexDAL(driver) { ' AND c1.receiver = c2.receiver' + ' AND c1.created_on = c2.created_on' + ' AND c2.op = ?' + - ')', [issuer, constants.IDX_UPDATE]); + ')', [issuer, common.constants.IDX_UPDATE]); this.existsNonReplayableLink = (issuer, receiver) => co(function*() { const results = yield that.query('SELECT * FROM ' + that.table + ' c1 ' + @@ -119,7 +120,7 @@ function CIndexDAL(driver) { ' AND c1.receiver = c2.receiver' + ' AND c1.created_on = c2.created_on' + ' AND c2.op = ?' + - ')', [issuer, receiver, constants.IDX_UPDATE]); + ')', [issuer, receiver, common.constants.IDX_UPDATE]); return results.length > 0; }); diff --git a/app/lib/dal/sqliteDAL/index/IIndexDAL.js b/app/lib/dal/sqliteDAL/index/IIndexDAL.js index 69458dc9020f7169c19ea719a64be8040846d220..23157689870103645978e3dbd80d604c803dd164 100644 --- a/app/lib/dal/sqliteDAL/index/IIndexDAL.js +++ b/app/lib/dal/sqliteDAL/index/IIndexDAL.js @@ -4,7 +4,7 @@ const co = require('co'); const _ = require('underscore'); -const indexer = require('./../../../dup/indexer'); +const indexer = require('duniter-common').indexer; const AbstractSQLite = require('./../AbstractSQLite'); const AbstractIndex = require('./../AbstractIndex'); @@ -72,6 +72,16 @@ function IIndexDAL(driver) { return filtered.map(toCorrectEntity); }); + this.getMembersPubkeys = () => this.query('SELECT i1.pub ' + + 'FROM i_index i1 ' + + 'WHERE i1.member ' + + 'AND CAST(i1.written_on as int) = (' + + ' SELECT MAX(CAST(i2.written_on as int)) ' + + ' FROM i_index i2 ' + + ' WHERE i1.pub = i2.pub ' + + ' AND i2.member IS NOT NULL' + + ')') + this.getLatestMember = () => co(function*() { const max_wotb_id = (yield that.query('SELECT MAX(wotb_id) as max_wotb_id FROM ' + that.table))[0].max_wotb_id; return entityOrNull('wotb_id', max_wotb_id); diff --git a/app/lib/dal/sqliteDAL/index/MIndexDAL.js b/app/lib/dal/sqliteDAL/index/MIndexDAL.js index de4a07d4745fbafecd4d9c913fbb3f007b3358f1..ab8ae38760ac5421bd7ced5310439470712b9d7c 100644 --- a/app/lib/dal/sqliteDAL/index/MIndexDAL.js +++ b/app/lib/dal/sqliteDAL/index/MIndexDAL.js @@ -3,7 +3,7 @@ */ const co = require('co'); -const indexer = require('./../../../dup/indexer'); +const indexer = require('duniter-common').indexer; const AbstractSQLite = require('./../AbstractSQLite'); const AbstractIndex = require('./../AbstractIndex'); @@ -28,6 +28,7 @@ function MIndexDAL(driver) { 'expired_on', 'revokes_on', 'revoked_on', + 'chainable_on', 'leaving', 'revocation' ]; diff --git a/app/lib/dal/sqliteDAL/index/SIndexDAL.js b/app/lib/dal/sqliteDAL/index/SIndexDAL.js index 6b097eb17728e2c4e52e591b2add6338d34ec0f3..27afb9900b574d17446ffacf7ba2ecc29fae6cf5 100644 --- a/app/lib/dal/sqliteDAL/index/SIndexDAL.js +++ b/app/lib/dal/sqliteDAL/index/SIndexDAL.js @@ -4,9 +4,11 @@ const _ = require('underscore'); const co = require('co'); -const indexer = require('../../../dup/indexer'); +const common = require('duniter-common'); +const indexer = require('duniter-common').indexer; const constants = require('../../../constants'); const AbstractSQLite = require('./../AbstractSQLite'); +const AbstractIndex = require('./../AbstractIndex'); module.exports = SIndexDAL; @@ -15,6 +17,7 @@ function SIndexDAL(driver) { "use strict"; AbstractSQLite.call(this, driver); + AbstractIndex.call(this, driver); const that = this; @@ -102,7 +105,7 @@ function SIndexDAL(driver) { ' AND s2.pos = s1.pos ' + ' AND s2.op = ?' + ') ' + - 'ORDER BY CAST(SUBSTR(written_on, 0, INSTR(written_on, "-")) as number)', [constants.IDX_CREATE, conditionsStr, constants.IDX_UPDATE]); + 'ORDER BY CAST(SUBSTR(written_on, 0, INSTR(written_on, "-")) as number)', [common.constants.IDX_CREATE, conditionsStr, common.constants.IDX_UPDATE]); const sources = potentials.map((src) => { src.type = src.tx ? 'T' : 'D'; return src; @@ -110,23 +113,6 @@ function SIndexDAL(driver) { return _.sortBy(sources, (row) => row.type == 'D' ? 0 : 1); }); - this.findLowerThan = (amount, base) => co(function*() { - const baseConditions = Array.from({ length: (base + 1) }).map((el, index) => { - return '(base = ' + index + ' and amount < ' + (amount * Math.pow(10, base - index)) + ')'; - }).join(' OR '); - const potentials = yield that.query('SELECT * FROM ' + that.table + ' s1 ' + - 'WHERE s1.op = ? ' + - 'AND (' + baseConditions + ') ' + - 'AND NOT EXISTS (' + - ' SELECT * ' + - ' FROM s_index s2 ' + - ' WHERE s2.identifier = s1.identifier ' + - ' AND s2.pos = s1.pos ' + - ' AND s2.op = ?' + - ')', [constants.IDX_CREATE, constants.IDX_UPDATE]); - return potentials; - }); - this.trimConsumedSource = (belowNumber) => co(function*() { const toDelete = yield that.query('SELECT * FROM ' + that.table + ' WHERE consumed AND CAST(written_on as int) < ?', [belowNumber]); const queries = []; diff --git a/app/lib/dup/indexer.js b/app/lib/dup/indexer.js deleted file mode 100644 index afb61730a442309ba8f1467b6af2e83e95dac4ea..0000000000000000000000000000000000000000 --- a/app/lib/dup/indexer.js +++ /dev/null @@ -1,1778 +0,0 @@ -"use strict"; - -const co = require('co'); -const _ = require('underscore'); -const constants = require('../constants'); -const rawer = require('duniter-common').rawer; -const unlock = require('../ucp/txunlock'); -const keyring = require('duniter-common').keyring; -const Block = require('../entity/block'); -const Identity = require('../entity/identity'); -const Certification = require('../entity/certification'); -const Membership = require('../entity/membership'); -const Transaction = require('../entity/transaction'); - -const indexer = module.exports = { - - localIndex: (block, conf) => { - - /******************** - * GENERAL BEHAVIOR - * - * * for each newcomer: 2 indexes (1 iindex CREATE, 1 mindex CREATE) - * * for each comeback: 2 indexes (1 iindex UPDATE, 1 mindex UPDATE) - * * for each renewer: 1 index ( 1 mindex UPDATE) - * * for each leaver: 1 index ( 1 mindex UPDATE) - * * for each revoked: 1 index ( 1 mindex UPDATE) - * * for each excluded: 1 indexes (1 iindex UPDATE) - * - * * for each certification: 1 index (1 cindex CREATE) - * - * * for each tx output: 1 index (1 sindex CREATE) - * * for each tx input: 1 index (1 sindex UPDATE) - */ - - const index = []; - - /*************************** - * IDENTITIES INDEX (IINDEX) - **************************/ - for (const identity of block.identities) { - const idty = Identity.statics.fromInline(identity); - // Computes the hash if not done yet - index.push({ - index: constants.I_INDEX, - op: constants.IDX_CREATE, - uid: idty.uid, - pub: idty.pubkey, - hash: idty.hash, - sig: idty.sig, - created_on: idty.buid, - written_on: [block.number, block.hash].join('-'), - member: true, - wasMember: true, - kick: false, - wid: null // wotb id - }); - } - - /**************************** - * MEMBERSHIPS INDEX (MINDEX) - ***************************/ - // Joiners (newcomer or join back) - for (const inlineMS of block.joiners) { - const ms = Membership.statics.fromInline(inlineMS); - const matchesANewcomer = _.filter(index, (row) => row.index == constants.I_INDEX && row.pub == ms.issuer).length > 0; - if (matchesANewcomer) { - // Newcomer - index.push({ - index: constants.M_INDEX, - op: constants.IDX_CREATE, - pub: ms.issuer, - created_on: [ms.number, ms.fpr].join('-'), - written_on: [block.number, block.hash].join('-'), - type: 'JOIN', - expires_on: conf.msValidity, - revokes_on: conf.msValidity * constants.REVOCATION_FACTOR, - revoked_on: null, - leaving: false - }); - } else { - // Join back - index.push({ - index: constants.M_INDEX, - op: constants.IDX_UPDATE, - pub: ms.issuer, - created_on: [ms.number, ms.fpr].join('-'), - written_on: [block.number, block.hash].join('-'), - type: 'JOIN', - expires_on: conf.msValidity, - revokes_on: conf.msValidity * constants.REVOCATION_FACTOR, - revoked_on: null, - leaving: null - }); - index.push({ - index: constants.I_INDEX, - op: constants.IDX_UPDATE, - uid: null, - pub: ms.issuer, - created_on: null, - written_on: [block.number, block.hash].join('-'), - member: true, - wasMember: null, - kick: null, - wid: null - }); - } - } - // Actives - for (const inlineMS of block.actives) { - const ms = Membership.statics.fromInline(inlineMS); - // Renew - index.push({ - index: constants.M_INDEX, - op: constants.IDX_UPDATE, - pub: ms.issuer, - created_on: [ms.number, ms.fpr].join('-'), - written_on: [block.number, block.hash].join('-'), - type: 'ACTIVE', - expires_on: conf.msValidity, - revokes_on: conf.msValidity * constants.REVOCATION_FACTOR, - revoked_on: null, - leaving: null - }); - } - // Leavers - for (const inlineMS of block.leavers) { - const ms = Membership.statics.fromInline(inlineMS); - index.push({ - index: constants.M_INDEX, - op: constants.IDX_UPDATE, - pub: ms.issuer, - created_on: [ms.number, ms.fpr].join('-'), - written_on: [block.number, block.hash].join('-'), - type: 'LEAVE', - expires_on: null, - revokes_on: null, - revoked_on: null, - leaving: true - }); - } - // Revoked - for (const inlineRevocation of block.revoked) { - const revocation = Identity.statics.revocationFromInline(inlineRevocation); - index.push({ - index: constants.M_INDEX, - op: constants.IDX_UPDATE, - pub: revocation.pubkey, - created_on: [block.number, block.hash].join('-'), - written_on: [block.number, block.hash].join('-'), - expires_on: null, - revokes_on: null, - revoked_on: [block.number, block.hash].join('-'), - revocation: revocation.sig, - leaving: false - }); - } - // Excluded - for (const excluded of block.excluded) { - index.push({ - index: constants.I_INDEX, - op: constants.IDX_UPDATE, - uid: null, - pub: excluded, - created_on: null, - written_on: [block.number, block.hash].join('-'), - member: false, - wasMember: null, - kick: false, - wid: null - }); - } - - /******************************* - * CERTIFICATIONS INDEX (CINDEX) - ******************************/ - for (const inlineCert of block.certifications) { - const cert = Certification.statics.fromInline(inlineCert); - index.push({ - index: constants.C_INDEX, - op: constants.IDX_CREATE, - issuer: cert.pubkey, - receiver: cert.to, - created_on: cert.block_number, - written_on: [block.number, block.hash].join('-'), - sig: cert.sig, - chainable_on: parseInt(block.medianTime) + conf.sigPeriod, - expires_on: conf.sigValidity, - expired_on: 0, - from_wid: null, - to_wid: null - }); - } - - return index.concat(module.exports.localSIndex(block)); - }, - - localSIndex: (block) => { - /******************************* - * SOURCES INDEX (SINDEX) - ******************************/ - const index = []; - if (!block.transactions && block.getTransactions) { - const txs = block.getTransactions(); - block.transactions = []; - for (const tx of txs) { - block.transactions.push({ - version: tx.version, - comment: tx.comment, - issuers: tx.issuers, - signatures: tx.signatures, - inputs: tx.inputs.map((i) => i.raw), - outputs: tx.outputs.map((o) => o.raw) - }); - } - } - for (const obj of block.transactions) { - obj.currency = block.currency; - const tx = new Transaction(obj); - const txObj = tx.getTransaction(); - const txHash = tx.getHash(true); - let k = 0; - for (const input of txObj.inputs) { - index.push({ - index: constants.S_INDEX, - op: constants.IDX_UPDATE, - tx: txHash, - identifier: input.identifier, - pos: input.pos, - created_on: tx.blockstamp, - written_on: [block.number, block.hash].join('-'), - written_time: block.medianTime, - locktime: obj.locktime, - unlock: txObj.unlocks[k], - amount: input.amount, - base: input.base, - conditions: null, - consumed: true, - txObj: txObj - }); - k++; - } - - let i = 0; - for (const output of txObj.outputs) { - index.push({ - index: constants.S_INDEX, - op: constants.IDX_CREATE, - tx: txHash, - identifier: txHash, - pos: i++, - written_on: [block.number, block.hash].join('-'), - written_time: block.medianTime, - locktime: obj.locktime, - amount: output.amount, - base: output.base, - conditions: output.conditions, - consumed: false, - txObj: obj - }); - } - } - return index; - }, - - quickCompleteGlobalScope: (block, conf, bindex, iindex, mindex, cindex, sindex, dal) => co(function*() { - - function range(start, end, property) { - return co(function*() { - let range; - end = Math.min(end, bindex.length); - if (start == 1) { - range = bindex.slice(-end); - } else { - range = bindex.slice(-end, -start + 1); - } - range.reverse(); - if (property) { - // Filter on a particular property - return range.map((b) => b[property]); - } else { - return range; - } - }); - } - - function head(n) { - return co(function*() { - return (yield range(n, n))[0]; - }); - } - - const HEAD = { - version: block.version, - currency: block.currency, - bsize: Block.statics.getLen(block), - hash: Block.statics.getHash(block), - issuer: block.issuer, - time: block.time, - medianTime: block.medianTime, - number: block.number, - powMin: block.powMin, - unitBase: block.unitbase, - membersCount: block.membersCount, - dividend: block.dividend - }; - const HEAD_1 = yield head(1); - - if (HEAD.number == 0) { - HEAD.dividend = conf.ud0; - } - else if (!HEAD.dividend) { - HEAD.dividend = HEAD_1.dividend; - } else { - HEAD.new_dividend = HEAD.dividend; - } - - // BR_G04 - yield indexer.prepareIssuersCount(HEAD, range, HEAD_1); - - // BR_G05 - indexer.prepareIssuersFrame(HEAD, HEAD_1); - - // BR_G06 - indexer.prepareIssuersFrameVar(HEAD, HEAD_1); - - // BR_G07 - yield indexer.prepareAvgBlockSize(HEAD, range); - - // BR_G09 - indexer.prepareDiffNumber(HEAD, HEAD_1, conf); - - // BR_G11 - indexer.prepareUDTime(HEAD, HEAD_1, conf); - - // BR_G15 - indexer.prepareMass(HEAD, HEAD_1); - - // BR_G16 - yield indexer.prepareSpeed(HEAD, head, conf); - - // BR_G19 - yield indexer.prepareIdentitiesAge(iindex, HEAD, HEAD_1, conf, dal); - - // BR_G22 - yield indexer.prepareMembershipsAge(mindex, HEAD, HEAD_1, conf, dal); - - // BR_G37 - yield indexer.prepareCertificationsAge(cindex, HEAD, HEAD_1, conf, dal); - - // BR_G104 - yield indexer.ruleIndexCorrectMembershipExpiryDate(HEAD, mindex, dal); - - // BR_G105 - yield indexer.ruleIndexCorrectCertificationExpiryDate(HEAD, cindex, dal); - - return HEAD; - }), - - completeGlobalScope: (block, conf, index, dal) => co(function*() { - - const iindex = module.exports.iindex(index); - const mindex = module.exports.mindex(index); - const cindex = module.exports.cindex(index); - const sindex = module.exports.sindex(index); - - const range = dal.range; - const head = dal.head; - - const HEAD = { - version: block.version, - bsize: Block.statics.getLen(block), - hash: Block.statics.getHash(block), - issuer: block.issuer, - time: block.time, - powMin: block.powMin - }; - const HEAD_1 = yield head(1); - if (HEAD_1) { - HEAD_1.currency = conf.currency; - } - - // BR_G01 - indexer.prepareNumber(HEAD, HEAD_1); - - // BR_G02 - if (HEAD.number > 0) { - HEAD.previousHash = HEAD_1.hash; - } else { - HEAD.previousHash = null; - } - - // BR_G99 - if (HEAD.number > 0) { - HEAD.currency = HEAD_1.currency; - } else { - HEAD.currency = null; - } - - // BR_G03 - if (HEAD.number > 0) { - HEAD.previousIssuer = HEAD_1.issuer; - } else { - HEAD.previousIssuer = null; - } - - // BR_G03 - if (HEAD.number > 0) { - HEAD.issuerIsMember = reduce(yield dal.iindexDAL.reducable(HEAD.issuer)).member; - } else { - HEAD.issuerIsMember = reduce(_.where(iindex, { pub: HEAD.issuer })).member; - } - - // BR_G04 - yield indexer.prepareIssuersCount(HEAD, range, HEAD_1); - - // BR_G05 - indexer.prepareIssuersFrame(HEAD, HEAD_1); - - // BR_G06 - indexer.prepareIssuersFrameVar(HEAD, HEAD_1); - - // BR_G07 - yield indexer.prepareAvgBlockSize(HEAD, range); - - // BR_G08 - if (HEAD.number > 0) { - HEAD.medianTime = Math.max(HEAD_1.medianTime, average(yield range(1, Math.min(conf.medianTimeBlocks, HEAD.number), 'time'))); - } else { - HEAD.medianTime = HEAD.time; - } - - // BR_G09 - indexer.prepareDiffNumber(HEAD, HEAD_1, conf); - - // BR_G10 - if (HEAD.number == 0) { - HEAD.membersCount = count(_.filter(iindex, (entry) => entry.member === true)); - } else { - HEAD.membersCount = HEAD_1.membersCount - + count(_.filter(iindex, (entry) => entry.member === true)) - - count(_.filter(iindex, (entry) => entry.member === false)); - } - - // BR_G11 - indexer.prepareUDTime(HEAD, HEAD_1, conf); - - // BR_G12 - if (HEAD.number == 0) { - HEAD.unitBase = 0; - } else { - HEAD.unitBase = HEAD_1.unitBase; - } - - // BR_G13 - indexer.prepareDividend(HEAD, HEAD_1, conf); - - // BR_G14 - indexer.prepareUnitBase(HEAD, HEAD_1, conf); - - // BR_G15 - indexer.prepareMass(HEAD, HEAD_1); - - // BR_G16 - yield indexer.prepareSpeed(HEAD, head, conf); - - // BR_G17 - if (HEAD.number > 0) { - - const ratio = constants.POW_DIFFICULTY_RANGE_RATIO; - const maxGenTime = Math.ceil(conf.avgGenTime * ratio); - const minGenTime = Math.floor(conf.avgGenTime / ratio); - const minSpeed = 1 / maxGenTime; - const maxSpeed = 1 / minGenTime; - - if (HEAD.diffNumber != HEAD_1.diffNumber && HEAD.speed >= maxSpeed && (HEAD_1.powMin + 2) % 16 == 0) { - HEAD.powMin = HEAD_1.powMin + 2; - } else if (HEAD.diffNumber != HEAD_1.diffNumber && HEAD.speed >= maxSpeed) { - HEAD.powMin = HEAD_1.powMin + 1; - } else if (HEAD.diffNumber != HEAD_1.diffNumber && HEAD.speed <= minSpeed && HEAD_1.powMin % 16 == 0) { - HEAD.powMin = Math.max(0, HEAD_1.powMin - 2); - } else if (HEAD.diffNumber != HEAD_1.diffNumber && HEAD.speed <= minSpeed) { - HEAD.powMin = Math.max(0, HEAD_1.powMin - 1); - } else { - HEAD.powMin = HEAD_1.powMin; - } - } - - // BR_G18 - yield indexer.preparePersonalizedPoW(HEAD, HEAD_1, range, conf); - - // BR_G19 - yield indexer.prepareIdentitiesAge(iindex, HEAD, HEAD_1, conf, dal); - - // BR_G20 - yield iindex.map((ENTRY) => co(function*() { - if (ENTRY.op == constants.IDX_CREATE) { - ENTRY.uidUnique = count(yield dal.iindexDAL.sqlFind({ uid: ENTRY.uid })) == 0; - } else { - ENTRY.uidUnique = true; - } - })); - - // BR_G21 - yield iindex.map((ENTRY) => co(function*() { - if (ENTRY.op == constants.IDX_CREATE) { - ENTRY.pubUnique = count(yield dal.iindexDAL.sqlFind({pub: ENTRY.pub})) == 0; - } else { - ENTRY.pubUnique = true; - } - })); - - // BR_G33 - yield iindex.map((ENTRY) => co(function*() { - if (ENTRY.member !== false) { - ENTRY.excludedIsMember = true; - } else { - ENTRY.excludedIsMember = reduce(yield dal.iindexDAL.reducable(ENTRY.pub)).member; - } - })); - - // BR_G34 - yield mindex.map((ENTRY) => co(function*() { - ENTRY.isBeingRevoked = !!ENTRY.revoked_on; - })); - - // BR_G35 - yield iindex.map((ENTRY) => co(function*() { - ENTRY.isBeingKicked = ENTRY.member === false; - })); - - // BR_G36 - yield iindex.map((ENTRY) => co(function*() { - const isMarkedAsToKick = reduce(yield dal.iindexDAL.reducable(ENTRY.pub)).kick; - const isBeingRevoked = count(_.filter(mindex, (m) => m.isBeingRevoked && m.pub == ENTRY.pub)) == 1; - ENTRY.hasToBeExcluded = isMarkedAsToKick || isBeingRevoked; - })); - - // BR_G22 - yield indexer.prepareMembershipsAge(mindex, HEAD, HEAD_1, conf, dal); - - // BR_G23 - yield mindex.map((ENTRY) => co(function*() { - if (!ENTRY.revoked_on) { - const created_on = reduce(yield dal.mindexDAL.reducable(ENTRY.pub)).created_on; - if (created_on != null) { - ENTRY.numberFollowing = number(ENTRY.created_on) > number(created_on); - } else { - ENTRY.numberFollowing = true; // Follows nothing - } - } else { - ENTRY.numberFollowing = true; - } - })); - - // BR_G24 - // Global testing, because of wotb - const oneIsOutdistanced = yield checkPeopleAreNotOudistanced( - _.filter(mindex, (entry) => !entry.revoked_on).map((entry) => entry.pub), - cindex.reduce((newLinks, c) => { - newLinks[c.receiver] = newLinks[c.receiver] || []; - newLinks[c.receiver].push(c.issuer); - return newLinks; - }, {}), - // Newcomers - _.where(iindex, { op: constants.IDX_CREATE }).map((entry) => entry.pub), - conf, - dal - ); - mindex.map((ENTRY) => { - if (ENTRY.expires_on) { - ENTRY.distanceOK = !oneIsOutdistanced; - } else { - ENTRY.distanceOK = true; - } - }); - - // BR_G25 - yield mindex.map((ENTRY) => co(function*() { - ENTRY.onRevoked = reduce(yield dal.mindexDAL.reducable(ENTRY.pub)).revoked_on != null; - })); - - // BR_G26 - yield _.filter(mindex, (entry) => entry.op == constants.IDX_UPDATE && entry.expired_on === 0).map((ENTRY) => co(function*() { - ENTRY.joinsTwice = reduce(yield dal.iindexDAL.reducable(ENTRY.pub)).member == true; - })); - - // BR_G27 - yield mindex.map((ENTRY) => co(function*() { - if (ENTRY.type == 'JOIN' || ENTRY.type == 'ACTIVE') { - const existing = count(yield dal.cindexDAL.sqlFind({ receiver: ENTRY.pub, expired_on: 0 })); - const pending = count(_.filter(cindex, (c) => c.receiver == ENTRY.pub && c.expired_on == 0)); - ENTRY.enoughCerts = (existing + pending) >= conf.sigQty; - } else { - ENTRY.enoughCerts = true; - } - })); - - // BR_G28 - yield mindex.map((ENTRY) => co(function*() { - if (ENTRY.type == 'LEAVE') { - ENTRY.leaverIsMember = reduce(yield dal.iindexDAL.reducable(ENTRY.pub)).member; - } else { - ENTRY.leaverIsMember = true; - } - })); - - // BR_G29 - yield mindex.map((ENTRY) => co(function*() { - if (ENTRY.type == 'ACTIVE') { - const reducable = yield dal.iindexDAL.reducable(ENTRY.pub); - ENTRY.activeIsMember = reduce(reducable).member; - } else { - ENTRY.activeIsMember = true; - } - })); - - // BR_G30 - yield mindex.map((ENTRY) => co(function*() { - if (!ENTRY.revoked_on) { - ENTRY.revokedIsMember = true; - } else { - ENTRY.revokedIsMember = reduce(yield dal.iindexDAL.reducable(ENTRY.pub)).member; - } - })); - - // BR_G31 - yield mindex.map((ENTRY) => co(function*() { - if (!ENTRY.revoked_on) { - ENTRY.alreadyRevoked = false; - } else { - ENTRY.alreadyRevoked = reduce(yield dal.mindexDAL.reducable(ENTRY.pub)).revoked_on; - } - })); - - // BR_G32 - yield mindex.map((ENTRY) => co(function*() { - if (!ENTRY.revoked_on) { - ENTRY.revocationSigOK = true; - } else { - ENTRY.revocationSigOK = yield sigCheckRevoke(ENTRY, dal, block.currency); - } - })); - - // BR_G37 - yield indexer.prepareCertificationsAge(cindex, HEAD, HEAD_1, conf, dal); - - // BR_G38 - if (HEAD.number > 0) { - yield cindex.map((ENTRY) => co(function*() { - const rows = yield dal.cindexDAL.sqlFind({ issuer: ENTRY.issuer, chainable_on: { $gt: HEAD_1.medianTime }}); - ENTRY.unchainables = count(rows); - })); - } - - // BR_G39 - yield cindex.map((ENTRY) => co(function*() { - ENTRY.stock = count(yield dal.cindexDAL.getValidLinksFrom(ENTRY.issuer)); - })); - - // BR_G40 - yield cindex.map((ENTRY) => co(function*() { - ENTRY.fromMember = reduce(yield dal.iindexDAL.reducable(ENTRY.issuer)).member; - })); - - // BR_G41 - yield cindex.map((ENTRY) => co(function*() { - ENTRY.toMember = reduce(yield dal.iindexDAL.reducable(ENTRY.receiver)).member; - })); - - // BR_G42 - yield cindex.map((ENTRY) => co(function*() { - ENTRY.toNewcomer = count(_.where(iindex, { member: true, pub: ENTRY.receiver })) > 0; - })); - - // BR_G43 - yield cindex.map((ENTRY) => co(function*() { - ENTRY.toLeaver = reduce(yield dal.mindexDAL.reducable(ENTRY.pub)).leaving; - })); - - // BR_G44 - yield cindex.map((ENTRY) => co(function*() { - const reducable = yield dal.cindexDAL.sqlFind({ issuer: ENTRY.issuer, receiver: ENTRY.receiver }); - ENTRY.isReplay = count(reducable) > 0 && reduce(reducable).expired_on === 0; - })); - - // BR_G45 - yield cindex.map((ENTRY) => co(function*() { - ENTRY.sigOK = checkCertificationIsValid(block, ENTRY, (pub) => { - let localInlineIdty = block.getInlineIdentity(pub); - if (localInlineIdty) { - return Identity.statics.fromInline(localInlineIdty); - } - return dal.getWrittenIdtyByPubkey(pub); - }, conf, dal); - })); - - // BR_G102 - yield _.where(sindex, { op: constants.IDX_UPDATE }).map((ENTRY) => co(function*() { - if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { - ENTRY.age = 0; - } else { - let ref = yield dal.getBlockByBlockstamp(ENTRY.created_on); - if (ref && blockstamp(ref.number, ref.hash) == ENTRY.created_on) { - ENTRY.age = HEAD_1.medianTime - ref.medianTime; - } else { - ENTRY.age = constants.TX_WINDOW + 1; - } - } - })); - - // BR_G46 - yield _.where(sindex, { op: constants.IDX_UPDATE }).map((ENTRY) => co(function*() { - const reducable = yield dal.sindexDAL.sqlFind({ - identifier: ENTRY.identifier, - pos: ENTRY.pos, - amount: ENTRY.amount, - base: ENTRY.base - }); - ENTRY.conditions = reduce(reducable).conditions; // We valuate the input conditions, so we can map these records to a same account - ENTRY.available = reduce(reducable).consumed === false; - })); - - // BR_G47 - yield _.where(sindex, { op: constants.IDX_UPDATE }).map((ENTRY) => co(function*() { - let source = _.filter(sindex, (src) => src.identifier == ENTRY.identifier && src.pos == ENTRY.pos && src.conditions && src.op === constants.IDX_CREATE)[0]; - if (!source) { - const reducable = yield dal.sindexDAL.sqlFind({ - identifier: ENTRY.identifier, - pos: ENTRY.pos, - amount: ENTRY.amount, - base: ENTRY.base - }); - source = reduce(reducable); - } - ENTRY.conditions = source.conditions; - ENTRY.isLocked = !txSourceUnlock(ENTRY, source, HEAD); - })); - - // BR_G48 - yield _.where(sindex, { op: constants.IDX_UPDATE }).map((ENTRY) => co(function*() { - ENTRY.isTimeLocked = ENTRY.written_time - reduce(yield dal.sindexDAL.sqlFind({ - identifier: ENTRY.identifier, - pos: ENTRY.pos, - amount: ENTRY.amount, - base: ENTRY.base - })).written_time < ENTRY.locktime; - })); - - return HEAD; - }), - - // BR_G01 - prepareNumber: (HEAD, HEAD_1) => { - if (HEAD_1) { - HEAD.number = HEAD_1.number + 1; - } else { - HEAD.number = 0; - } - }, - - // BR_G04 - prepareIssuersCount: (HEAD, range, HEAD_1) => co(function*() { - if (HEAD.number == 0) { - HEAD.issuersCount = 0; - } else { - HEAD.issuersCount = count(uniq(yield range(1, HEAD_1.issuersFrame, 'issuer'))); - } - }), - - // BR_G05 - prepareIssuersFrame: (HEAD, HEAD_1) => { - if (HEAD.number == 0) { - HEAD.issuersFrame = 1; - } else if (HEAD_1.issuersFrameVar > 0) { - HEAD.issuersFrame = HEAD_1.issuersFrame + 1 - } else if (HEAD_1.issuersFrameVar < 0) { - HEAD.issuersFrame = HEAD_1.issuersFrame - 1 - } else { - HEAD.issuersFrame = HEAD_1.issuersFrame - } - }, - - // BR_G06 - prepareIssuersFrameVar: (HEAD, HEAD_1) => { - if (HEAD.number == 0) { - HEAD.issuersFrameVar = 0; - } else { - const issuersVar = (HEAD.issuersCount - HEAD_1.issuersCount); - if (HEAD_1.issuersFrameVar > 0) { - HEAD.issuersFrameVar = HEAD_1.issuersFrameVar + 5 * issuersVar - 1; - } else if (HEAD_1.issuersFrameVar < 0) { - HEAD.issuersFrameVar = HEAD_1.issuersFrameVar + 5 * issuersVar + 1; - } else { - HEAD.issuersFrameVar = HEAD_1.issuersFrameVar + 5 * issuersVar; - } - } - }, - - // BR_G07 - prepareAvgBlockSize: (HEAD, range) => co(function*() { - HEAD.avgBlockSize = average(yield range(1, HEAD.issuersCount, 'bsize')); - }), - - // BR_G09 - prepareDiffNumber: (HEAD, HEAD_1, conf) => { - if (HEAD.number == 0) { - HEAD.diffNumber = HEAD.number + conf.dtDiffEval; - } else if (HEAD_1.diffNumber <= HEAD.number) { - HEAD.diffNumber = HEAD_1.diffNumber + conf.dtDiffEval; - } else { - HEAD.diffNumber = HEAD_1.diffNumber; - } - }, - - // BR_G11 - prepareUDTime: (HEAD, HEAD_1, conf) => { - // UD Production - if (HEAD.number == 0) { - HEAD.udTime = conf.udTime0; - } else if (HEAD_1.udTime <= HEAD.medianTime) { - HEAD.udTime = HEAD_1.udTime + conf.dt; - } else { - HEAD.udTime = HEAD_1.udTime; - } - // UD Reevaluation - if (HEAD.number == 0) { - HEAD.udReevalTime = conf.udReevalTime0; - } else if (HEAD_1.udReevalTime <= HEAD.medianTime) { - HEAD.udReevalTime = HEAD_1.udReevalTime + conf.dtReeval; - } else { - HEAD.udReevalTime = HEAD_1.udReevalTime; - } - }, - - // BR_G13 - prepareDividend: (HEAD, HEAD_1, conf) => { - // UD re-evaluation - if (HEAD.number == 0) { - HEAD.dividend = conf.ud0; - } else if (HEAD.udReevalTime != HEAD_1.udReevalTime) { - // DUG - const previousUB = HEAD_1.unitBase; - HEAD.dividend = Math.ceil(HEAD_1.dividend + Math.pow(conf.c, 2) * Math.ceil(HEAD_1.massReeval / Math.pow(10, previousUB)) / HEAD.membersCount / (conf.dtReeval / conf.dt)); - } else { - HEAD.dividend = HEAD_1.dividend; - } - // UD creation - if (HEAD.number == 0) { - HEAD.new_dividend = null; - } else if (HEAD.udTime != HEAD_1.udTime) { - HEAD.new_dividend = HEAD.dividend; - } else { - HEAD.new_dividend = null; - } - }, - - // BR_G14 - prepareUnitBase: (HEAD) => { - if (HEAD.dividend >= Math.pow(10, constants.NB_DIGITS_UD)) { - HEAD.dividend = Math.ceil(HEAD.dividend / 10); - HEAD.new_dividend = HEAD.dividend; - HEAD.unitBase = HEAD.unitBase + 1; - } - }, - - // BR_G15 - prepareMass: (HEAD, HEAD_1) => { - // Mass - if (HEAD.number == 0) { - HEAD.mass = 0; - } - else if (HEAD.udTime != HEAD_1.udTime) { - HEAD.mass = HEAD_1.mass + HEAD.dividend * Math.pow(10, HEAD.unitBase) * HEAD.membersCount; - } else { - HEAD.mass = HEAD_1.mass; - } - // Mass on re-evaluation - if (HEAD.number == 0) { - HEAD.massReeval = 0; - } - else if (HEAD.udReevalTime != HEAD_1.udReevalTime) { - HEAD.massReeval = HEAD_1.mass; - } else { - HEAD.massReeval = HEAD_1.massReeval; - } - }, - - // BR_G16 - prepareSpeed: (HEAD, head, conf) => co(function*() { - if (HEAD.number == 0) { - HEAD.speed = 0; - } else { - const quantity = Math.min(conf.dtDiffEval, HEAD.number); - const elapsed = (HEAD.medianTime - (yield head(quantity)).medianTime); - if (!elapsed) { - HEAD.speed = 100; - } else { - HEAD.speed = quantity / elapsed; - } - } - }), - - // BR_G18 - preparePersonalizedPoW: (HEAD, HEAD_1, range, conf) => co(function*() { - let nbPersonalBlocksInFrame, medianOfBlocksInFrame, blocksOfIssuer; - let nbPreviousIssuers = 0, nbBlocksSince = 0; - if (HEAD.number == 0) { - nbPersonalBlocksInFrame = 0; - medianOfBlocksInFrame = 1; - } else { - const blocksInFrame = _.filter(yield range(1, HEAD_1.issuersFrame), (b) => b.number <= HEAD_1.number); - const issuersInFrame = blocksInFrame.map((b) => b.issuer); - blocksOfIssuer = _.filter(blocksInFrame, (entry) => entry.issuer == HEAD.issuer); - nbPersonalBlocksInFrame = count(blocksOfIssuer); - const blocksPerIssuerInFrame = uniq(issuersInFrame).map((issuer) => count(_.where(blocksInFrame, { issuer }))); - medianOfBlocksInFrame = Math.max(1, median(blocksPerIssuerInFrame)); - if (nbPersonalBlocksInFrame == 0) { - nbPreviousIssuers = 0; - nbBlocksSince = 0; - } else { - const last = blocksOfIssuer[0]; - nbPreviousIssuers = last.issuersCount; - nbBlocksSince = HEAD_1.number - last.number; - } - } - - // V0.6 Hardness - const PERSONAL_EXCESS = Math.max(0, ( (nbPersonalBlocksInFrame + 1) / medianOfBlocksInFrame) - 1); - const PERSONAL_HANDICAP = Math.floor(Math.log(1 + PERSONAL_EXCESS) / Math.log(1.189)); - HEAD.issuerDiff = Math.max(HEAD.powMin, HEAD.powMin * Math.floor(conf.percentRot * nbPreviousIssuers / (1 + nbBlocksSince))) + PERSONAL_HANDICAP; - if ((HEAD.issuerDiff + 1) % 16 == 0) { - HEAD.issuerDiff += 1; - } - - HEAD.powRemainder = HEAD.issuerDiff % 16; - HEAD.powZeros = (HEAD.issuerDiff - HEAD.powRemainder) / 16; - }), - - // BR_G19 - prepareIdentitiesAge: (iindex, HEAD, HEAD_1, conf, dal) => co(function*() { - yield _.where(iindex, { op: constants.IDX_CREATE }).map((ENTRY) => co(function*() { - if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { - ENTRY.age = 0; - } else { - let ref = yield dal.getBlockByBlockstamp(ENTRY.created_on); - if (ref && blockstamp(ref.number, ref.hash) == ENTRY.created_on) { - ENTRY.age = HEAD_1.medianTime - ref.medianTime; - } else { - ENTRY.age = conf.idtyWindow + 1; - } - } - })); - }), - - // BR_G22 - prepareMembershipsAge: (mindex, HEAD, HEAD_1, conf, dal) => co(function*() { - yield _.filter(mindex, (entry) => !entry.revoked_on).map((ENTRY) => co(function*() { - if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { - ENTRY.age = 0; - } else { - let ref = yield dal.getBlockByBlockstamp(ENTRY.created_on); - if (ref && blockstamp(ref.number, ref.hash) == ENTRY.created_on) { - ENTRY.age = HEAD_1.medianTime - ref.medianTime; - } else { - ENTRY.age = conf.msWindow + 1; - } - } - })); - }), - - // BR_G37 - prepareCertificationsAge: (cindex, HEAD, HEAD_1, conf, dal) => co(function*() { - yield cindex.map((ENTRY) => co(function*() { - if (HEAD.number == 0) { - ENTRY.age = 0; - } else { - let ref = yield dal.getBlock(number(ENTRY.created_on)); - if (ref) { - ENTRY.age = HEAD_1.medianTime - ref.medianTime; - } else { - ENTRY.age = conf.sigWindow + 1; - } - } - })); - }), - - // BR_G49 - ruleVersion: (HEAD, HEAD_1) => { - if (HEAD.number > 0) { - return HEAD.version == HEAD_1.version || HEAD.version == HEAD_1.version + 1; - } - return true; - }, - - // BR_G50 - ruleBlockSize: (HEAD) => { - if (HEAD.number > 0) { - return HEAD.bsize < indexer.DUP_HELPERS.getMaxBlockSize(HEAD); - } - return true; - }, - - // BR_G98 - ruleCurrency: (block, HEAD) => { - if (HEAD.number > 0) { - return block.currency === HEAD.currency; - } - return true; - }, - - // BR_G51 - ruleNumber: (block, HEAD) => block.number == HEAD.number, - - // BR_G52 - rulePreviousHash: (block, HEAD) => block.previousHash == HEAD.previousHash || (!block.previousHash && !HEAD.previousHash), - - // BR_G53 - rulePreviousIssuer: (block, HEAD) => block.previousIssuer == HEAD.previousIssuer || (!block.previousIssuer && !HEAD.previousIssuer), - - // BR_G101 - ruleIssuerIsMember: (HEAD) => HEAD.issuerIsMember == true, - - // BR_G54 - ruleIssuersCount: (block, HEAD) => block.issuersCount == HEAD.issuersCount, - - // BR_G55 - ruleIssuersFrame: (block, HEAD) => block.issuersFrame == HEAD.issuersFrame, - - // BR_G56 - ruleIssuersFrameVar: (block, HEAD) => block.issuersFrameVar == HEAD.issuersFrameVar, - - // BR_G57 - ruleMedianTime: (block, HEAD) => block.medianTime == HEAD.medianTime, - - // BR_G58 - ruleDividend: (block, HEAD) => block.dividend == HEAD.new_dividend, - - // BR_G59 - ruleUnitBase: (block, HEAD) => block.unitbase == HEAD.unitBase, - - // BR_G60 - ruleMembersCount: (block, HEAD) => block.membersCount == HEAD.membersCount, - - // BR_G61 - rulePowMin: (block, HEAD) => { - if (HEAD.number > 0) { - return block.powMin == HEAD.powMin; - } - }, - - // BR_G62 - ruleProofOfWork: (HEAD) => { - // Compute exactly how much zeros are required for this block's issuer - const remainder = HEAD.powRemainder; - const nbZerosReq = HEAD.powZeros; - const highMark = constants.PROOF_OF_WORK.UPPER_BOUND[remainder]; - const powRegexp = new RegExp('^0{' + nbZerosReq + '}' + '[0-' + highMark + ']'); - try { - if (!HEAD.hash.match(powRegexp)) { - const givenZeros = Math.max(0, Math.min(nbZerosReq, HEAD.hash.match(/^0*/)[0].length)); - const c = HEAD.hash.substr(givenZeros, 1); - throw Error('Wrong proof-of-work level: given ' + givenZeros + ' zeros and \'' + c + '\', required was ' + nbZerosReq + ' zeros and an hexa char between [0-' + highMark + ']'); - } - return true; - } catch (e) { - return false; - } - }, - - // BR_G63 - ruleIdentityWritability: (iindex, conf) => { - for (const ENTRY of iindex) { - if (ENTRY.age > conf.idtyWindow) return false; - } - }, - - // BR_G64 - ruleMembershipWritability: (mindex, conf) => { - for (const ENTRY of mindex) { - if (ENTRY.age > conf.msWindow) return false; - } - }, - - // BR_G65 - ruleCertificationWritability: (cindex, conf) => { - for (const ENTRY of cindex) { - if (ENTRY.age > conf.sigWindow) return false; - } - }, - - // BR_G66 - ruleCertificationStock: (cindex, conf) => { - for (const ENTRY of cindex) { - if (ENTRY.stock > conf.sigStock) return false; - } - }, - - // BR_G67 - ruleCertificationPeriod: (cindex) => { - for (const ENTRY of cindex) { - if (ENTRY.unchainables > 0) return false; - } - }, - - // BR_G68 - ruleCertificationFromMember: (HEAD, cindex) => { - if (HEAD.number > 0) { - for (const ENTRY of cindex) { - if (!ENTRY.fromMember) return false; - } - } - }, - - // BR_G69 - ruleCertificationToMemberOrNewcomer: (cindex) => { - for (const ENTRY of cindex) { - if (!ENTRY.toMember && !ENTRY.toNewcomer) return false; - } - }, - - // BR_G70 - ruleCertificationToLeaver: (cindex) => { - for (const ENTRY of cindex) { - if (ENTRY.toLeaver) return false; - } - }, - - // BR_G71 - ruleCertificationReplay: (cindex) => { - for (const ENTRY of cindex) { - if (ENTRY.isReplay) return false; - } - }, - - // BR_G72 - ruleCertificationSignature: (cindex) => { - for (const ENTRY of cindex) { - if (!ENTRY.sigOK) return false; - } - }, - - // BR_G73 - ruleIdentityUIDUnicity: (iindex) => { - for (const ENTRY of iindex) { - if (!ENTRY.uidUnique) return false; - } - }, - - // BR_G74 - ruleIdentityPubkeyUnicity: (iindex) => { - for (const ENTRY of iindex) { - if (!ENTRY.pubUnique) return false; - } - }, - - // BR_G75 - ruleMembershipSuccession: (mindex) => { - for (const ENTRY of mindex) { - if (!ENTRY.numberFollowing) return false; - } - }, - - // BR_G76 - ruleMembershipDistance: (HEAD, mindex) => { - for (const ENTRY of mindex) { - if (HEAD.currency == 'gtest' - && !ENTRY.distanceOK - // && HEAD.number != 8450 - // && HEAD.number != 9775 - // && HEAD.number != 10893 - // && HEAD.number != 11090 - // && HEAD.number != 11263 - // && HEAD.number != 11392 - && HEAD.number < 11512) { - return false; - } - else if (HEAD.currency != 'gtest' && !ENTRY.distanceOK) { - return false; - } - } - }, - - // BR_G77 - ruleMembershipOnRevoked: (mindex) => { - for (const ENTRY of mindex) { - if (ENTRY.onRevoked) return false; - } - }, - - // BR_G78 - ruleMembershipJoinsTwice: (mindex) => { - for (const ENTRY of mindex) { - if (ENTRY.joinsTwice) return false; - } - }, - - // BR_G79 - ruleMembershipEnoughCerts: (mindex) => { - for (const ENTRY of mindex) { - if (!ENTRY.enoughCerts) return false; - } - }, - - // BR_G80 - ruleMembershipLeaverIsMember: (mindex) => { - for (const ENTRY of mindex) { - if (!ENTRY.leaverIsMember) return false; - } - }, - - // BR_G81 - ruleMembershipActiveIsMember: (mindex) => { - for (const ENTRY of mindex) { - if (!ENTRY.activeIsMember) return false; - } - }, - - // BR_G82 - ruleMembershipRevokedIsMember: (mindex) => { - for (const ENTRY of mindex) { - if (!ENTRY.revokedIsMember) return false; - } - }, - - // BR_G83 - ruleMembershipRevokedSingleton: (mindex) => { - for (const ENTRY of mindex) { - if (ENTRY.alreadyRevoked) return false; - } - }, - - // BR_G84 - ruleMembershipRevocationSignature: (mindex) => { - for (const ENTRY of mindex) { - if (!ENTRY.revocationSigOK) return false; - } - }, - - // BR_G85 - ruleMembershipExcludedIsMember: (iindex) => { - for (const ENTRY of iindex) { - if (!ENTRY.excludedIsMember) return false; - } - }, - - // BR_G86 - ruleToBeKickedArePresent: (iindex, dal) => co(function*() { - const toBeKicked = yield dal.iindexDAL.getToBeKickedPubkeys(); - for (const toKick of toBeKicked) { - if (count(_.where(iindex, { pub: toKick, isBeingKicked: true })) !== 1) { - return false; - } - } - const beingKicked = _.filter(iindex, (i) => i.member === false); - for (const entry of beingKicked) { - if (!entry.hasToBeExcluded) { - return false; - } - } - }), - - // BR_G103 - ruleTxWritability: (sindex) => { - for (const ENTRY of sindex) { - if (ENTRY.age > constants.TX_WINDOW) return false; - } - }, - - // BR_G87 - ruleInputIsAvailable: (sindex) => { - const inputs = _.where(sindex, { op: constants.IDX_UPDATE }); - for (const ENTRY of inputs) { - if (!ENTRY.available) { - return false; - } - } - }, - - // BR_G88 - ruleInputIsUnlocked: (sindex) => { - const inputs = _.where(sindex, { op: constants.IDX_UPDATE }); - for (const ENTRY of inputs) { - if (ENTRY.isLocked) { - return false; - } - } - }, - - // BR_G89 - ruleInputIsTimeUnlocked: (sindex) => { - const inputs = _.where(sindex, { op: constants.IDX_UPDATE }); - for (const ENTRY of inputs) { - if (ENTRY.isTimeLocked) { - return false; - } - } - }, - - // BR_G90 - ruleOutputBase: (sindex, HEAD_1) => { - const inputs = _.where(sindex, { op: constants.IDX_CREATE }); - for (const ENTRY of inputs) { - if (ENTRY.unitBase > HEAD_1.unitBase) { - return false; - } - } - }, - - // BR_G91 - ruleIndexGenDividend: (HEAD, dal) => co(function*() { - const dividends = []; - if (HEAD.new_dividend) { - const potentials = reduceBy(yield dal.iindexDAL.sqlFind({ member: true }), ['pub']); - for (const potential of potentials) { - const MEMBER = reduce(yield dal.iindexDAL.reducable(potential.pub)); - if (MEMBER.member) { - dividends.push({ - op: 'CREATE', - identifier: MEMBER.pub, - pos: HEAD.number, - written_on: [HEAD.number, HEAD.hash].join('-'), - written_time: HEAD.medianTime, - amount: HEAD.dividend, - base: HEAD.unitBase, - locktime: null, - conditions: 'SIG(' + MEMBER.pub + ')', - consumed: false - }); - } - } - } - return dividends; - }), - - // BR_G106 - ruleIndexGarbageSmallAccounts: (HEAD, sindex, dal) => co(function*() { - const garbages = []; - let potentialSources = yield dal.sindexDAL.findLowerThan(constants.ACCOUNT_MINIMUM_CURRENT_BASED_AMOUNT, HEAD.unitBase); - let localSources = _.where(sindex, { op: constants.IDX_CREATE }); - potentialSources = potentialSources.concat(localSources); - const accounts = Object.keys(potentialSources.reduce((acc, src) => { - acc[src.conditions] = true; - return acc; - }, {})); - const accountsBalance = yield accounts.reduce((map, acc) => { - map[acc] = dal.sindexDAL.getAvailableForConditions(acc); - return map; - }, {}); - for (const account of accounts) { - let sources = yield accountsBalance[account]; - const localAccountEntries = _.filter(sindex, (src) => src.conditions == account); - const balance = sources.concat(localAccountEntries).reduce((sum, src) => { - if (src.op === 'CREATE') { - return sum + src.amount * Math.pow(10, src.base); - } else { - return sum - src.amount * Math.pow(10, src.base); - } - }, 0) - if (balance < constants.ACCOUNT_MINIMUM_CURRENT_BASED_AMOUNT * Math.pow(10, HEAD.unitBase)) { - for (const src of sources.concat(localAccountEntries)) { - const sourceBeingConsumed = _.filter(sindex, (entry) => entry.op === 'UPDATE' && entry.identifier == src.identifier && entry.pos == src.pos).length > 0; - if (!sourceBeingConsumed) { - garbages.push({ - op: 'UPDATE', - tx: src.tx, - identifier: src.identifier, - pos: src.pos, - amount: src.amount, - base: src.base, - written_on: [HEAD.number, HEAD.hash].join('-'), - written_time: HEAD.medianTime, - conditions: src.conditions, - consumed: true // It is now consumed - }); - } - } - } - } - return garbages; - }), - - // BR_G92 - ruleIndexGenCertificationExpiry: (HEAD, dal) => co(function*() { - const expiries = []; - const certs = yield dal.cindexDAL.findExpired(HEAD.medianTime); - for (const CERT of certs) { - expiries.push({ - op: 'UPDATE', - issuer: CERT.issuer, - receiver: CERT.receiver, - created_on: CERT.created_on, - written_on: [HEAD.number, HEAD.hash].join('-'), - expired_on: HEAD.medianTime - }); - } - return expiries; - }), - - // BR_G93 - ruleIndexGenMembershipExpiry: (HEAD, dal) => co(function*() { - const expiries = []; - const memberships = reduceBy(yield dal.mindexDAL.sqlFind({ expires_on: { $lte: HEAD.medianTime } }), ['pub']); - for (const POTENTIAL of memberships) { - const MS = yield dal.mindexDAL.getReducedMS(POTENTIAL.pub); - const hasRenewedSince = MS.expires_on > HEAD.medianTime; - if (!MS.expired_on && !hasRenewedSince) { - expiries.push({ - op: 'UPDATE', - pub: MS.pub, - created_on: MS.created_on, - written_on: [HEAD.number, HEAD.hash].join('-'), - expired_on: HEAD.medianTime - }); - } - } - return expiries; - }), - - // BR_G94 - ruleIndexGenExclusionByMembership: (HEAD, mindex, dal) => co(function*() { - const exclusions = []; - const memberships = _.filter(mindex, (entry) => entry.expired_on); - for (const MS of memberships) { - const idty = yield dal.iindexDAL.getFromPubkey(MS.pub); - if (idty.member) { - exclusions.push({ - op: 'UPDATE', - pub: MS.pub, - written_on: [HEAD.number, HEAD.hash].join('-'), - kick: true - }); - } - } - return exclusions; - }), - - // BR_G95 - ruleIndexGenExclusionByCertificatons: (HEAD, cindex, iindex, conf, dal) => co(function*() { - const exclusions = []; - const expiredCerts = _.filter(cindex, (c) => c.expired_on > 0); - for (const CERT of expiredCerts) { - const just_expired = _.filter(cindex, (c) => c.receiver == CERT.receiver && c.expired_on > 0); - const just_received = _.filter(cindex, (c) => c.receiver == CERT.receiver && c.expired_on == 0); - const non_expired_global = yield dal.cindexDAL.getValidLinksTo(CERT.receiver); - if ((count(non_expired_global) - count(just_expired) + count(just_received)) < conf.sigQty) { - const isInExcluded = _.filter(iindex, (i) => i.member === false && i.pub === CERT.receiver)[0]; - const idty = yield dal.iindexDAL.getFromPubkey(CERT.receiver); - if (!isInExcluded && idty.member) { - exclusions.push({ - op: 'UPDATE', - pub: CERT.receiver, - written_on: [HEAD.number, HEAD.hash].join('-'), - kick: true - }); - } - } - } - return exclusions; - }), - - // BR_G96 - ruleIndexGenImplicitRevocation: (HEAD, dal) => co(function*() { - const revocations = []; - const pending = yield dal.mindexDAL.sqlFind({ revokes_on: { $lte: HEAD.medianTime}, revoked_on: { $null: true } }); - for (const MS of pending) { - const REDUCED = reduce(yield dal.mindexDAL.sqlFind({ pub: MS.pub })); - if (REDUCED.revokes_on <= HEAD.medianTime && !REDUCED.revoked_on) { - revocations.push({ - op: 'UPDATE', - pub: MS.pub, - created_on: REDUCED.created_on, - written_on: [HEAD.number, HEAD.hash].join('-'), - revoked_on: HEAD.medianTime - }); - } - } - return revocations; - }), - - // BR_G104 - ruleIndexCorrectMembershipExpiryDate: (HEAD, mindex, dal) => co(function*() { - for (const MS of mindex) { - if (MS.type == 'JOIN' || MS.type == 'ACTIVE') { - let basedBlock = { medianTime: 0 }; - if (HEAD.number == 0) { - basedBlock = HEAD; - } else { - if (HEAD.currency === 'gtest') { - basedBlock = yield dal.getBlockByBlockstamp(MS.created_on); - } else { - basedBlock = yield dal.getBlockByBlockstamp(MS.created_on); - } - } - MS.expires_on += basedBlock.medianTime; - MS.revokes_on += basedBlock.medianTime; - } - } - }), - - // BR_G105 - ruleIndexCorrectCertificationExpiryDate: (HEAD, cindex, dal) => co(function*() { - for (const CERT of cindex) { - let basedBlock = { medianTime: 0 }; - if (HEAD.number == 0) { - basedBlock = HEAD; - } else { - if (HEAD.currency === 'gtest') { - basedBlock = yield dal.getBlock(CERT.created_on); - } else { - basedBlock = yield dal.getBlock(CERT.created_on); - } - } - CERT.expires_on += basedBlock.medianTime; - } - }), - - iindexCreate: (index) => _(index).filter({ index: constants.I_INDEX, op: constants.IDX_CREATE }), - mindexCreate: (index) => _(index).filter({ index: constants.M_INDEX, op: constants.IDX_CREATE }), - iindex: (index) => _(index).filter({ index: constants.I_INDEX }), - mindex: (index) => _(index).filter({ index: constants.M_INDEX }), - cindex: (index) => _(index).filter({ index: constants.C_INDEX }), - sindex: (index) => _(index).filter({ index: constants.S_INDEX }), - - DUP_HELPERS: { - - reduce: reduce, - reduceBy: reduceBy, - getMaxBlockSize: (HEAD) => Math.max(500, Math.ceil(1.1 * HEAD.avgBlockSize)), - checkPeopleAreNotOudistanced: checkPeopleAreNotOudistanced - } -}; - -function count(range) { - return range.length; -} - -function uniq(range) { - return _.uniq(range); -} - -function average(values) { - // No values => 0 average - if (!values.length) return 0; - // Otherwise, real average - const avg = values.reduce((sum, val) => sum + val, 0) / values.length; - return Math.floor(avg); -} - -function median(values) { - let med = 0; - values.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0)); - const nbValues = values.length; - if (nbValues > 0) { - if (nbValues % 2 === 0) { - // Even number: the median is the average between the 2 central values, ceil rounded. - const firstValue = values[nbValues / 2]; - const secondValue = values[nbValues / 2 - 1]; - med = ((firstValue + secondValue) / 2); - } else { - med = values[(nbValues + 1) / 2 - 1]; - } - } - return med; -} - -function number(blockstamp) { - return parseInt(blockstamp); -} - -function blockstamp(number, hash) { - return [number, hash].join('-'); -} - -function reduce(records) { - return records.reduce((obj, record) => { - const keys = Object.keys(record); - for (const k of keys) { - if (record[k] !== undefined && record[k] !== null) { - obj[k] = record[k]; - } - } - return obj; - }, {}); -} - -function reduceBy(reducables, properties) { - const reduced = reducables.reduce((map, entry) => { - const id = properties.map((prop) => entry[prop]).join('-'); - map[id] = map[id] || []; - map[id].push(entry); - return map; - }, {}); - return Object.values(reduced).map((value) => indexer.DUP_HELPERS.reduce(value)); -} - -function checkPeopleAreNotOudistanced (pubkeys, newLinks, newcomers, conf, dal) { - return co(function *() { - // let wotb = dal.wotb; - let wotb = dal.wotb.memCopy(); - let current = yield dal.getCurrentBlockOrNull(); - let membersCount = current ? current.membersCount : 0; - // TODO: make a temporary copy of the WoT in RAM - // We add temporarily the newcomers to the WoT, to integrate their new links - let nodesCache = newcomers.reduce((map, pubkey) => { - let nodeID = wotb.addNode(); - map[pubkey] = nodeID; - wotb.setEnabled(false, nodeID); // These are not members yet - return map; - }, {}); - // Add temporarily the links to the WoT - let tempLinks = []; - let toKeys = _.keys(newLinks); - for (const toKey of toKeys) { - let toNode = yield getNodeIDfromPubkey(nodesCache, toKey, dal); - for (const fromKey of newLinks[toKey]) { - let fromNode = yield getNodeIDfromPubkey(nodesCache, fromKey, dal); - tempLinks.push({ from: fromNode, to: toNode }); - } - } - wotb.setMaxCert(conf.sigStock + tempLinks.length); - tempLinks.forEach((link) => wotb.addLink(link.from, link.to)); - // Checking distance of each member against them - let error; - for (const pubkey of pubkeys) { - let nodeID = yield getNodeIDfromPubkey(nodesCache, pubkey, dal); - const dSen = Math.ceil(Math.pow(membersCount, 1 / conf.stepMax)); - let isOutdistanced = wotb.isOutdistanced(nodeID, dSen, conf.stepMax, conf.xpercent); - if (isOutdistanced) { - error = Error('Joiner/Active is outdistanced from WoT'); - break; - } - } - // Undo temp links/nodes - tempLinks.forEach((link) => wotb.removeLink(link.from, link.to)); - newcomers.forEach(() => wotb.removeNode()); - wotb.clear(); - return error ? true : false; - }); -} - -function getNodeIDfromPubkey(nodesCache, pubkey, dal) { - return co(function *() { - let toNode = nodesCache[pubkey]; - // Eventually cache the target nodeID - if (toNode === null || toNode === undefined) { - let idty = yield dal.getWrittenIdtyByPubkey(pubkey); - toNode = idty.wotb_id; - nodesCache[pubkey] = toNode; - } - return toNode; - }); -} - -function sigCheckRevoke(entry, dal, currency) { - return co(function*() { - try { - let pubkey = entry.pub, sig = entry.revocation; - let idty = yield dal.getWrittenIdtyByPubkey(pubkey); - if (!idty) { - throw Error("A pubkey who was never a member cannot be revoked"); - } - if (idty.revoked) { - throw Error("A revoked identity cannot be revoked again"); - } - let rawRevocation = rawer.getOfficialRevocation({ - currency: currency, - issuer: idty.pubkey, - uid: idty.uid, - buid: idty.buid, - sig: idty.sig, - revocation: '' - }); - let sigOK = keyring.verify(rawRevocation, sig, pubkey); - if (!sigOK) { - throw Error("Revocation signature must match"); - } - return true; - } catch (e) { - return false; - } - }); -} - - - -function checkCertificationIsValid (block, cert, findIdtyFunc, conf, dal) { - return co(function *() { - if (block.number == 0 && cert.created_on != 0) { - throw Error('Number must be 0 for root block\'s certifications'); - } else { - try { - let basedBlock = { - hash: constants.BLOCK.SPECIAL_HASH - }; - if (block.number != 0) { - try { - basedBlock = yield dal.getBlock(cert.created_on); - } catch (e) { - throw Error('Certification based on an unexisting block'); - } - } - let idty = yield findIdtyFunc(block, cert.to, dal); - let current = block.number == 0 ? null : yield dal.getCurrentBlockOrNull(); - if (!idty) { - throw Error('Identity does not exist for certified'); - } - else if (current && current.medianTime > basedBlock.medianTime + conf.sigValidity) { - throw Error('Certification has expired'); - } - else if (cert.from == idty.pubkey) - throw Error('Rejected certification: certifying its own self-certification has no meaning'); - else { - const buid = [cert.created_on, basedBlock.hash].join('-'); - idty.currency = conf.currency; - const raw = rawer.getOfficialCertification(_.extend(idty, { - idty_issuer: idty.pubkey, - idty_uid: idty.uid, - idty_buid: idty.buid, - idty_sig: idty.sig, - issuer: cert.from, - buid: buid, - sig: '' - })); - const verified = keyring.verify(raw, cert.sig, cert.from); - if (!verified) { - throw Error('Wrong signature for certification'); - } - return true; - } - } catch (e) { - return false; - } - } - }); -} - -function txSourceUnlock(ENTRY, source, HEAD) { - const tx = ENTRY.txObj; - let sigResults = require('../rules/local_rules').HELPERS.getSigResult(tx, 'a'); - let unlocksForCondition = []; - let unlocksMetadata = {}; - let unlockValues = ENTRY.unlock; - if (source.conditions) { - if (unlockValues) { - // Evaluate unlock values - let sp = unlockValues.split(' '); - for (const func of sp) { - let param = func.match(/\((.+)\)/)[1]; - if (func.match(/SIG/)) { - let pubkey = tx.issuers[parseInt(param)]; - if (!pubkey) { - return false; - } - unlocksForCondition.push({ - pubkey: pubkey, - sigOK: sigResults.sigs[pubkey] && sigResults.sigs[pubkey].matching || false - }); - } else { - // XHX - unlocksForCondition.push(param); - } - } - } - - if (source.conditions.match(/CLTV/)) { - unlocksMetadata.currentTime = HEAD.medianTime; - } - - if (source.conditions.match(/CSV/)) { - unlocksMetadata.elapsedTime = HEAD.medianTime - parseInt(source.written_time); - } - - if (unlock(source.conditions, unlocksForCondition, unlocksMetadata)) { - return true; - } - } - return false; -} diff --git a/app/lib/entity/block.js b/app/lib/entity/block.js index 91404fb6313f235b1f4ebd72fa06eeb5e43f0f3e..e8e4a457ba6096ec713005713868d3bc1f49d378 100644 --- a/app/lib/entity/block.js +++ b/app/lib/entity/block.js @@ -1,6 +1,8 @@ "use strict"; const _ = require('underscore'); -const hashf = require('duniter-common').hashf; +const common = require('duniter-common') +const document = common.document; +const hashf = common.hashf; const Transaction = require('./transaction'); module.exports = Block; @@ -52,70 +54,9 @@ function Block(json) { }); this.json = () => { - const json = {}; - [ - "version", - "nonce", - "number", - "powMin", - "time", - "medianTime", - "membersCount", - "monetaryMass", - "unitbase", - "issuersCount", - "issuersFrame", - "issuersFrameVar", - "len" - ].forEach((field) => { - json[field] = parseInt(this[field], 10); - }); - [ - "currency", - "issuer", - "signature", - "hash", - "parameters" - ].forEach((field) => { - json[field] = this[field] || ""; - }); - [ - "previousHash", - "previousIssuer", - "inner_hash" - ].forEach((field) => { - json[field] = this[field] || null; - }); - [ - "dividend" - ].forEach((field) => { - json[field] = parseInt(this[field]) || null; - }); - [ - "identities", - "joiners", - "actives", - "leavers", - "revoked", - "excluded", - "certifications" - ].forEach((field) => { - json[field] = []; - this[field].forEach((raw) => { - json[field].push(raw); - }); - }); - [ - "transactions" - ].forEach((field) => { - json[field] = []; - this[field].forEach((obj) => { - json[field].push(_(obj).omit('raw', 'certifiers', 'hash')); - }); - }); - json.raw = this.getRaw(); - return json; - }; + const b = document.Block.fromJSON(this) + return b.json() + } this.getHash = () => { if (!this.hash) { diff --git a/app/lib/entity/identity.js b/app/lib/entity/identity.js index f4cdc9499387bae65964530238484717d5cd3840..49eaea2a36504e34144aba81cc785e1700bd2dbd 100644 --- a/app/lib/entity/identity.js +++ b/app/lib/entity/identity.js @@ -85,11 +85,8 @@ const Identity = function(json) { }; this.rawWithoutSig = () => { - const sig = this.sig; - this.sig = ''; - const raw = rawer.getOfficialIdentity(this); - this.sig = sig; - return raw; + const DO_NOT_SIGN = false + return rawer.getOfficialIdentity(this, DO_NOT_SIGN) }; this.getTargetHash = () => { diff --git a/app/lib/entity/membership.js b/app/lib/entity/membership.js index 92167fc66cee519fc77ff62f27e4eaf96c761f53..a4a64fc6b9c20e74a942e76122e51eee8bda91a5 100644 --- a/app/lib/entity/membership.js +++ b/app/lib/entity/membership.js @@ -23,14 +23,6 @@ const Membership = function(json) { }); }; - this.inline = () => [this.issuer, - this.signature, - [this.number, this.fpr].join('-'), - this.certts, - this.userid - ].join(':'); - - this.json = () => { const json = {}; ["version", "currency", "issuer", "membership"].forEach((key) => { diff --git a/app/lib/entity/stat.js b/app/lib/entity/stat.js deleted file mode 100644 index 1b459dbd90d1be15bc1a7ecf43e80daba0e8001e..0000000000000000000000000000000000000000 --- a/app/lib/entity/stat.js +++ /dev/null @@ -1,14 +0,0 @@ -"use strict"; -const _ = require('underscore'); - -const Stat = function(json) { - _(json).keys().forEach((key) => { - this[key] = json[key]; - }); - - this.json = function () { - return { "blocks": this.blocks }; - }; -}; - -module.exports = Stat; diff --git a/app/lib/entity/transaction.js b/app/lib/entity/transaction.js index 6d12b0488c8a13eaa45adc0fb953af2e66c34286..a6c2bd9c021334c291881840eec98061cf84b51e 100644 --- a/app/lib/entity/transaction.js +++ b/app/lib/entity/transaction.js @@ -18,8 +18,8 @@ let Transaction = function(obj, currency) { }); // Store the maximum output base - this.output_amount = this.outputs.reduce((sum, output) => sum + parseInt(output.split(':')[0]), 0); - this.output_base = this.outputs.reduce((maxBase, output) => Math.max(maxBase, parseInt(output.split(':')[1])), 0); + this.output_amount = this.outputs.reduce((sum, output) => sum + parseInt((output.raw || output).split(':')[0]), 0); + this.output_base = this.outputs.reduce((maxBase, output) => Math.max(maxBase, parseInt((output.raw || output).split(':')[1])), 0); this.currency = currency || this.currency; @@ -98,7 +98,7 @@ Transaction.statics = {}; Transaction.statics.fromJSON = (json) => new Transaction(json); Transaction.statics.outputs2recipients = (tx) => tx.outputs.map(function(out) { - const recipent = out.match('SIG\\((.*)\\)'); + const recipent = (out.raw || out).match('SIG\\((.*)\\)'); return (recipent && recipent[1]) || 'UNKNOWN'; }); diff --git a/app/lib/rules/global_rules.js b/app/lib/rules/global_rules.js deleted file mode 100644 index b783b0405bd3f7285d2c74356e9a7164f78ed7a6..0000000000000000000000000000000000000000 --- a/app/lib/rules/global_rules.js +++ /dev/null @@ -1,278 +0,0 @@ -"use strict"; - -const Q = require('q'); -const co = require('co'); -const _ = require('underscore'); -const constants = require('../constants'); -const keyring = require('duniter-common').keyring; -const rawer = require('duniter-common').rawer; -const indexer = require('../dup/indexer'); -const Identity = require('../entity/identity'); -const Transaction = require('../entity/transaction'); -const logger = require('../logger')('globr'); -const unlock = require('../ucp/txunlock'); -const local_rules = require('./local_rules'); - -let rules = {}; - -// TODO: all the global rules should be replaced by index rule someday - -rules.FUNCTIONS = { - - checkIdentitiesAreWritable: (block, conf, dal) => co(function *() { - let current = yield dal.getCurrentBlockOrNull(); - for (const obj of block.identities) { - let idty = Identity.statics.fromInline(obj); - let found = yield dal.getWrittenIdtyByUID(idty.uid); - if (found) { - throw Error('Identity already used'); - } - // Because the window rule does not apply on initial certifications - if (current && idty.buid != constants.BLOCK.SPECIAL_BLOCK) { - // From DUP 0.5: we fully check the blockstamp - const basedBlock = yield dal.getBlockByBlockstamp(idty.buid); - // Check if writable - let duration = current.medianTime - parseInt(basedBlock.medianTime); - if (duration > conf.idtyWindow) { - throw Error('Identity is too old and cannot be written'); - } - } - } - return true; - }), - - checkSourcesAvailability: (block, conf, dal, alsoCheckPendingTransactions) => co(function *() { - let txs = block.getTransactions(); - const current = yield dal.getCurrentBlockOrNull(); - for (const tx of txs) { - let unlocks = {}; - let sumOfInputs = 0; - let maxOutputBase = current.unitbase; - for (const unlock of tx.unlocks) { - let sp = unlock.split(':'); - let index = parseInt(sp[0]); - unlocks[index] = sp[1]; - } - for (let k = 0, len2 = tx.inputs.length; k < len2; k++) { - let src = tx.inputs[k]; - let dbSrc = yield dal.getSource(src.identifier, src.pos); - logger.debug('Source %s:%s:%s:%s = %s', src.amount, src.base, src.identifier, src.pos, dbSrc && dbSrc.consumed); - if (!dbSrc && alsoCheckPendingTransactions) { - // For chained transactions which are checked on sandbox submission, we accept them if there is already - // a previous transaction of the chain already recorded in the pool - dbSrc = yield co(function*() { - let hypotheticSrc = null; - let targetTX = yield dal.getTxByHash(src.identifier); - if (targetTX) { - let outputStr = targetTX.outputs[src.pos]; - if (outputStr) { - hypotheticSrc = Transaction.statics.outputStr2Obj(outputStr); - hypotheticSrc.consumed = false; - hypotheticSrc.time = 0; - } - } - return hypotheticSrc; - }); - } - if (!dbSrc || dbSrc.consumed) { - logger.warn('Source ' + [src.type, src.identifier, src.pos].join(':') + ' is not available'); - throw constants.ERRORS.SOURCE_ALREADY_CONSUMED; - } - sumOfInputs += dbSrc.amount * Math.pow(10, dbSrc.base); - if (block.medianTime - dbSrc.written_time < tx.locktime) { - throw constants.ERRORS.LOCKTIME_PREVENT; - } - let sigResults = local_rules.HELPERS.getSigResult(tx); - let unlocksForCondition = []; - let unlocksMetadata = {}; - let unlockValues = unlocks[k]; - if (dbSrc.conditions) { - if (unlockValues) { - // Evaluate unlock values - let sp = unlockValues.split(' '); - for (const func of sp) { - let param = func.match(/\((.+)\)/)[1]; - if (func.match(/^SIG/)) { - let pubkey = tx.issuers[parseInt(param)]; - if (!pubkey) { - logger.warn('Source ' + [src.amount, src.base, src.type, src.identifier, src.pos].join(':') + ' unlock fail (unreferenced signatory)'); - throw constants.ERRORS.WRONG_UNLOCKER; - } - unlocksForCondition.push({ - pubkey: pubkey, - sigOK: sigResults.sigs[pubkey] && sigResults.sigs[pubkey].matching || false - }); - } else if (func.match(/^XHX/)) { - unlocksForCondition.push(param); - } - } - } - - if (dbSrc.conditions.match(/CLTV/)) { - unlocksMetadata.currentTime = block.medianTime; - } - - if (dbSrc.conditions.match(/CSV/)) { - unlocksMetadata.elapsedTime = block.medianTime - dbSrc.written_time; - } - - try { - if (!unlock(dbSrc.conditions, unlocksForCondition, unlocksMetadata)) { - throw Error('Locked'); - } - } catch (e) { - logger.warn('Source ' + [src.amount, src.base, src.type, src.identifier, src.pos].join(':') + ' unlock fail'); - throw constants.ERRORS.WRONG_UNLOCKER; - } - } - } - let sumOfOutputs = tx.outputs.reduce(function(p, output) { - if (output.base > maxOutputBase) { - throw constants.ERRORS.WRONG_OUTPUT_BASE; - } - return p + output.amount * Math.pow(10, output.base); - }, 0); - if (sumOfInputs !== sumOfOutputs) { - logger.warn('Inputs/Outputs != 1 (%s/%s)', sumOfInputs, sumOfOutputs); - throw constants.ERRORS.WRONG_AMOUNTS; - } - } - return true; - }) -}; - -rules.HELPERS = { - - // Functions used in an external context too - checkMembershipBlock: (ms, current, conf, dal) => checkMSTarget(ms, current ? { number: current.number + 1} : { number: 0 }, conf, dal), - - checkCertificationIsValid: (cert, current, findIdtyFunc, conf, dal) => checkCertificationIsValid(current ? current : { number: 0 }, cert, findIdtyFunc, conf, dal), - - checkCertificationIsValidForBlock: (cert, block, idty, conf, dal) => checkCertificationIsValid(block, cert, () => idty, conf, dal), - - isOver3Hops: (member, newLinks, newcomers, current, conf, dal) => co(function *() { - if (!current) { - return Q(false); - } - try { - return indexer.DUP_HELPERS.checkPeopleAreNotOudistanced([member], newLinks, newcomers, conf, dal); - } catch (e) { - return true; - } - }), - - checkExistsUserID: (uid, dal) => dal.getWrittenIdtyByUID(uid), - - checkExistsPubkey: (pub, dal) => dal.getWrittenIdtyByPubkey(pub), - - checkSingleTransaction: (tx, block, conf, dal, alsoCheckPendingTransactions) => rules.FUNCTIONS.checkSourcesAvailability({ - getTransactions: () => [tx], - medianTime: block.medianTime - }, conf, dal, alsoCheckPendingTransactions), - - checkTxBlockStamp: (tx, dal) => co(function *() { - const number = tx.blockstamp.split('-')[0]; - const hash = tx.blockstamp.split('-')[1]; - const basedBlock = yield dal.getBlockByNumberAndHashOrNull(number, hash); - if (!basedBlock) { - throw "Wrong blockstamp for transaction"; - } - // Valuates the blockstampTime field - tx.blockstampTime = basedBlock.medianTime; - const current = yield dal.getCurrentBlockOrNull(); - if (current && current.medianTime > basedBlock.medianTime + constants.TX_WINDOW) { - throw "Transaction has expired"; - } - }) -}; - -/***************************** - * - * UTILITY FUNCTIONS - * - *****************************/ - -function checkMSTarget (ms, block, conf, dal) { - return co(function *() { - if (block.number == 0 && ms.number != 0) { - throw Error('Number must be 0 for root block\'s memberships'); - } - else if (block.number == 0 && ms.fpr != 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { - throw Error('Hash must be E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 for root block\'s memberships'); - } - else if (block.number == 0) { - return null; // Valid for root block - } else { - let basedBlock; - try { - basedBlock = yield dal.getBlockByNumberAndHash(ms.number, ms.fpr); - } catch (e) { - throw Error('Membership based on an unexisting block'); - } - let current = yield dal.getCurrentBlockOrNull(); - if (current && current.medianTime > basedBlock.medianTime + conf.msValidity) { - throw Error('Membership has expired'); - } - return basedBlock; - } - }); -} - -function checkCertificationIsValid (block, cert, findIdtyFunc, conf, dal) { - return co(function *() { - if (block.number == 0 && cert.block_number != 0) { - throw Error('Number must be 0 for root block\'s certifications'); - } else { - let basedBlock = { - hash: constants.BLOCK.SPECIAL_HASH - }; - if (block.number != 0) { - try { - basedBlock = yield dal.getBlock(cert.block_number); - } catch (e) { - throw Error('Certification based on an unexisting block'); - } - try { - const issuer = yield dal.getWrittenIdtyByPubkey(cert.from) - if (!issuer || !issuer.member) { - throw Error('Issuer is not a member') - } - } catch (e) { - throw Error('Certifier must be a member') - } - } - let idty = yield findIdtyFunc(block, cert.to, dal); - let current = block.number == 0 ? null : yield dal.getCurrentBlockOrNull(); - if (!idty) { - throw Error('Identity does not exist for certified'); - } - else if (current && current.medianTime > basedBlock.medianTime + conf.sigValidity) { - throw Error('Certification has expired'); - } - else if (cert.from == idty.pubkey) - throw Error('Rejected certification: certifying its own self-certification has no meaning'); - else { - const buid = [cert.block_number, basedBlock.hash].join('-'); - if (cert.block_hash && buid != [cert.block_number, cert.block_hash].join('-')) - throw Error('Certification based on an unexisting block buid. from ' + cert.from.substring(0,8) + ' to ' + idty.pubkey.substring(0,8)); - idty.currency = conf.currency; - const raw = rawer.getOfficialCertification(_.extend(idty, { - idty_issuer: idty.pubkey, - idty_uid: idty.uid, - idty_buid: idty.buid, - idty_sig: idty.sig, - issuer: cert.from, - buid: buid, - sig: '' - })); - const verified = keyring.verify(raw, cert.sig, cert.from); - if (!verified) { - throw Error('Wrong signature for certification'); - } - return true; - } - } - }); -} - -module.exports = rules; diff --git a/app/lib/rules/index.js b/app/lib/rules/index.js deleted file mode 100644 index 284ce198aecd0b7aa7d4fdff858db41584b3e245..0000000000000000000000000000000000000000 --- a/app/lib/rules/index.js +++ /dev/null @@ -1,100 +0,0 @@ -"use strict"; - -const _ = require('underscore'); -const co = require('co'); -const Block = require('../entity/block'); -const local_rules = require('./local_rules'); -const global_rules = require('./global_rules'); - -let rules = {}; - -rules.LOCAL = local_rules.FUNCTIONS; -rules.GLOBAL = global_rules.FUNCTIONS; - -rules.HELPERS = {}; - -_.extend(rules.HELPERS, local_rules.HELPERS); -_.extend(rules.HELPERS, global_rules.HELPERS); - -rules.ALIAS = { - - ALL_LOCAL: (block, conf) => co(function *() { - yield rules.LOCAL.checkParameters(block); - yield rules.LOCAL.checkProofOfWork(block); - yield rules.LOCAL.checkInnerHash(block); - yield rules.LOCAL.checkPreviousHash(block); - yield rules.LOCAL.checkPreviousIssuer(block); - yield rules.LOCAL.checkUnitBase(block); - yield rules.LOCAL.checkBlockSignature(block); - yield rules.LOCAL.checkBlockTimes(block, conf); - yield rules.LOCAL.checkIdentitiesSignature(block); - yield rules.LOCAL.checkIdentitiesUserIDConflict(block, conf); - yield rules.LOCAL.checkIdentitiesPubkeyConflict(block, conf); - yield rules.LOCAL.checkIdentitiesMatchJoin(block, conf); - yield rules.LOCAL.checkMembershipUnicity(block, conf); - yield rules.LOCAL.checkRevokedUnicity(block, conf); - yield rules.LOCAL.checkRevokedAreExcluded(block, conf); - yield rules.LOCAL.checkMembershipsSignature(block); - yield rules.LOCAL.checkPubkeyUnicity(block); - yield rules.LOCAL.checkCertificationOneByIssuer(block, conf); - yield rules.LOCAL.checkCertificationUnicity(block, conf); - yield rules.LOCAL.checkCertificationIsntForLeaverOrExcluded(block, conf); - yield rules.LOCAL.checkTxVersion(block); - yield rules.LOCAL.checkTxIssuers(block); - yield rules.LOCAL.checkTxSources(block); - yield rules.LOCAL.checkTxRecipients(block); - yield rules.LOCAL.checkTxAmounts(block); - yield rules.LOCAL.checkTxSignature(block); - }), - - ALL_LOCAL_BUT_POW_AND_SIGNATURE: (block, conf) => co(function *() { - yield rules.LOCAL.checkParameters(block); - yield rules.LOCAL.checkInnerHash(block); - yield rules.LOCAL.checkPreviousHash(block); - yield rules.LOCAL.checkPreviousIssuer(block); - yield rules.LOCAL.checkUnitBase(block); - yield rules.LOCAL.checkBlockTimes(block, conf); - yield rules.LOCAL.checkIdentitiesSignature(block); - yield rules.LOCAL.checkIdentitiesUserIDConflict(block, conf); - yield rules.LOCAL.checkIdentitiesPubkeyConflict(block, conf); - yield rules.LOCAL.checkIdentitiesMatchJoin(block, conf); - yield rules.LOCAL.checkMembershipUnicity(block, conf); - yield rules.LOCAL.checkRevokedUnicity(block, conf); - yield rules.LOCAL.checkRevokedAreExcluded(block, conf); - yield rules.LOCAL.checkMembershipsSignature(block); - yield rules.LOCAL.checkPubkeyUnicity(block); - yield rules.LOCAL.checkCertificationOneByIssuer(block, conf); - yield rules.LOCAL.checkCertificationUnicity(block, conf); - yield rules.LOCAL.checkCertificationIsntForLeaverOrExcluded(block, conf); - yield rules.LOCAL.checkTxVersion(block); - yield rules.LOCAL.checkTxIssuers(block); - yield rules.LOCAL.checkTxSources(block); - yield rules.LOCAL.checkTxRecipients(block); - yield rules.LOCAL.checkTxAmounts(block); - yield rules.LOCAL.checkTxSignature(block); - }) -}; - -rules.CHECK = { - ASYNC: { - ALL_LOCAL: checkLocal(rules.ALIAS.ALL_LOCAL), - ALL_LOCAL_BUT_POW: checkLocal(rules.ALIAS.ALL_LOCAL_BUT_POW_AND_SIGNATURE) - } -}; - -function checkLocal(contract) { - return (b, conf, done) => { - return co(function *() { - try { - const block = new Block(b); - yield contract(block, conf); - done && done(); - } catch (err) { - if (done) return done(err); - throw err; - } - }); - }; -} - -module.exports = rules; diff --git a/app/lib/rules/local_rules.js b/app/lib/rules/local_rules.js deleted file mode 100644 index c0eb654a3e9b264e796ff9849adfb7712519fe62..0000000000000000000000000000000000000000 --- a/app/lib/rules/local_rules.js +++ /dev/null @@ -1,516 +0,0 @@ -"use strict"; - -const co = require('co'); -const _ = require('underscore'); -const constants = require('../constants'); -const indexer = require('../dup/indexer'); -const hashf = require('duniter-common').hashf; -const keyring = require('duniter-common').keyring; -const rawer = require('duniter-common').rawer; -const Identity = require('../entity/identity'); -const Membership = require('../entity/membership'); -const Transaction = require('../entity/transaction'); -const maxAcceleration = require('duniter-common').rules.HELPERS.maxAcceleration; - -let rules = {}; - -// TODO: make a global variable 'index' instead of recomputing the index each time - -rules.FUNCTIONS = { - - checkParameters: (block) => co(function *() { - if (block.number == 0 && !block.parameters) { - throw Error('Parameters must be provided for root block'); - } - else if (block.number > 0 && block.parameters) { - throw Error('Parameters must not be provided for non-root block'); - } - return true; - }), - - checkProofOfWork: (block) => co(function *() { - let remainder = block.powMin % 16; - let nb_zeros = (block.powMin - remainder) / 16; - const powRegexp = new RegExp('^0{' + nb_zeros + '}'); - if (!block.hash.match(powRegexp)) { - throw Error('Not a proof-of-work'); - } - return true; - }), - - checkInnerHash: (block) => co(function *() { - let inner_hash = hashf(block.getRawInnerPart()).toUpperCase(); - if (block.inner_hash != inner_hash) { - throw Error('Wrong inner hash'); - } - return true; - }), - - checkPreviousHash: (block) => co(function *() { - if (block.number == 0 && block.previousHash) { - throw Error('PreviousHash must not be provided for root block'); - } - else if (block.number > 0 && !block.previousHash) { - throw Error('PreviousHash must be provided for non-root block'); - } - return true; - }), - - checkPreviousIssuer: (block) => co(function *() { - if (block.number == 0 && block.previousIssuer) - throw Error('PreviousIssuer must not be provided for root block'); - else if (block.number > 0 && !block.previousIssuer) - throw Error('PreviousIssuer must be provided for non-root block'); - return true; - }), - - checkUnitBase: (block) => co(function *() { - if (block.number == 0 && block.unitbase != 0) { - throw Error('UnitBase must equal 0 for root block'); - } - return true; - }), - - checkBlockSignature: (block) => co(function *() { - if (!keyring.verify(block.getSignedPart(), block.signature, block.issuer)) - throw Error('Block\'s signature must match'); - return true; - }), - - checkBlockTimes: (block, conf) => co(function *() { - const time = parseInt(block.time); - const medianTime = parseInt(block.medianTime); - if (block.number > 0 && (time < medianTime || time > medianTime + maxAcceleration(conf))) - throw Error('A block must have its Time between MedianTime and MedianTime + ' + maxAcceleration(conf)); - else if (block.number == 0 && time != medianTime) - throw Error('Root block must have Time equal MedianTime'); - return true; - }), - - checkIdentitiesSignature: (block) => co(function *() { - let i = 0; - let wrongSig = false; - while (!wrongSig && i < block.identities.length) { - const idty = Identity.statics.fromInline(block.identities[i]); - idty.currency = block.currency; - wrongSig = !keyring.verify(idty.rawWithoutSig(), idty.sig, idty.pubkey); - if (wrongSig) { - throw Error('Identity\'s signature must match'); - } - i++; - } - return true; - }), - - checkIdentitiesUserIDConflict: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const creates = indexer.iindexCreate(index); - const uids = _.chain(creates).pluck('uid').uniq().value(); - if (creates.length !== uids.length) { - throw Error('Block must not contain twice same identity uid'); - } - return true; - }), - - checkIdentitiesPubkeyConflict: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const creates = indexer.iindexCreate(index); - const pubkeys = _.chain(creates).pluck('pub').uniq().value(); - if (creates.length !== pubkeys.length) { - throw Error('Block must not contain twice same identity pubkey'); - } - return true; - }), - - checkIdentitiesMatchJoin: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const icreates = indexer.iindexCreate(index); - const mcreates = indexer.mindexCreate(index); - for (const icreate of icreates) { - const matching = _(mcreates).filter({ pub: icreate.pub }); - if (matching.length == 0) { - throw Error('Each identity must match a newcomer line with same userid and certts'); - } - } - return true; - }), - - checkRevokedAreExcluded: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const iindex = indexer.iindex(index); - const mindex = indexer.mindex(index); - const revocations = _.chain(mindex) - .filter((row) => row.op == constants.IDX_UPDATE && row.revoked_on !== null) - .pluck('pub') - .value(); - for (const pub of revocations) { - const exclusions = _(iindex).where({ op: constants.IDX_UPDATE, member: false, pub }); - if (exclusions.length == 0) { - throw Error('A revoked member must be excluded'); - } - } - return true; - }), - - checkRevokedUnicity: (block, conf) => co(function *() { - try { - yield rules.FUNCTIONS.checkMembershipUnicity(block, conf); - } catch (e) { - throw Error('A single revocation per member is allowed'); - } - return true; - }), - - checkMembershipUnicity: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const mindex = indexer.mindex(index); - const pubkeys = _.chain(mindex).pluck('pub').uniq().value(); - if (pubkeys.length !== mindex.length) { - throw Error('Unicity constraint PUBLIC_KEY on MINDEX is not respected'); - } - return true; - }), - - checkMembershipsSignature: (block) => co(function *() { - let i = 0; - let wrongSig = false, ms; - // Joiners - while (!wrongSig && i < block.joiners.length) { - ms = Membership.statics.fromInline(block.joiners[i], 'IN', block.currency); - wrongSig = !checkSingleMembershipSignature(ms); - i++; - } - // Actives - i = 0; - while (!wrongSig && i < block.actives.length) { - ms = Membership.statics.fromInline(block.actives[i], 'IN', block.currency); - wrongSig = !checkSingleMembershipSignature(ms); - i++; - } - // Leavers - i = 0; - while (!wrongSig && i < block.leavers.length) { - ms = Membership.statics.fromInline(block.leavers[i], 'OUT', block.currency); - wrongSig = !checkSingleMembershipSignature(ms); - i++; - } - if (wrongSig) { - throw Error('Membership\'s signature must match'); - } - return true; - }), - - checkPubkeyUnicity: (block) => co(function *() { - const pubkeys = []; - let conflict = false; - let pubk; - // Joiners - let i = 0; - while (!conflict && i < block.joiners.length) { - pubk = block.joiners[i].split(':')[0]; - conflict = ~pubkeys.indexOf(pubk); - pubkeys.push(pubk); - i++; - } - // Actives - i = 0; - while (!conflict && i < block.actives.length) { - pubk = block.actives[i].split(':')[0]; - conflict = ~pubkeys.indexOf(pubk); - pubkeys.push(pubk); - i++; - } - // Leavers - i = 0; - while (!conflict && i < block.leavers.length) { - pubk = block.leavers[i].split(':')[0]; - conflict = ~pubkeys.indexOf(pubk); - pubkeys.push(pubk); - i++; - } - // Excluded - i = 0; - while (!conflict && i < block.excluded.length) { - pubk = block.excluded[i].split(':')[0]; - conflict = ~pubkeys.indexOf(pubk); - pubkeys.push(pubk); - i++; - } - if (conflict) { - throw Error('Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded'); - } - return true; - }), - - checkCertificationOneByIssuer: (block, conf) => co(function *() { - if (block.number > 0) { - const index = indexer.localIndex(block, conf); - const cindex = indexer.cindex(index); - const certFromA = _.uniq(cindex.map((row) => row.issuer)); - if (certFromA.length !== cindex.length) { - throw Error('Block cannot contain two certifications from same issuer'); - } - } - return true; - }), - - checkCertificationUnicity: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const cindex = indexer.cindex(index); - const certAtoB = _.uniq(cindex.map((row) => row.issuer + row.receiver)); - if (certAtoB.length !== cindex.length) { - throw Error('Block cannot contain identical certifications (A -> B)'); - } - return true; - }), - - checkCertificationIsntForLeaverOrExcluded: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); - const cindex = indexer.cindex(index); - const iindex = indexer.iindex(index); - const mindex = indexer.mindex(index); - const certified = cindex.map((row) => row.receiver); - for (const pub of certified) { - const exclusions = _(iindex).where({ op: constants.IDX_UPDATE, member: false, pub: pub }); - const leavers = _(mindex).where({ op: constants.IDX_UPDATE, leaving: true, pub: pub }); - if (exclusions.length > 0 || leavers.length > 0) { - throw Error('Block cannot contain certifications concerning leavers or excluded members'); - } - } - return true; - }), - - checkTxVersion: (block) => co(function *() { - const txs = block.getTransactions(); - // Check rule against each transaction - for (const tx of txs) { - if (tx.version != 10) { - throw Error('A transaction must have the version 10'); - } - } - return true; - }), - - checkTxLen: (block) => co(function *() { - const txs = block.getTransactions(); - // Check rule against each transaction - for (const tx of txs) { - const txLen = Transaction.statics.getLen(tx); - if (txLen > constants.MAXIMUM_LEN_OF_COMPACT_TX) { - throw constants.ERRORS.A_TRANSACTION_HAS_A_MAX_SIZE; - } - } - // Check rule against each output of each transaction - for (const tx of txs) { - for (const output of tx.outputs) { - const out = typeof output === 'string' ? output : Transaction.statics.outputObj2Str(output) - if (out.length > constants.MAXIMUM_LEN_OF_OUTPUT) { - throw constants.ERRORS.MAXIMUM_LEN_OF_OUTPUT - } - } - } - // Check rule against each unlock of each transaction - for (const tx of txs) { - for (const unlock of tx.unlocks) { - if (unlock.length > constants.MAXIMUM_LEN_OF_UNLOCK) { - throw constants.ERRORS.MAXIMUM_LEN_OF_UNLOCK - } - } - } - return true; - }), - - checkTxIssuers: (block) => co(function *() { - const txs = block.getTransactions(); - // Check rule against each transaction - for (const tx of txs) { - if (tx.issuers.length == 0) { - throw Error('A transaction must have at least 1 issuer'); - } - } - return true; - }), - - checkTxSources: (block) => co(function *() { - const txs = block.getTransactions(); - for (const tx of txs) { - if (!tx.inputs || tx.inputs.length == 0) { - throw Error('A transaction must have at least 1 source'); - } - } - const sindex = indexer.localSIndex(block); - const inputs = _.filter(sindex, (row) => row.op == constants.IDX_UPDATE).map((row) => [row.op, row.identifier, row.pos].join('-')); - if (inputs.length !== _.uniq(inputs).length) { - throw Error('It cannot exist 2 identical sources for transactions inside a given block'); - } - const outputs = _.filter(sindex, (row) => row.op == constants.IDX_CREATE).map((row) => [row.op, row.identifier, row.pos].join('-')); - if (outputs.length !== _.uniq(outputs).length) { - throw Error('It cannot exist 2 identical sources for transactions inside a given block'); - } - return true; - }), - - checkTxAmounts: (block) => co(function *() { - for (const tx of block.getTransactions()) { - rules.HELPERS.checkTxAmountsValidity(tx); - } - }), - - checkTxRecipients: (block) => co(function *() { - const txs = block.getTransactions(); - // Check rule against each transaction - for (const tx of txs) { - if (!tx.outputs || tx.outputs.length == 0) { - throw Error('A transaction must have at least 1 recipient'); - } - else { - // Cannot have empty output condition - for (const output of tx.outputs) { - if (!output.conditions.match(/(SIG|XHX)/)) { - throw Error('Empty conditions are forbidden'); - } - } - } - } - return true; - }), - - checkTxSignature: (block) => co(function *() { - const txs = block.getTransactions(); - // Check rule against each transaction - for (const tx of txs) { - let sigResult = getSigResult(tx); - if (!sigResult.matching) { - throw Error('Signature from a transaction must match'); - } - } - return true; - }) -}; - -function checkSingleMembershipSignature(ms) { - return keyring.verify(ms.getRaw(), ms.signature, ms.issuer); -} - -function getSigResult(tx) { - let sigResult = { sigs: {}, matching: true }; - let json = { "version": tx.version, "currency": tx.currency, "blockstamp": tx.blockstamp, "locktime": tx.locktime, "inputs": [], "outputs": [], "issuers": tx.issuers, "signatures": [], "comment": tx.comment }; - tx.inputs.forEach(function (input) { - json.inputs.push(input.raw); - }); - tx.outputs.forEach(function (output) { - json.outputs.push(output.raw); - }); - json.unlocks = tx.unlocks; - let i = 0; - let signaturesMatching = true; - const raw = rawer.getTransaction(json); - while (signaturesMatching && i < tx.signatures.length) { - const sig = tx.signatures[i]; - const pub = tx.issuers[i]; - signaturesMatching = keyring.verify(raw, sig, pub); - sigResult.sigs[pub] = { - matching: signaturesMatching, - index: i - }; - i++; - } - sigResult.matching = signaturesMatching; - return sigResult; -} - -function checkBunchOfTransactions(txs, done){ - const block = { - getTransactions: function () { - return txs; - } - }; - return co(function *() { - try { - let local_rule = rules.FUNCTIONS; - yield local_rule.checkTxLen(block); - yield local_rule.checkTxIssuers(block); - yield local_rule.checkTxSources(block); - yield local_rule.checkTxRecipients(block); - yield local_rule.checkTxAmounts(block); - yield local_rule.checkTxSignature(block); - done && done(); - } catch (err) { - if (done) return done(err); - throw err; - } - }); -} - -rules.HELPERS = { - - maxAcceleration: (block, conf) => maxAcceleration(conf), - - checkSingleMembershipSignature: checkSingleMembershipSignature, - - getSigResult: getSigResult, - - checkBunchOfTransactions: checkBunchOfTransactions, - - checkSingleTransactionLocally: (tx, done) => checkBunchOfTransactions([tx], done), - - checkTxAmountsValidity: (tx) => { - // Rule of money conservation - const commonBase = tx.inputs.concat(tx.outputs).reduce((min, input) => { - if (min === null) return input.base; - return Math.min(min, parseInt(input.base)); - }, null); - const inputSumCommonBase = tx.inputs.reduce((sum, input) => { - return sum + input.amount * Math.pow(10, input.base - commonBase); - }, 0); - const outputSumCommonBase = tx.outputs.reduce((sum, output) => { - return sum + output.amount * Math.pow(10, output.base - commonBase); - }, 0); - if (inputSumCommonBase !== outputSumCommonBase) { - throw constants.ERRORS.TX_INPUTS_OUTPUTS_NOT_EQUAL; - } - // Rule of unit base transformation - const maxOutputBase = tx.outputs.reduce((max, output) => { - return Math.max(max, parseInt(output.base)); - }, 0); - // Compute deltas - const deltas = {}; - for (let i = commonBase; i <= maxOutputBase; i++) { - const inputBaseSum = tx.inputs.reduce((sum, input) => { - if (input.base == i) { - return sum + input.amount * Math.pow(10, input.base - commonBase); - } else { - return sum; - } - }, 0); - const outputBaseSum = tx.outputs.reduce((sum, output) => { - if (output.base == i) { - return sum + output.amount * Math.pow(10, output.base - commonBase); - } else { - return sum; - } - }, 0); - const delta = outputBaseSum - inputBaseSum; - let sumUpToBase = 0; - for (let j = commonBase; j < i; j++) { - sumUpToBase -= deltas[j]; - } - if (delta > 0 && delta > sumUpToBase) { - throw constants.ERRORS.TX_OUTPUT_SUM_NOT_EQUALS_PREV_DELTAS; - } - deltas[i] = delta; - } - }, - - getMaxPossibleVersionNumber: (current) => co(function*() { - // Looking at current blockchain, find what is the next maximum version we can produce - - // 1. We follow previous block's version - let version = current ? current.version : constants.BLOCK_GENERATED_VERSION; - - // 2. If we can, we go to the next version - return version; - }) -}; - -module.exports = rules; diff --git a/app/lib/streams/parsers/GenericParser.js b/app/lib/streams/parsers/GenericParser.js deleted file mode 100644 index 753752e7d8bcc8ae1fc4d9286d83c9366ed9d754..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/GenericParser.js +++ /dev/null @@ -1,110 +0,0 @@ -"use strict"; -const util = require('util'); -const stream = require('stream'); -const hashf = require('duniter-common').hashf; -const logger = require('../../logger')('gen_parser'); -const constants = require('../../constants'); - -module.exports = GenericParser; - - -function GenericParser (captures, multipleLinesFields, rawerFunc) { - - stream.Transform.call(this, { decodeStrings: false, objectMode: true }); - - this.rawerFunc = rawerFunc; - - this._simpleLineExtraction = (pr, rawEntry, cap) => { - const fieldValue = rawEntry.match(cap.regexp); - if(fieldValue && fieldValue.length >= 2){ - pr[cap.prop] = cap.parser ? cap.parser(fieldValue[1], pr) : fieldValue[1]; - } - return; - }; - - this._multipleLinesExtraction = (am, wholeAmend, cap) => { - const fieldValue = wholeAmend.match(cap.regexp); - let line = 0; - am[cap.prop] = []; - if(fieldValue && fieldValue.length >= 2) - { - const lines = fieldValue[1].split(/\n/); - if(lines[lines.length - 1].match(/^$/)){ - for (let i = 0; i < lines.length - 1; i++) { - line = lines[i]; - let fprChange = line.match(/([+-][A-Z\d]{40})/); - if(fprChange && fprChange.length == 2){ - am[cap.prop].push(fprChange[1]); - } - else{ - return "Wrong structure for line: '" + line + "'"; - } - } - } - else return "Wrong structure for line: '" + line + "'"; - } - }; - - this.syncWrite = (str) => { - let error; - const obj = {}; - this._parse(str, obj); - this._clean(obj); - if (!error) { - error = this._verify(obj); - } - if (!error) { - const raw = this.rawerFunc(obj); - if (hashf(str) != hashf(raw)) - error = constants.ERRORS.WRONG_DOCUMENT; - if (error) { - logger.trace(error); - logger.trace('-----------------'); - logger.trace('Written: %s', JSON.stringify({ str: str })); - logger.trace('Extract: %s', JSON.stringify({ raw: raw })); - logger.trace('-----------------'); - } - } - if (error){ - logger.trace(error); - throw constants.ERRORS.WRONG_DOCUMENT; - } - return obj; - }; - - this._parse = (str, obj) => { - let error; - if(!str){ - error = "No document given"; - } else { - error = ""; - obj.hash = hashf(str).toUpperCase(); - // Divide in 2 parts: document & signature - const sp = str.split('\n'); - if (sp.length < 3) { - error = "Wrong document: must have at least 2 lines"; - } - else { - const endOffset = str.match(/\n$/) ? 2 : 1; - obj.signature = sp[sp.length - endOffset]; - obj.hash = hashf(str).toUpperCase(); - obj.raw = sp.slice(0, sp.length - endOffset).join('\n') + '\n'; - const docLF = obj.raw.replace(/\r\n/g, "\n"); - if(docLF.match(/\n$/)){ - captures.forEach((cap) => { - if(~multipleLinesFields.indexOf(multipleLinesFields)) - error = this._multipleLinesExtraction(obj, docLF, cap); - else - this._simpleLineExtraction(obj, docLF, cap); - }); - } - else{ - error = "Bad document structure: no new line character at the end of the document."; - } - } - } - return error; - }; -} - -util.inherits(GenericParser, stream.Transform); diff --git a/app/lib/streams/parsers/block.js b/app/lib/streams/parsers/block.js deleted file mode 100644 index 58368da34851b718a45782faaca0d4ae84ae510b..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/block.js +++ /dev/null @@ -1,249 +0,0 @@ -"use strict"; -const util = require('util'); -const GenericParser = require('./GenericParser'); -const Block = require('../../entity/block'); -const hashf = require('duniter-common').hashf; -const rawer = require('duniter-common').rawer; -const constants = require('../../constants'); - -module.exports = BlockParser; - -function BlockParser (onError) { - - const captures = [ - {prop: "version", regexp: constants.BLOCK.VERSION}, - {prop: "type", regexp: constants.BLOCK.TYPE}, - {prop: "currency", regexp: constants.BLOCK.CURRENCY}, - {prop: "number", regexp: constants.BLOCK.BNUMBER}, - {prop: "powMin", regexp: constants.BLOCK.POWMIN}, - {prop: "time", regexp: constants.BLOCK.TIME}, - {prop: "medianTime", regexp: constants.BLOCK.MEDIAN_TIME}, - {prop: "dividend", regexp: constants.BLOCK.UD}, - {prop: "unitbase", regexp: constants.BLOCK.UNIT_BASE}, - {prop: "issuer", regexp: constants.BLOCK.BLOCK_ISSUER}, - {prop: "issuersFrame", regexp: constants.BLOCK.BLOCK_ISSUERS_FRAME}, - {prop: "issuersFrameVar", regexp: constants.BLOCK.BLOCK_ISSUERS_FRAME_VAR}, - {prop: "issuersCount", regexp: constants.BLOCK.DIFFERENT_ISSUERS_COUNT}, - {prop: "parameters", regexp: constants.BLOCK.PARAMETERS}, - {prop: "previousHash", regexp: constants.BLOCK.PREV_HASH}, - {prop: "previousIssuer", regexp: constants.BLOCK.PREV_ISSUER}, - {prop: "membersCount", regexp: constants.BLOCK.MEMBERS_COUNT}, - {prop: "identities", regexp: /Identities:\n([\s\S]*)Joiners/, parser: splitAndMatch('\n', constants.IDENTITY.INLINE)}, - {prop: "joiners", regexp: /Joiners:\n([\s\S]*)Actives/, parser: splitAndMatch('\n', constants.BLOCK.JOINER)}, - {prop: "actives", regexp: /Actives:\n([\s\S]*)Leavers/, parser: splitAndMatch('\n', constants.BLOCK.ACTIVE)}, - {prop: "leavers", regexp: /Leavers:\n([\s\S]*)Excluded/, parser: splitAndMatch('\n', constants.BLOCK.LEAVER)}, - {prop: "revoked", regexp: /Revoked:\n([\s\S]*)Excluded/, parser: splitAndMatch('\n', constants.BLOCK.REVOCATION)}, - {prop: "excluded", regexp: /Excluded:\n([\s\S]*)Certifications/, parser: splitAndMatch('\n', constants.PUBLIC_KEY)}, - {prop: "certifications", regexp: /Certifications:\n([\s\S]*)Transactions/, parser: splitAndMatch('\n', constants.CERT.OTHER.INLINE)}, - {prop: "transactions", regexp: /Transactions:\n([\s\S]*)/, parser: extractTransactions}, - {prop: "inner_hash", regexp: constants.BLOCK.INNER_HASH}, - {prop: "nonce", regexp: constants.BLOCK.NONCE} - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getBlock, onError); - - this._clean = (obj) => { - obj.documentType = 'block'; - obj.identities = obj.identities || []; - obj.joiners = obj.joiners || []; - obj.actives = obj.actives || []; - obj.leavers = obj.leavers || []; - obj.revoked = obj.revoked || []; - obj.excluded = obj.excluded || []; - obj.certifications = obj.certifications || []; - obj.transactions = obj.transactions || []; - obj.version = obj.version || ''; - obj.type = obj.type || ''; - obj.hash = hashf(require('duniter-common').rawer.getBlockInnerHashAndNonceWithSignature(obj)).toUpperCase(); - obj.inner_hash = obj.inner_hash || ''; - obj.currency = obj.currency || ''; - obj.nonce = obj.nonce || ''; - obj.number = obj.number || ''; - obj.time = obj.time || ''; - obj.medianTime = obj.medianTime || ''; - obj.dividend = obj.dividend || null; - obj.unitbase = obj.unitbase || ''; - obj.issuer = obj.issuer || ''; - obj.parameters = obj.parameters || ''; - obj.previousHash = obj.previousHash || ''; - obj.previousIssuer = obj.previousIssuer || ''; - obj.membersCount = obj.membersCount || ''; - obj.transactions.map((tx) => { - tx.currency = obj.currency; - tx.hash = hashf(rawer.getTransaction(tx)).toUpperCase(); - }); - obj.len = Block.statics.getLen(obj); - }; - - this._verify = (obj) => { - let err = null; - const codes = { - 'BAD_VERSION': 150, - 'BAD_CURRENCY': 151, - 'BAD_NUMBER': 152, - 'BAD_TYPE': 153, - 'BAD_NONCE': 154, - 'BAD_RECIPIENT_OF_NONTRANSFERT': 155, - 'BAD_PREV_HASH_PRESENT': 156, - 'BAD_PREV_HASH_ABSENT': 157, - 'BAD_PREV_ISSUER_PRESENT': 158, - 'BAD_PREV_ISSUER_ABSENT': 159, - 'BAD_DIVIDEND': 160, - 'BAD_TIME': 161, - 'BAD_MEDIAN_TIME': 162, - 'BAD_INNER_HASH': 163, - 'BAD_MEMBERS_COUNT': 164, - 'BAD_UNITBASE': 165 - }; - if(!err){ - // Version - if(!obj.version || !obj.version.match(constants.DOCUMENTS_BLOCK_VERSION_REGEXP)) - err = {code: codes.BAD_VERSION, message: "Version unknown"}; - } - if(!err){ - // Type - if(!obj.type || !obj.type.match(/^Block$/)) - err = {code: codes.BAD_TYPE, message: "Not a Block type"}; - } - if(!err){ - // Nonce - if(!obj.nonce || !obj.nonce.match(constants.INTEGER)) - err = {code: codes.BAD_NONCE, message: "Nonce must be an integer value"}; - } - if(!err){ - // Number - if(!obj.number || !obj.number.match(constants.INTEGER)) - err = {code: codes.BAD_NUMBER, message: "Incorrect Number field"}; - } - if(!err){ - // Time - if(!obj.time || !obj.time.match(constants.INTEGER)) - err = {code: codes.BAD_TIME, message: "Time must be an integer"}; - } - if(!err){ - // MedianTime - if(!obj.medianTime || !obj.medianTime.match(constants.INTEGER)) - err = {code: codes.BAD_MEDIAN_TIME, message: "MedianTime must be an integer"}; - } - if(!err){ - if(obj.dividend && !obj.dividend.match(constants.INTEGER)) - err = {code: codes.BAD_DIVIDEND, message: "Incorrect UniversalDividend field"}; - } - if(!err){ - if(obj.unitbase && !obj.unitbase.match(constants.INTEGER)) - err = {code: codes.BAD_UNITBASE, message: "Incorrect UnitBase field"}; - } - if(!err){ - if(!obj.issuer || !obj.issuer.match(constants.BASE58)) - err = {code: codes.BAD_ISSUER, message: "Incorrect Issuer field"}; - } - if(!err){ - // MembersCount - if(!obj.nonce || !obj.nonce.match(constants.INTEGER)) - err = {code: codes.BAD_MEMBERS_COUNT, message: "MembersCount must be an integer value"}; - } - if(!err){ - // InnerHash - if(!obj.inner_hash || !obj.inner_hash.match(constants.FINGERPRINT)) - err = {code: codes.BAD_INNER_HASH, message: "InnerHash must be a hash value"}; - } - return err && err.message; - }; -} - -function splitAndMatch (separator, regexp) { - return function (raw) { - const lines = raw.split(new RegExp(separator)); - const kept = []; - lines.forEach(function(line){ - if (line.match(regexp)) - kept.push(line); - }); - return kept; - }; -} - -function extractTransactions(raw) { - const regexps = { - "issuers": constants.TRANSACTION.SENDER, - "inputs": constants.TRANSACTION.SOURCE_V3, - "unlocks": constants.TRANSACTION.UNLOCK, - "outputs": constants.TRANSACTION.TARGET, - "comments": constants.TRANSACTION.INLINE_COMMENT, - "signatures": constants.SIG - }; - const transactions = []; - const lines = raw.split(/\n/); - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - // On each header - if (line.match(constants.TRANSACTION.HEADER)) { - // Parse the transaction - const currentTX = { raw: line + '\n' }; - const sp = line.split(':'); - const version = parseInt(sp[1]); - const nbIssuers = parseInt(sp[2]); - const nbInputs = parseInt(sp[3]); - const nbUnlocks = parseInt(sp[4]); - const nbOutputs = parseInt(sp[5]); - const hasComment = parseInt(sp[6]); - const start = 2; - currentTX.version = version; - currentTX.blockstamp = lines[i + 1]; - currentTX.raw += currentTX.blockstamp + '\n'; - currentTX.locktime = parseInt(sp[7]); - const linesToExtract = { - issuers: { - start: start, - end: (start - 1) + nbIssuers - }, - inputs: { - start: start + nbIssuers, - end: (start - 1) + nbIssuers + nbInputs - }, - unlocks: { - start: start + nbIssuers + nbInputs, - end: (start - 1) + nbIssuers + nbInputs + nbUnlocks - }, - outputs: { - start: start + nbIssuers + nbInputs + nbUnlocks, - end: (start - 1) + nbIssuers + nbInputs + nbUnlocks + nbOutputs - }, - comments: { - start: start + nbIssuers + nbInputs + nbUnlocks + nbOutputs, - end: (start - 1) + nbIssuers + nbInputs + nbUnlocks + nbOutputs + hasComment - }, - signatures: { - start: start + nbIssuers + nbInputs + nbUnlocks + nbOutputs + hasComment, - end: (start - 1) + 2 * nbIssuers + nbInputs + nbUnlocks + nbOutputs + hasComment - } - }; - ['issuers', 'inputs', 'unlocks', 'outputs', 'comments', 'signatures'].forEach((prop) => { - currentTX[prop] = currentTX[prop] || []; - for (let j = linesToExtract[prop].start; j <= linesToExtract[prop].end; j++) { - const line = lines[i + j]; - if (line.match(regexps[prop])) { - currentTX.raw += line + '\n'; - currentTX[prop].push(line); - } - } - }); - // Comment - if (hasComment) { - currentTX.comment = currentTX.comments[0]; - } else { - currentTX.comment = ''; - } - currentTX.hash = hashf(rawer.getTransaction(currentTX)).toUpperCase(); - // Add to txs array - transactions.push(currentTX); - i = i + 1 + 2 * nbIssuers + nbInputs + nbUnlocks + nbOutputs + hasComment; - } else { - // Not a transaction header, stop reading - i = lines.length; - } - } - return transactions; -} - -util.inherits(BlockParser, GenericParser); diff --git a/app/lib/streams/parsers/certification.js b/app/lib/streams/parsers/certification.js deleted file mode 100644 index aa57b0ef41818fe519687777a161d75a7f4ac766..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/certification.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -const GenericParser = require('./GenericParser'); -const util = require('util'); -const rawer = require('duniter-common').rawer; -const constants = require('../../constants'); - -module.exports = CertificationParser; - -function CertificationParser (onError) { - - const captures = [ - {prop: "version", regexp: constants.DOCUMENTS.DOC_VERSION }, - {prop: "type", regexp: constants.CERTIFICATION.CERT_TYPE }, - {prop: "currency", regexp: constants.DOCUMENTS.DOC_CURRENCY }, - {prop: "issuer", regexp: constants.DOCUMENTS.DOC_ISSUER }, - {prop: "idty_issuer", regexp: constants.CERTIFICATION.IDTY_ISSUER }, - {prop: "idty_sig", regexp: constants.CERTIFICATION.IDTY_SIG }, - {prop: "idty_buid", regexp: constants.CERTIFICATION.IDTY_TIMESTAMP}, - {prop: "idty_uid", regexp: constants.CERTIFICATION.IDTY_UID }, - {prop: "buid", regexp: constants.CERTIFICATION.CERT_TIMESTAMP } - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getOfficialCertification, onError); - - this._clean = (obj) => { - obj.documentType = 'certification'; - obj.sig = obj.signature; - obj.block = obj.buid; - if (obj.block) { - obj.number = obj.block.split('-')[0]; - obj.fpr = obj.block.split('-')[1]; - } else { - obj.number = '0'; - obj.fpr = ''; - } - }; - - this._verify = (obj) => ["version", "type", "currency", "issuer", "idty_issuer", "idty_sig", "idty_buid", "idty_uid", "block"].reduce(function (p, field) { - return p || (!obj[field] && "Wrong format for certification"); - }, null); -} - -util.inherits(CertificationParser, GenericParser); diff --git a/app/lib/streams/parsers/identity.js b/app/lib/streams/parsers/identity.js deleted file mode 100644 index 0f79a5d4b364a59017c801cabbca6774f4f88798..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/identity.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -const GenericParser = require('./GenericParser'); -const util = require('util'); -const rawer = require('duniter-common').rawer; -const hashf = require('duniter-common').hashf; -const constants = require('../../constants'); - -module.exports = IdentityParser; - -function IdentityParser (onError) { - - const captures = [ - {prop: "version", regexp: constants.DOCUMENTS.DOC_VERSION }, - {prop: "type", regexp: constants.IDENTITY.IDTY_TYPE}, - {prop: "currency", regexp: constants.DOCUMENTS.DOC_CURRENCY }, - {prop: "pubkey", regexp: constants.DOCUMENTS.DOC_ISSUER }, - {prop: "uid", regexp: constants.IDENTITY.IDTY_UID }, - {prop: "buid", regexp: constants.DOCUMENTS.TIMESTAMP } - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getOfficialIdentity, onError); - - this._clean = (obj) => { - obj.documentType = 'identity'; - obj.sig = obj.signature; - if (obj.uid && obj.buid && obj.pubkey) { - obj.hash = hashf(obj.uid + obj.buid + obj.pubkey).toUpperCase(); - } - }; - - this._verify = (obj) => { - if (!obj.pubkey) { - return "No pubkey found"; - } - if (!obj.uid) { - return "Wrong user id format"; - } - if (!obj.buid) { - return "Could not extract block uid"; - } - if (!obj.sig) { - return "No signature found for self-certification"; - } - }; -} - -util.inherits(IdentityParser, GenericParser); diff --git a/app/lib/streams/parsers/index.js b/app/lib/streams/parsers/index.js deleted file mode 100644 index 7eec548c6ef8f3c710496fab37dbe00fbdf10690..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/index.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; - -module.exports = { - parseIdentity: (new (require('./identity'))), - parseCertification:(new (require('./certification'))), - parseRevocation: (new (require('./revocation'))), - parseTransaction: (new (require('./transaction'))), - parsePeer: (new (require('./peer'))), - parseMembership: (new (require('./membership'))), - parseBlock: (new (require('./block'))) -}; diff --git a/app/lib/streams/parsers/membership.js b/app/lib/streams/parsers/membership.js deleted file mode 100644 index a0243c4efff5ec2a4f18ee85f798ee35d442a92a..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/membership.js +++ /dev/null @@ -1,75 +0,0 @@ -"use strict"; -const GenericParser = require('./GenericParser'); -const ucp = require('duniter-common').buid; -const rawer = require('duniter-common').rawer; -const util = require('util'); -const constants = require('../../constants'); - -module.exports = MembershipParser; - -function MembershipParser (onError) { - - const captures = [ - {prop: "version", regexp: constants.MEMBERSHIP.VERSION }, - {prop: "currency", regexp: constants.MEMBERSHIP.CURRENCY }, - {prop: "issuer", regexp: constants.MEMBERSHIP.ISSUER }, - {prop: "membership", regexp: constants.MEMBERSHIP.MEMBERSHIP }, - {prop: "userid", regexp: constants.MEMBERSHIP.USERID }, - {prop: "block", regexp: constants.MEMBERSHIP.BLOCK}, - {prop: "certts", regexp: constants.MEMBERSHIP.CERTTS} - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getMembership, onError); - - this._clean = (obj) => { - obj.documentType = 'membership'; - if (obj.block) { - obj.number = obj.block.split('-')[0]; - obj.fpr = obj.block.split('-')[1]; - } else { - obj.number = '0'; - obj.fpr = ''; - } - }; - - this._verify = (obj) => { - let err = null; - const codes = { - 'BAD_VERSION': 150, - 'BAD_CURRENCY': 151, - 'BAD_ISSUER': 152, - 'BAD_MEMBERSHIP': 153, - 'BAD_REGISTRY_TYPE': 154, - 'BAD_BLOCK': 155, - 'BAD_USERID': 156, - 'BAD_CERTTS': 157 - }; - if(!err){ - if(!obj.version || !obj.version.match(constants.DOCUMENTS_VERSION_REGEXP)) - err = {code: codes.BAD_VERSION, message: "Version unknown"}; - } - if(!err){ - if(obj.issuer && !obj.issuer.match(constants.BASE58)) - err = {code: codes.BAD_ISSUER, message: "Incorrect issuer field"}; - } - if(!err){ - if(!(obj.membership || "").match(/^(IN|OUT)$/)) - err = {code: codes.BAD_MEMBERSHIP, message: "Incorrect Membership field: must be either IN or OUT"}; - } - if(!err){ - if(obj.block && !obj.block.match(constants.BLOCK_UID)) - err = {code: codes.BAD_BLOCK, message: "Incorrect Block field: must be a positive or zero integer, a dash and an uppercased SHA1 hash"}; - } - if(!err){ - if(obj.userid && !obj.userid.match(constants.USER_ID)) - err = {code: codes.BAD_USERID, message: "UserID must match udid2 format"}; - } - if(!err){ - if(!ucp.format.isBuid(obj.certts)) - err = {code: codes.BAD_CERTTS, message: "CertTS must be a valid timestamp"}; - } - return err && err.message; - }; -} - -util.inherits(MembershipParser, GenericParser); diff --git a/app/lib/streams/parsers/peer.js b/app/lib/streams/parsers/peer.js deleted file mode 100644 index 64a58436b0276cedf22c61db782d9cf30bddbf0b..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/peer.js +++ /dev/null @@ -1,105 +0,0 @@ -"use strict"; -const GenericParser = require('./GenericParser'); -const rawer = require('duniter-common').rawer; -const util = require('util'); -const constants = require('../../constants'); - -module.exports = PeerParser; - -function PeerParser (onError) { - - const captures = [ - {prop: "version", regexp: /Version: (.*)/}, - {prop: "currency", regexp: /Currency: (.*)/}, - {prop: "pubkey", regexp: /PublicKey: (.*)/}, - {prop: "block", regexp: constants.PEER.BLOCK}, - { - prop: "endpoints", regexp: /Endpoints:\n([\s\S]*)/, parser: (str) => str.split("\n") - } - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getPeer, onError); - - this._clean = (obj) => { - obj.documentType = 'peer'; - obj.endpoints = obj.endpoints || []; - // Removes trailing space - if (obj.endpoints.length > 0) - obj.endpoints.splice(obj.endpoints.length - 1, 1); - obj.getBMA = function() { - let bma = null; - obj.endpoints.forEach((ep) => { - let matches = !bma && ep.match(constants.BMA_REGEXP); - if (matches) { - bma = { - "dns": matches[2] || '', - "ipv4": matches[4] || '', - "ipv6": matches[6] || '', - "port": matches[8] || 9101 - }; - } - }); - return bma || {}; - }; - }; - - this._verify = (obj) => { - let err = null; - const codes = { - 'BAD_VERSION': 150, - 'BAD_CURRENCY': 151, - 'BAD_DNS': 152, - 'BAD_IPV4': 153, - 'BAD_IPV6': 154, - 'BAD_PORT': 155, - 'BAD_FINGERPRINT': 156, - 'BAD_BLOCK': 157, - 'NO_IP_GIVEN': 158 - }; - if(!err){ - // Version - if(!obj.version || !obj.version.match(constants.DOCUMENTS_VERSION_REGEXP)) - err = {code: codes.BAD_VERSION, message: "Version unknown"}; - } - if(!err){ - // PublicKey - if(!obj.pubkey || !obj.pubkey.match(constants.BASE58)) - err = {code: codes.BAD_FINGERPRINT, message: "Incorrect PublicKey field"}; - } - if(!err){ - // Block - if(!obj.block) - err = {code: codes.BAD_BLOCK, message: "Incorrect Block field"}; - } - // Basic Merkled API requirements - let bma = obj.getBMA(); - if(!err){ - // DNS - if(bma.dns && !bma.dns.match(/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/)) - err = {code: codes.BAD_DNS, message: "Incorrect Dns field"}; - } - if(!err){ - // IPv4 - if(bma.ipv4 && !bma.ipv4.match(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/)) - err = {code: codes.BAD_IPV4, message: "Incorrect IPv4 field"}; - } - if(!err){ - // IPv6 - if(bma.ipv6 && !bma.ipv6.match(/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(([0-9A-Fa-f]{1,4}:){0,5}:((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(::([0-9A-Fa-f]{1,4}:){0,5}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/)) - err = {code: codes.BAD_IPV6, message: "Incorrect IPv6 field"}; - } - if(!err){ - // IP - if(!bma.dns && !bma.ipv4 && !bma.ipv6) - err = {code: codes.NO_IP_GIVEN, message: "It must be given at least DNS or one IP, either v4 or v6"}; - } - if(!err){ - // Port - if(bma.port && !(bma.port + "").match(/^\d+$/)) - err = {code: codes.BAD_PORT, message: "Port must be provided and match an integer format"}; - } - return err && err.message; - }; -} - -util.inherits(PeerParser, GenericParser); diff --git a/app/lib/streams/parsers/revocation.js b/app/lib/streams/parsers/revocation.js deleted file mode 100644 index f77544659715501aa0043bb3581e46e6d8505ded..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/revocation.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -const GenericParser = require('./GenericParser'); -const util = require('util'); -const rawer = require('duniter-common').rawer; -const hashf = require('duniter-common').hashf; -const constants = require('../../constants'); - -module.exports = RevocationParser; - -function RevocationParser (onError) { - - const captures = [ - {prop: "version", regexp: constants.DOCUMENTS.DOC_VERSION }, - {prop: "type", regexp: constants.REVOCATION.REVOC_TYPE }, - {prop: "currency", regexp: constants.DOCUMENTS.DOC_CURRENCY }, - {prop: "issuer", regexp: constants.DOCUMENTS.DOC_ISSUER }, - {prop: "sig", regexp: constants.REVOCATION.IDTY_SIG }, - {prop: "buid", regexp: constants.REVOCATION.IDTY_TIMESTAMP}, - {prop: "uid", regexp: constants.REVOCATION.IDTY_UID } - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getOfficialRevocation, onError); - - this._clean = (obj) => { - obj.documentType = 'revocation'; - obj.pubkey = obj.issuer; - obj.revocation = obj.signature; - if (obj.uid && obj.buid && obj.pubkey) { - obj.hash = hashf(obj.uid + obj.buid + obj.pubkey).toUpperCase(); - } - }; - - this._verify = (obj) => { - if (!obj.pubkey) { - return "No pubkey found"; - } - if (!obj.uid) { - return "Wrong user id format"; - } - if (!obj.buid) { - return "Could not extract block uid"; - } - if (!obj.sig) { - return "No signature found for identity"; - } - if (!obj.revocation) { - return "No revocation signature found"; - } - }; -} - -util.inherits(RevocationParser, GenericParser); diff --git a/app/lib/streams/parsers/transaction.js b/app/lib/streams/parsers/transaction.js deleted file mode 100644 index 25da6f462c8f46a8e82e96b78808418fc881ddf5..0000000000000000000000000000000000000000 --- a/app/lib/streams/parsers/transaction.js +++ /dev/null @@ -1,128 +0,0 @@ -"use strict"; -const GenericParser = require('./GenericParser'); -const rawer = require('duniter-common').rawer; -const constants = require('../../constants'); -const util = require('util'); - -module.exports = TransactionParser; - -function TransactionParser (onError) { - - const captures = [ - {prop: "version", regexp: /Version: (.*)/}, - {prop: "currency", regexp: /Currency: (.*)/}, - {prop: "issuers", regexp: /Issuers:\n([\s\S]*)Inputs/, parser: extractIssuers }, - {prop: "inputs", regexp: /Inputs:\n([\s\S]*)Unlocks/, parser: extractInputs }, - {prop: "unlocks", regexp: /Unlocks:\n([\s\S]*)Outputs/,parser: extractUnlocks }, - {prop: "outputs", regexp: /Outputs:\n([\s\S]*)/, parser: extractOutputs }, - {prop: "comment", regexp: constants.TRANSACTION.COMMENT }, - {prop: "locktime", regexp: constants.TRANSACTION.LOCKTIME }, - {prop: "blockstamp", regexp: constants.TRANSACTION.BLOCKSTAMP }, - {prop: "signatures", regexp: /Outputs:\n([\s\S]*)/, parser: extractSignatures } - ]; - const multilineFields = []; - GenericParser.call(this, captures, multilineFields, rawer.getTransaction, onError); - - this._clean = (obj) => { - obj.documentType = 'transaction'; - obj.comment = obj.comment || ""; - obj.locktime = parseInt(obj.locktime) || 0; - obj.signatures.push(obj.signature); - const compactSize = 2 // Header + blockstamp - + obj.issuers.length - + obj.inputs.length - + obj.unlocks.length - + obj.outputs.length - + (obj.comment ? 1 : 0) - + obj.signatures; - if (compactSize > 100) { - throw 'A transaction has a maximum size of 100 lines'; - } - }; - - this._verify = (obj) => { - let err = null; - const codes = { - 'BAD_VERSION': 150, - 'NO_BLOCKSTAMP': 151 - }; - if(!err){ - // Version - if(!obj.version || !obj.version.match(constants.DOCUMENTS_TRANSACTION_VERSION_REGEXP)) - err = {code: codes.BAD_VERSION, message: "Version unknown"}; - // Blockstamp - if(!obj.blockstamp || !obj.blockstamp.match(constants.BLOCKSTAMP_REGEXP)) - err = {code: codes.BAD_VERSION, message: "Blockstamp is required"}; - } - return err && err.message; - }; -} - -function extractIssuers(raw) { - const issuers = []; - const lines = raw.split(/\n/); - for (const line of lines) { - if (line.match(constants.TRANSACTION.SENDER)) { - issuers.push(line); - } else { - // Not a pubkey, stop reading - break; - } - } - return issuers; -} - -function extractInputs(raw) { - const inputs = []; - const lines = raw.split(/\n/); - for (const line of lines) { - if (line.match(constants.TRANSACTION.SOURCE_V3)) { - inputs.push(line); - } else { - // Not a transaction input, stop reading - break; - } - } - return inputs; -} - -function extractUnlocks(raw) { - const unlocks = []; - const lines = raw.split(/\n/); - for (const line of lines) { - if (line.match(constants.TRANSACTION.UNLOCK)) { - unlocks.push(line); - } else { - // Not a transaction unlock, stop reading - break; - } - } - return unlocks; -} - -function extractOutputs(raw) { - const outputs = []; - const lines = raw.split(/\n/); - for (const line of lines) { - if (line.match(constants.TRANSACTION.TARGET)) { - outputs.push(line); - } else { - // Not a transaction input, stop reading - break; - } - } - return outputs; -} - -function extractSignatures(raw) { - const signatures = []; - const lines = raw.split(/\n/); - for (const line of lines) { - if (line.match(constants.SIG)) { - signatures.push(line); - } - } - return signatures; -} - -util.inherits(TransactionParser, GenericParser); diff --git a/app/lib/streams/router.js b/app/lib/streams/router.js index 82f04e124b439fc971d72ac9135515900da39799..f97138ab45475699673b2ab8c37fd141c84459aa 100644 --- a/app/lib/streams/router.js +++ b/app/lib/streams/router.js @@ -65,7 +65,7 @@ function Router (PeeringService, dal) { if (e && e.uerr && e.uerr.ucode == constants.ERRORS.NEWER_PEER_DOCUMENT_AVAILABLE.uerr.ucode) { logger.info('Newer peer document available on the network for local node'); } else { - logger.error("Routing error: %s", e && (e.stack || e.message || e)); + logger.error("Routing error: %s", e && (e.stack || e.message || (e.uerr && e.uerr.message) || e)); } } done && done(); diff --git a/app/lib/ucp/txunlock.js b/app/lib/ucp/txunlock.js deleted file mode 100644 index cab1219e40d75433d6da370a98ca571b2ad3561a..0000000000000000000000000000000000000000 --- a/app/lib/ucp/txunlock.js +++ /dev/null @@ -1,76 +0,0 @@ -"use strict"; - -let Parser = require("jison").Parser; -let ucp = require('duniter-common').buid; - -let grammar = { - "lex": { - "rules": [ - ["\\s+", "/* skip whitespace */"], - ["\\&\\&", "return 'AND';"], - ["\\|\\|", "return 'OR';"], - ["\\(", "return '(';"], - ["\\)", "return ')';"], - ["[0-9A-Za-z]{40,64}", "return 'PARAMETER';"], - ["[0-9]{1,10}", "return 'PARAMETER';"], - ["SIG", "return 'SIG';"], - ["XHX", "return 'XHX';"], - ["CLTV", "return 'CLTV';"], - ["CSV", "return 'CSV';"], - ["$", "return 'EOF';"] - ] - }, - - "operators": [ - ["left", "AND", "OR"] - ], - - "bnf": { - "expressions" :[ - [ "e EOF", "return $1;" ] - ], - - "e" :[ - [ "e AND e", "$$ = $1 && $3;" ], - [ "e OR e", "$$ = $1 || $3;" ], - [ "SIG ( e )","$$ = yy.sig($3);"], - [ "XHX ( e )","$$ = yy.xHx($3);"], - [ "CLTV ( e )","$$ = yy.cltv($3);"], - [ "CSV ( e )","$$ = yy.csv($3);"], - [ "PARAMETER", "$$ = $1;" ], - [ "( e )", "$$ = $2;" ] - ] - } -}; - -let logger = require('../logger')('unlock'); - -module.exports = function unlock(conditionsStr, executions, metadata) { - - let parser = new Parser(grammar); - - parser.yy = { - i: 0, - sig: function (pubkey) { - let sigParam = executions[this.i++]; - return (sigParam && pubkey === sigParam.pubkey && sigParam.sigOK) || false; - }, - xHx: function(hash) { - let xhxParam = executions[this.i++]; - return ucp.format.hashf(xhxParam) === hash; - }, - cltv: function(deadline) { - return metadata.currentTime && metadata.currentTime >= parseInt(deadline); - }, - csv: function(amountToWait) { - return metadata.elapsedTime && metadata.elapsedTime >= parseInt(amountToWait); - } - }; - - try { - return parser.parse(conditionsStr); - } catch(e) { - logger.error(e); - return false; - } -}; diff --git a/app/modules/plugin.js b/app/modules/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..b242665299af9f92a4520b66f24aaea2b706c8d0 --- /dev/null +++ b/app/modules/plugin.js @@ -0,0 +1,150 @@ +"use strict"; + +const co = require('co'); +const fs = require('fs'); +const path = require('path'); +const spawn = require('child_process').spawn; + +module.exports = { + duniter: { + + methods: { + canWrite: getNPMAccess, + npmInstall, + npmRemove + }, + + cli: [{ + name: 'plug [what]', + desc: 'Plugs in a duniter module to this Duniter codebase, making it available for the node.', + logs: false, + onDatabaseExecute: (server, conf, program, params) => co(function*() { + const what = params[0]; + try { + console.log('Trying to install module "%s"...', what) + yield checkNPMAccess() + yield npmInstall(what) + console.log('Module successfully installed.') + } catch (err) { + console.error('Error during installation of the plugin:', err); + } + // Close the DB connection properly + return server && server.disconnect() + }) + }, { + name: 'unplug [what]', + desc: 'Plugs in a duniter module to this Duniter codebase, making it available for the node.', + logs: false, + onDatabaseExecute: (server, conf, program, params) => co(function*() { + const what = params[0]; + try { + console.log('Trying to remove module "%s"...', what) + yield checkNPMAccess() + yield npmRemove(what) + console.log('Module successfully uninstalled.') + } catch (err) { + console.error('Error during installation of the plugin:', err); + } + // Close the DB connection properly + return server && server.disconnect() + }) + }] + } +} + +function npmInstall(what, npm, cwd) { + return new Promise((res, rej) => { + const node = getNode() + npm = npm || getNPM() + cwd = cwd || getCWD() + const install = spawn(node, [npm, 'i', '--save', what], { cwd }) + + install.stdout.pipe(process.stdout) + install.stderr.pipe(process.stderr) + + install.stderr.on('data', (data) => { + if (data.toString().match(/ERR!/)) { + setTimeout(() => { + install.kill('SIGINT') + }, 100) + } + }); + + install.on('close', (code) => { + if (code === null || code > 0) { + return rej('could not retrieve or install the plugin') + } + res() + }); + }) +} + + +function npmRemove(what, npm, cwd) { + return new Promise((res, rej) => { + const node = getNode() + npm = npm || getNPM() + cwd = cwd || getCWD() + const uninstall = spawn(node, [npm, 'remove', '--save', what], { cwd }) + + uninstall.stdout.pipe(process.stdout) + uninstall.stderr.pipe(process.stderr) + + uninstall.stderr.on('data', (data) => { + if (data.toString().match(/ERR!/)) { + setTimeout(() => { + uninstall.kill('SIGINT') + }, 100) + } + }); + + uninstall.on('close', (code) => { + if (code === null || code > 0) { + return rej('error during the uninstallation of the plugin') + } + res() + }); + }) +} + +function getNode() { + return process.argv[0] + .replace(/(node|nw)$/, 'node') + .replace(/(node|nw)\.exe$/, 'nodejs\\node.exe') +} + +function getNPM() { + return process.argv[0] + .replace(/(node|nw)$/, 'npm') + .replace(/(node|nw)\.exe$/, 'nodejs\\node_modules\\npm\\bin\\npm-cli.js') +} + +function getCWD() { + return process.argv[1].replace(/bin\/duniter$/, '') +} + +function checkNPMAccess() { + return co(function*() { + const hasReadWriteAccess = yield getNPMAccess() + if (!hasReadWriteAccess) { + throw 'no write access on disk' + } + }) +} + +function getNPMAccess() { + return co(function*() { + const hasAccessToPackageJSON = yield new Promise((res) => { + fs.access(path.join(__dirname, '/../../package.json'), fs.constants.R_OK | fs.constants.W_OK, (err) => { + res(!err) + }) + }) + const hasAccessToNodeModules = yield new Promise((res) => { + fs.access(path.join(__dirname, '/../../node_modules'), fs.constants.R_OK | fs.constants.W_OK, (err) => { + res(!err) + }) + }) + console.log(hasAccessToPackageJSON, hasAccessToNodeModules) + return hasAccessToPackageJSON && hasAccessToNodeModules + }) +} diff --git a/app/service/BlockchainService.js b/app/service/BlockchainService.js index 6628d7af11fc4dd178b704959a6a9634f38a31f6..d91a84b430eda5c6735e5f5733ca8f05c1238e2e 100644 --- a/app/service/BlockchainService.js +++ b/app/service/BlockchainService.js @@ -3,8 +3,8 @@ const _ = require('underscore'); const co = require('co'); const Q = require('q'); -const parsers = require('../lib/streams/parsers'); -const rules = require('../lib/rules'); +const parsers = require('duniter-common').parsers; +const rules = require('duniter-common').rules const constants = require('../lib/constants'); const blockchainCtx = require('../lib/computation/blockchainContext'); const Block = require('../lib/entity/block'); @@ -23,7 +23,7 @@ function BlockchainService (server) { AbstractService.call(this); let that = this; - const mainContext = blockchainCtx(); + const mainContext = blockchainCtx(this); let conf, dal, logger, selfPubkey; this.getContext = () => mainContext; @@ -412,7 +412,6 @@ function BlockchainService (server) { } // Transactions recording yield mainContext.updateTransactionsForBlocks(blocks, getBlockByNumberAndHash); - logger.debug(blocks[0].number); yield dal.blockDAL.saveBunch(blocks); yield pushStatsForBlocks(blocks); }); @@ -450,4 +449,14 @@ function BlockchainService (server) { } return dal.getBlocksBetween(from, from + count - 1); }); + + /** + * Allows to quickly insert a bunch of blocks. To reach such speed, this method skips global rules and buffers changes. + * + * **This method should be used ONLY when a node is really far away from current blockchain HEAD (i.e several hundreds of blocks late). + * + * @param blocks An array of blocks to insert. + * @param to The final block number of the fast insertion. + */ + this.fastBlockInsertions = (blocks, to) => mainContext.quickApplyBlocks(blocks, to) } diff --git a/app/service/IdentityService.js b/app/service/IdentityService.js index 27e9ec796c94da46ba228ae299a09e6dee223601..d5e0aa6fb970c17fc41dc95a298c40e2b755ccf8 100644 --- a/app/service/IdentityService.js +++ b/app/service/IdentityService.js @@ -1,6 +1,6 @@ "use strict"; const Q = require('q'); -const rules = require('../lib/rules'); +const rules = require('duniter-common').rules const keyring = require('duniter-common').keyring; const constants = require('../lib/constants'); const Block = require('../../app/lib/entity/block'); @@ -182,7 +182,9 @@ function IdentityService () { if (idtyAbsorbed) { yield dal.idtyDAL.deleteByHash(targetHash) } - logger.info('✘ CERT %s %s', cert.from, cert.err); + const err = cert.err + const errMessage = (err.uerr && err.uerr.message) || err.message || err + logger.info('✘ CERT %s %s', cert.from, errMessage); throw cert.err; } return cert; diff --git a/app/service/MembershipService.js b/app/service/MembershipService.js index a31075bf38513a32be5042250f085674ed60123f..ec115bf1affcd4f62adada0c37d937c9a8ccc7dd 100644 --- a/app/service/MembershipService.js +++ b/app/service/MembershipService.js @@ -1,7 +1,7 @@ "use strict"; const co = require('co'); -const rules = require('../lib/rules'); +const rules = require('duniter-common').rules const hashf = require('duniter-common').hashf; const constants = require('../lib/constants'); const Membership = require('../lib/entity/membership'); diff --git a/app/service/TransactionsService.js b/app/service/TransactionsService.js index 90a35e9e62b9d4d51e2a6cbf55de016e7b72adca..d362c003f7284a1e90aa87ffbb8cf40297a90b9f 100644 --- a/app/service/TransactionsService.js +++ b/app/service/TransactionsService.js @@ -3,7 +3,7 @@ const co = require('co'); const Q = require('q'); const constants = require('../lib/constants'); -const rules = require('../lib/rules'); +const rules = require('duniter-common').rules const Transaction = require('../lib/entity/transaction'); const AbstractService = require('./AbstractService'); diff --git a/doc/Protocol.md b/doc/Protocol.md index 8d4bded3b08b979d7182b40db83e7aaa359305b8..612afb4eaecdcc9cf51de022336c70c284dcd48f 100644 --- a/doc/Protocol.md +++ b/doc/Protocol.md @@ -1057,6 +1057,7 @@ ud0 | UD(0), i.e. initial Universal Dividend udTime0 | Time of first UD. udReevalTime0 | Time of first reevaluation of the UD. sigPeriod | Minimum delay between 2 certifications of a same issuer, in seconds. Must be positive or zero. +msPeriod | Minimum delay between 2 memberships of a same issuer, in seconds. Must be positive or zero. sigStock | Maximum quantity of active certifications made by member. sigWindow | Maximum delay a certification can wait before being expired for non-writing. sigValidity | Maximum age of an active signature (in seconds) @@ -1198,6 +1199,7 @@ Each identity produces 2 new entries: expired_on = 0 expires_on = MedianTime + msValidity revokes_on = MedianTime + msValidity*2 + chainable_on = MedianTime + msPeriod type = 'JOIN' revoked_on = null leaving = false @@ -1226,6 +1228,7 @@ Each join whose `PUBLIC_KEY` **does not match** a local MINDEX `CREATE, PUBLIC_K expired_on = 0 expires_on = MedianTime + msValidity revokes_on = MedianTime + msValidity*2 + chainable_on = MedianTime + msPeriod type = 'JOIN' revoked_on = null leaving = null @@ -1242,6 +1245,7 @@ Each active produces 1 new entry: written_on = BLOCKSTAMP expires_on = MedianTime + msValidity revokes_on = MedianTime + msValidity*2 + chainable_on = MedianTime + msPeriod type = 'RENEW' revoked_on = null leaving = null @@ -2088,6 +2092,12 @@ For each ENTRY in local MINDEX where `revoked_on == null`: For each ENTRY in local MINDEX where `revoked_on != null`: ENTRY.isBeingRevoked = true + +####### BR_G107 - ENTRY.unchainables +F +If `HEAD.number > 0`: + + ENTRY.unchainables = COUNT(GLOBAL_MINDEX[issuer=ENTRY.issuer, chainable_on > HEAD~1.medianTime])) ###### Local CINDEX augmentation @@ -2327,6 +2337,12 @@ Rule: ENTRY.age <= [msWindow] +###### BR_G108 - Membership period + +Rule: + + ENTRY.unchainables == 0 + ###### BR_G65 - Certification writability Rule: diff --git a/duniter.sh b/duniter.sh index 4e71d991c302b654455ae2d5bf2da94ac391662a..23b5fba83e7978bdfc8751d1275bf96d786e3fbc 100755 --- a/duniter.sh +++ b/duniter.sh @@ -9,7 +9,7 @@ DEB_PACKAGING= if [[ $DEB_PACKAGING ]]; then - DUNITER_DIR=/opt/duniter/sources/ + DUNITER_DIR=/opt/duniter/ fi duniter() { @@ -40,6 +40,7 @@ duniter() { else # Calls duniter JS command + cd $DUNITER_DIR $NODE "$DUNITER_DIR/bin/duniter" "$@" fi; diff --git a/gui/index.html b/gui/index.html index 2bb755c890094dbb3bcf673aa7520c27a9220bf4..b788525bb1804fb0c063ef1ca4acbdb1e355957f 100644 --- a/gui/index.html +++ b/gui/index.html @@ -3,7 +3,7 @@ <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <title>Duniter 1.2.6</title> + <title>Duniter 1.3.8</title> <style> html { font-family: "Courier New", Courier, monospace; @@ -53,7 +53,7 @@ let gui = require('nw.gui'); - let packageJSON = require('../../nw/package.json'); + let packageJSON = require(require('path').resolve('./package.json')); function reqListener () { document.getElementById('loader').innerHTML = 'Server ready.'; clearTimeout(strangeTimeout); diff --git a/gui/package.json b/gui/package.json deleted file mode 100644 index a8bf682b5d2f9fbdfc28afca983c14b27d941d3b..0000000000000000000000000000000000000000 --- a/gui/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "v1.2.6", - "main": "index.html", - "node-main": "../sources/bin/duniter", - "window": { - "icon": "duniter.png", - "title": "v1.2.6", - "width": 800, - "height": 800, - "min_width": 750, - "min_height": 400 - } -} diff --git a/index.js b/index.js index 535748f127ae311d21b56cfe690bf8333ce8dd9a..a96bed32028f581b528111aa9f4a867a6ccd443a 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,7 @@ "use strict"; -const Q = require('q'); const co = require('co'); -const es = require('event-stream'); +const path = require('path'); const util = require('util'); const stream = require('stream'); const _ = require('underscore'); @@ -22,6 +21,7 @@ const revertDependency = require('./app/modules/revert'); const daemonDependency = require('./app/modules/daemon'); const pSignalDependency = require('./app/modules/peersignal'); const routerDependency = require('./app/modules/router'); +const pluginDependency = require('./app/modules/plugin'); const MINIMAL_DEPENDENCIES = [ { name: 'duniter-config', required: configDependency } @@ -36,7 +36,8 @@ const DEFAULT_DEPENDENCIES = MINIMAL_DEPENDENCIES.concat([ { name: 'duniter-revert', required: revertDependency }, { name: 'duniter-daemon', required: daemonDependency }, { name: 'duniter-psignal', required: pSignalDependency }, - { name: 'duniter-router', required: routerDependency } + { name: 'duniter-router', required: routerDependency }, + { name: 'duniter-plugin', required: pluginDependency } ]); const PRODUCTION_DEPENDENCIES = DEFAULT_DEPENDENCIES.concat([ @@ -64,26 +65,55 @@ module.exports.statics = { * Creates a new stack pre-registered with compliant modules found in package.json */ autoStack: (priorityModules) => { - const pjson = require('./package.json'); const duniterModules = []; - - // Look for compliant packages - const prodDeps = Object.keys(pjson.dependencies); - const devDeps = Object.keys(pjson.devDependencies); - const duniterDeps = _.filter(prodDeps.concat(devDeps), (dep) => dep.match(/^duniter-/)); + let duniterDeps = [] + try { + const pjson = require(path.resolve('./package.json')) + // Look for compliant packages + const prodDeps = Object.keys(pjson.dependencies || {}); + const devDeps = Object.keys(pjson.devDependencies || {}); + duniterDeps = prodDeps.concat(devDeps) + } catch (e) { /* duniter as a dependency might not be run from an NPM project */ } for(const dep of duniterDeps) { - const required = require(dep); - if (required.duniter) { - duniterModules.push({ - name: dep, - required - }); - } + try { + const required = require(dep); + if (required.duniter) { + duniterModules.push({ + name: dep, + required + }); + } + } catch (e) { /* Silent errors for packages that fail to load */ } } // The final stack return new Stack((priorityModules || []).concat(PRODUCTION_DEPENDENCIES).concat(duniterModules)); - } + }, + + quickRun: function() { + const deps = Array.from(arguments).map((f, index) => { + const canonicalPath = path.resolve(f) + return { + name: 'duniter-quick-module-' + index, + required: require(canonicalPath) + } + }) + const that = this + const stack = this.autoStack(deps) + return co(function*() { + let res + try { + res = yield stack.executeStack(that.quickRunGetArgs()) + } catch(e) { + console.error(e) + } + that.onRunDone() + return res + }) + }, + + quickRunGetArgs: () => process.argv.slice(), + onRunDone: () => process.exit() }; function Stack(dependencies) { @@ -92,6 +122,8 @@ function Stack(dependencies) { const cli = require('./app/cli')(); const configLoadingCallbacks = []; const configBeforeSaveCallbacks = []; + const resetDataHooks = []; + const resetConfigHooks = []; const INPUT = new InputStream(); const PROCESS = new ProcessStream(); const loaded = {}; @@ -105,12 +137,15 @@ function Stack(dependencies) { neutral: [] }; + // Part of modules API + this.getModule = (name) => loaded[name] + this.registerDependency = (requiredObject, name) => { if (name && loaded[name]) { // Do not try to load it twice return; } - loaded[name] = true; + loaded[name] = requiredObject; const def = requiredObject.duniter; definitions.push(def); for (const opt of (def.cliOptions || [])) { @@ -137,6 +172,20 @@ function Stack(dependencies) { } } + /** + * Reset data/config injection + * ----------------------- + */ + if (def.onReset) { + if (def.onReset.data) { + resetDataHooks.push(def.onReset.data); + } + // Before the configuration is saved, the module can make some injection/cleaning + if (def.onReset.config) { + resetConfigHooks.push(def.onReset.config); + } + } + /** * Wizard injection * ----------------------- @@ -186,6 +235,18 @@ function Stack(dependencies) { }); }); + // Config or Data reset hooks + server.resetDataHook = () => co(function*() { + for (const callback of resetDataHooks) { + yield callback(server.conf, program, logger, server.dal.confDAL); + } + }) + server.resetConfigHook = () => co(function*() { + for (const callback of resetConfigHooks) { + yield callback(server.conf, program, logger, server.dal.confDAL); + } + }) + // Initialize server (db connection, ...) try { server.onPluggedFSHook = () => co(function*() { @@ -235,7 +296,7 @@ function Stack(dependencies) { return yield command.onConfiguredExecute(server, conf, program, params, wizardTasks, that); } // Second possible class of commands: post-service - yield server.initDAL(); + yield server.initDAL(conf); /** * Service injection diff --git a/install.sh b/install.sh index aaa56c55e50e89aa81581bc8db3f99baffb17dbd..23ffaa14422361d746252a19d872da8510179943 100755 --- a/install.sh +++ b/install.sh @@ -11,7 +11,7 @@ if [ -z "$DUNITER_DIR" ]; then fi latest_version() { - echo "v1.2.6" + echo "v1.3.8" } repo_url() { @@ -96,11 +96,7 @@ install_from_git() { NODE=$DUNITER_DIR/node/bin/node NPM=$DUNITER_DIR/node/bin/npm $NODE $NPM install - $NODE $NPM install duniter-bma@1.1.2 --save --production - $NODE $NPM install duniter-crawler@1.1.4 --save --production - $NODE $NPM install duniter-keypair@1.1.3 --save --production - $NODE $NPM install duniter-prover@1.1.2 --save --production - $NODE $NPM install duniter-ui@1.1.5 --production --save + [[ $? -eq 0 ]] && $NODE -e "const deps = require('./package.json').peerDependencies; Object.keys(deps).forEach(k => console.log(k + \"@\" + deps[k]))" | xargs $NODE $NPM install --save --production return } diff --git a/package.json b/package.json index 1a0cc05b4df827b1b0ab2ff01cc1f0daa57cdee9..533310452f5e0439230153992dd59ac069117a46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "duniter", - "version": "1.2.6", + "version": "1.3.8", "engines": { "node": ">=4.2.0", "npm": ">=2.11" @@ -9,14 +9,23 @@ "private": false, "description": "Crypto-currency software allowing to build P2P free currencies", "main": "index.js", + "node-main": "./bin/duniter", + "window": { + "icon": "duniter.png", + "title": "v1.3.8", + "width": 800, + "height": 800, + "min_width": 750, + "min_height": 400 + }, "directories": { "test": "test" }, "scripts": { - "test": "mocha --growl --timeout 20000 test test/fast test/fast/block test/integration test/", + "test": "mocha --growl --timeout 20000 test test/fast test/integration test/", "start": "node bin/duniter start", "build": "cd \"node_modules/duniter-ui\" && npm install && npm run build", - "test-travis": "node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec --timeout 20000 test test/fast test/fast/block test/integration test/" + "test-travis": "node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec --timeout 20000 test test/fast test/integration test/" }, "repository": { "type": "git", @@ -42,16 +51,14 @@ "colors": "1.1.2", "commander": "2.9.0", "daemonize2": "0.4.2", - "duniter-common": "^1.0.0", + "duniter-common": "^1.3.5", "event-stream": "3.3.4", "heapdump": "^0.3.9", "inquirer": "3.0.6", - "jison": "0.4.17", "merkle": "0.5.1", "moment": "2.18.1", "node-pre-gyp": "0.6.34", "optimist": "0.6.1", - "parallelshell": "2.0.0", "q": "1.5.0", "q-io": "1.13.2", "querablep": "^0.1.0", @@ -70,10 +77,11 @@ }, "devDependencies": { "coveralls": "2.11.4", - "duniter-bma": "1.1.2", - "duniter-crawler": "1.1.4", - "duniter-keypair": "1.1.3", - "duniter-prover": "1.1.2", + "duniter-bma": "1.3.x", + "duniter-crawler": "1.3.x", + "duniter-keypair": "1.3.X", + "duniter-prover": "^1.3.3", + "duniter-ui": "1.3.x", "eslint": "3.13.1", "eslint-plugin-mocha": "4.8.0", "istanbul": "0.4.0", @@ -85,6 +93,13 @@ "supertest": "", "tmp": "0.0.29" }, + "peerDependencies": { + "duniter-bma": "1.3.x", + "duniter-crawler": "1.3.x", + "duniter-keypair": "1.3.X", + "duniter-prover": "1.3.x", + "duniter-ui": "1.3.x" + }, "bin": { "duniter": "./bin/duniter" } diff --git a/release/arch/arm/build-arm.sh b/release/arch/arm/build-arm.sh index b054cab2639a64c793710aff7a4d5a7fbafebdfe..e7517c34b75ad6a08d59af7e3c3ab8913ab4e5f4 100755 --- a/release/arch/arm/build-arm.sh +++ b/release/arch/arm/build-arm.sh @@ -4,14 +4,8 @@ export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm -VER_UI=1.1.5 -VER_BMA=1.1.2 -VER_CRAWLER=1.1.4 -VER_PROVER=1.1.2 -VER_KEYPAIR=1.1.3 - # Prepare -ARCH="armv7l" +ARCH="`uname -m | sed -e \"s/86_//\"`" NVER="v6.10.2" # Folders @@ -72,11 +66,8 @@ SRC=`pwd` echo $SRC # Install modules -node/bin/npm install "duniter-bma@$VER_BMA" --save --production -node/bin/npm install "duniter-crawler@$VER_CRAWLER" --save --production -node/bin/npm install "duniter-keypair@$VER_KEYPAIR" --save --production -node/bin/npm install "duniter-prover@$VER_PROVER" --save --production -node/bin/npm install "duniter-ui@$VER_UI" --production --save +echo ">> VM: installing peerDependencies..." +node/bin/node -e "const deps = require('./package.json').peerDependencies; Object.keys(deps).forEach(k => console.log(k + \"@\" + deps[k]))" | xargs node/bin/npm i --production # Clean unused UI modules rm -Rf node_modules/duniter-ui/node_modules @@ -88,22 +79,22 @@ rm -Rf node_modules/duniter-ui/node_modules #mv node_modules/sqlite3/lib/binding/Release/node-v48-linux-x64 node_modules/sqlite3/lib/binding/Release/node-v48-linux-arm cd .. -mkdir -p duniter_release/sources -cp -R ${SRC}/* duniter_release/sources/ +mkdir -p duniter_release +cp -R ${SRC}/* duniter_release/ # Creating DEB packaging -mv duniter_release/sources/release/arch/debian/package duniter-${ARCH} +mv duniter_release/release/arch/debian/package duniter-${ARCH} mkdir -p duniter-${ARCH}/opt/duniter/ chmod 755 duniter-${ARCH}/DEBIAN/post* chmod 755 duniter-${ARCH}/DEBIAN/pre* sed -i "s/Version:.*/Version:$DUNITER_DEB_VER/g" duniter-${ARCH}/DEBIAN/control -cd duniter_release/sources +cd duniter_release pwd rm -Rf .git echo "Zipping..." zip -qr ../duniter-desktop.nw * -cd ../.. -mv duniter_release/duniter-desktop.nw duniter-${ARCH}/opt/duniter/ +cd ../ +mv duniter-desktop.nw duniter-${ARCH}/opt/duniter/ echo "Making package package" fakeroot dpkg-deb --build duniter-${ARCH} mv duniter-${ARCH}.deb "$INITIAL_DIRECTORY/duniter-server-v${DUNITER_VER}-linux-${ARCH}.deb" \ No newline at end of file diff --git a/release/arch/debian/build-deb.sh b/release/arch/debian/build-deb.sh index f230ae209c762287cbdaa6b855ef3c1082eb8420..9a052556de730e8aab447ada9f71df26a5e8c691 100644 --- a/release/arch/debian/build-deb.sh +++ b/release/arch/debian/build-deb.sh @@ -4,12 +4,6 @@ export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm -VER_UI=1.1.5 -VER_BMA=1.1.2 -VER_CRAWLER=1.1.4 -VER_PROVER=1.1.2 -VER_KEYPAIR=1.1.3 - # Prepare NVER=`node -v` DUNITER_TAG= @@ -81,17 +75,12 @@ cd ${RELEASES}/duniter # Remove git files rm -Rf .git [[ $? -eq 0 ]] && echo ">> VM: building modules..." -[[ $? -eq 0 ]] && yarn +[[ $? -eq 0 ]] && yarn --production #[[ $? -eq 0 ]] && echo ">> VM: running tests..." #[[ $? -eq 0 ]] && yarn test -# Clean test and UI packages -[[ $? -eq 0 ]] && echo ">> VM: removing duniter dev modules..." -yarn remove duniter-bma duniter-crawler duniter-keypair duniter-prover --save -[[ $? -eq 0 ]] && echo ">> VM: adding duniter modules..." -yarn add "duniter-ui@$VER_UI" "duniter-bma@$VER_BMA" "duniter-crawler@$VER_CRAWLER" "duniter-keypair@$VER_KEYPAIR" "duniter-prover@$VER_PROVER" --save --production -rm -rf node_modules yarn.lock -yarn --production +[[ $? -eq 0 ]] && node -e "const deps = require('./package.json').peerDependencies; Object.keys(deps).forEach(k => console.log(k + \"@\" + deps[k]))" | xargs yarn add --production + # Specific modules that are not needed in a release rm -rf node_modules/materialize-css @@ -150,11 +139,27 @@ mkdir -p "$RELEASES/desktop_release" # Build Desktop version .tar.gz # ------------------------------------------------- -cp -r "$DOWNLOADS/${NW}" "$RELEASES/desktop_release/nw" -cp ${RELEASES}/desktop_/gui/* "$RELEASES/desktop_release/nw/" -cp -R "$RELEASES/desktop_/" "$RELEASES/desktop_release/sources/" +cp -r $DOWNLOADS/${NW}/* "$RELEASES/desktop_release/" +# Embed Node.js with Nw.js to make Duniter modules installable +cp -r ${DOWNLOADS}/node-${NVER}-linux-x64/lib "$RELEASES/desktop_release/" +cp -r ${DOWNLOADS}/node-${NVER}-linux-x64/include "$RELEASES/desktop_release/" +cp -r ${DOWNLOADS}/node-${NVER}-linux-x64/bin "$RELEASES/desktop_release/" +# Add some specific files for GUI +cp ${RELEASES}/desktop_/gui/* "$RELEASES/desktop_release/" +# Add Duniter sources +cp -R $RELEASES/desktop_/* "$RELEASES/desktop_release/" +## Insert Nw specific fields while they do not exist (1.3.3) +sed -i "s/\"main\": \"index.js\",/\"main\": \"index.html\",/" "$RELEASES/desktop_release/package.json" +# Add links for Node.js + NPM +cd "$RELEASES/desktop_release/bin" +ln -s ../lib/node_modules/npm/bin/npm-cli.js ./npm -f +cd .. +ln -s ./bin/node node -f +ln -s ./bin/npm npm -f +#sed -i "s/\"node-main\": \"\.\.\/sources\/bin\/duniter\",/\"node-main\": \".\/bin\/duniter\",/" "$RELEASES/desktop_release/package.json" +# Create a copy for TGZ binary cp -R "$RELEASES/desktop_release" "$RELEASES/desktop_release_tgz" -#cd "$RELEASES/desktop_release_tgz/sources/" +#cd "$RELEASES/desktop_release_tgz/" #rm -rf node_modules/sqlite3/lib/binding/node-webkit-$NW_RELEASE-linux-x64 #rm -rf node_modules/wotb/lib/binding/Release/node-webkit-$NW_RELEASE-linux-x64 #rm -rf node_modules/naclb/lib/binding/Release/node-webkit-$NW_RELEASE-linux-x64 @@ -167,12 +172,13 @@ tar czf /vagrant/duniter-desktop-${DUNITER_TAG}-linux-x64.tar.gz * --exclude ".g # ------------------------------------------------- # Create .deb tree + package it -cp -r "$RELEASES/desktop_release/sources/release/arch/debian/package" "$RELEASES/duniter-x64" +#cp -r "$RELEASES/desktop_release/release/arch/debian/package" "$RELEASES/duniter-x64" +cp -r "/vagrant/package" "$RELEASES/duniter-x64" mkdir -p "$RELEASES/duniter-x64/opt/duniter/" chmod 755 ${RELEASES}/duniter-x64/DEBIAN/post* chmod 755 ${RELEASES}/duniter-x64/DEBIAN/pre* sed -i "s/Version:.*/Version:$DUNITER_DEB_VER/g" ${RELEASES}/duniter-x64/DEBIAN/control -cd ${RELEASES}/desktop_release/sources +cd ${RELEASES}/desktop_release/ #rm -rf node_modules/sqlite3/lib/binding/node-webkit-$NW_RELEASE-linux-x64 #rm -rf node_modules/wotb/lib/binding/Release/node-webkit-$NW_RELEASE-linux-x64 #rm -rf node_modules/naclb/lib/binding/Release/node-webkit-$NW_RELEASE-linux-x64 @@ -182,8 +188,6 @@ cd ${RELEASES}/desktop_release/sources #rm -rf node_modules/naclb/lib/binding/Release/node-v$ADDON_VERSION-linux-x64 #rm -rf node_modules/scryptb/lib/binding/Release/node-v$ADDON_VERSION-linux-x64 zip -qr ${RELEASES}/duniter-x64/opt/duniter/duniter-desktop.nw * -cd ${RELEASES}/desktop_release/nw -zip -qr ${RELEASES}/duniter-x64/opt/duniter/nw.nwb * sed -i "s/Package: .*/Package: duniter-desktop/g" ${RELEASES}/duniter-x64/DEBIAN/control cd ${RELEASES}/ @@ -199,7 +203,7 @@ rm -rf duniter-server-x64 cp -r duniter-x64 duniter-server-x64 # Remove Nw.js -rm -rf duniter-server-x64/opt/duniter/nw* +rm -rf duniter-server-x64/opt/duniter/duniter-desktop.nw* cd ${RELEASES}/server_ cp -r ${DOWNLOADS}/node-${NVER}-linux-x64 node diff --git a/release/arch/debian/package/DEBIAN/control b/release/arch/debian/package/DEBIAN/control index 95e72440b7c7d64180309a6d76a09a04518edd8d..0886b9e75d8c90a5dd8df949d391af90ce5a71ba 100644 --- a/release/arch/debian/package/DEBIAN/control +++ b/release/arch/debian/package/DEBIAN/control @@ -1,5 +1,5 @@ Package: duniter -Version: 1.2.6 +Version: 1.3.8 Section: misc Priority: optional Architecture: all diff --git a/release/arch/debian/package/DEBIAN/postinst b/release/arch/debian/package/DEBIAN/postinst index 8ab67ea178b85d572ce99e193a7519f94e30cd2b..8938ddb32899360b05791ebe244a871f88765bd0 100755 --- a/release/arch/debian/package/DEBIAN/postinst +++ b/release/arch/debian/package/DEBIAN/postinst @@ -1,30 +1,39 @@ #!/bin/bash DUN_ROOT=/opt/duniter -DUN_SOURCES=$DUN_ROOT/sources -DUN_NW=$DUN_ROOT/nw +DUN_SOURCES=$DUN_ROOT/ mkdir -p $DUN_SOURCES -# Duniter sources +# Duniter sources extraction if [[ -f $DUN_ROOT/duniter-desktop.nw ]]; then unzip -q -d $DUN_SOURCES/ $DUN_ROOT/duniter-desktop.nw + rm -rf $DUN_ROOT/duniter-desktop.nw fi # Duniter-Desktop -if [[ -f $DUN_ROOT/nw.nwb ]]; then - unzip -q -d $DUN_NW $DUN_ROOT/nw.nwb - cp -R $DUN_SOURCES/gui/* $DUN_NW/ - chmod +x $DUN_NW/nw $DUN_NW/lib $DUN_NW/locales - ln -s $DUN_NW/nw /usr/bin/duniter-desktop +if [[ -f $DUN_SOURCES/nw ]]; then + chmod +x $DUN_SOURCES/nw $DUN_SOURCES/lib $DUN_SOURCES/locales + chmod +rw $DUN_SOURCES/nw $DUN_SOURCES/lib $DUN_SOURCES/locales + ln -s $DUN_SOURCES/nw /usr/bin/duniter-desktop sed -i "s/DEB_PACKAGING=.*/DEB_PACKAGING=true/g" $DUN_SOURCES/duniter.sh + # Links for Node + NPM + cd $DUN_SOURCES + cd bin + ln -s ../lib/node_modules/npm/bin/npm-cli.js ./npm -f + cd .. + ln -s ./bin/node node -f + ln -s ./bin/npm npm -f fi # Duniter CLI executes with embedded node if [[ -d $DUN_SOURCES/node ]]; then chmod 755 $DUN_SOURCES/bin/duniter - sed -i "s/usr\/bin\/env node/opt\/duniter\/sources\/node\/bin\/node/g" $DUN_SOURCES/bin/duniter + sed -i "s/usr\/bin\/env node/opt\/duniter\/node\/bin\/node/g" $DUN_SOURCES/bin/duniter sed -i "s/DEB_PACKAGING=.*/DEB_PACKAGING=true/g" $DUN_SOURCES/duniter.sh - ln -s $DUN_SOURCES/duniter.sh /usr/bin/duniter + ln -s $DUN_SOURCES/duniter.sh /usr/bin/duniter -f + cd $DUN_SOURCES + cd node/bin/ + ln -s ../lib/node_modules/npm/bin/npm-cli.js ./npm -f fi # Else will execute with environment node diff --git a/release/arch/debian/package/usr/share/applications/duniter.desktop b/release/arch/debian/package/usr/share/applications/duniter.desktop index 9f25ff4657325871a94e5b0095f9ed149cadbb7c..5c68dde73dff49f857ff8d6b4f2351d35515ef3a 100644 --- a/release/arch/debian/package/usr/share/applications/duniter.desktop +++ b/release/arch/debian/package/usr/share/applications/duniter.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Name=Duniter Desktop Exec=duniter-desktop -Icon=/opt/duniter/nw/duniter.png +Icon=/opt/duniter/duniter.png Type=Application Categories=Utility diff --git a/release/arch/windows/build.bat b/release/arch/windows/build.bat index f519fd6fa9ee144a6061fda59655208268faa579..9be0fd426059b43ab917541ef7b78176b6b4873f 100644 --- a/release/arch/windows/build.bat +++ b/release/arch/windows/build.bat @@ -1,18 +1,22 @@ -set VER_UI=1.1.5 -set VER_BMA=1.1.2 -set VER_CRAWLER=1.1.4 -set VER_PROVER=1.1.2 -set VER_KEYPAIR=1.1.3 +set DUNITER_BRANCH=1.3.x +set VER_UI=%DUNITER_BRANCH% +set VER_BMA=%DUNITER_BRANCH% +set VER_CRAWLER=%DUNITER_BRANCH% +set VER_PROVER=%DUNITER_BRANCH% +set VER_KEYPAIR=%DUNITER_BRANCH% set ADDON_VERSION=48 set NW_VERSION=0.17.6 +set NODEJS_VERSION=6.11.0 + set NW_RELEASE=v0.17.6 set NW=nwjs-%NW_RELEASE%-win-x64 set NW_GZ=%NW%.zip -echo %NW% -echo %NW_GZ% -echo %NW_RELEASE% + +set NODE_RELEASE=v%NODEJS_VERSION% +set NODE=node-v%NODEJS_VERSION%-win-x64 +set NODE_ZIP=node-v%NODEJS_VERSION%-win-x64.zip node -v REM NPM @@ -21,6 +25,13 @@ REM InnoSetup set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH% cd C:\Users\vagrant + +if not exist %NODE_ZIP% ( + echo "Telechargement de %NODE_ZIP%..." + powershell -Command "(New-Object System.Net.WebClient).DownloadFile(\"https://nodejs.org/dist/%NODE_RELEASE%/%NODE_ZIP%\", \"%NODE_ZIP%\")" + call 7z x %NODE_ZIP% +) + echo "Suppression des anciennes sources..." rd /s /q duniter rd /s /q duniter_release @@ -35,19 +46,27 @@ echo %DUNITER_TAG% git checkout %DUNITER_TAG% -call npm install +call npm cache clean +call npm install --production REM call npm test - echo "Retrait des modules 'dev'..." call npm prune --production -echo "Ajout du module 1/4..." +echo "Ajout du module 1/5..." call npm install duniter-bma@%VER_BMA% --save --production -echo "Ajout du module 2/4..." +echo "Ajout du module 2/5..." call npm install duniter-crawler@%VER_CRAWLER% --save --production -echo "Ajout du module 3/4..." +echo "Ajout du module 3/5..." call npm install duniter-keypair@%VER_KEYPAIR% --save --production -echo "Ajout du module 4/4..." +echo "Ajout du module 4/5..." call npm install duniter-prover@%VER_PROVER% --save --production +echo "Ajout du module 5/5..." +call npm install duniter-ui@%VER_UI% --save --production + +REM echo ">> VM: installing peerDependencies installer..." +REM call npm i --save-dev @team-griffin/install-self-peers +REM echo ">> VM: installing peerDependencies..." +REM call ./node_modules/.bin/install-self-peers --npm -- --production + set SRC=%cd% echo %SRC% cd node_modules/wotb @@ -73,16 +92,18 @@ copy %cd%\lib\binding\node-webkit-%NW_RELEASE%-win32-x64\node_sqlite3.node %cd%\ cd ../heapdump call nw-gyp --target=%NW_VERSION% --msvs_version=2015 configure call nw-gyp --target=%NW_VERSION% --msvs_version=2015 build -cd ../.. -call npm install duniter-ui@%VER_UI% --save --production -rd /s /q %cd%\node_modules\duniter-ui\node_modules -cd .. +cd ../../.. mkdir duniter_release +mkdir duniter_release\nodejs call 7z x %NW_GZ% -move %NW% %cd%\duniter_release\nw -mkdir %cd%\duniter_release\sources -xcopy %SRC%\gui\* %cd%\duniter_release\nw\ /s /e -xcopy %SRC%\* %cd%\duniter_release\sources\ /s /e -iscc %cd%\duniter_release\sources\release\arch\windows\duniter.iss /DROOT_PATH=%cd%\duniter_release +xcopy %NW%\* %cd%\duniter_release\ /s /e /Y +xcopy %SRC%\gui\* %cd%\duniter_release\ /s /e /Y +xcopy %SRC%\* %cd%\duniter_release\ /s /e /Y +xcopy %NODE%\* %cd%\duniter_release\nodejs\ /s /e /Y +cd duniter_release +powershell -Command "(Get-Content package.json) | foreach-object {$_ -replace '\"main\": \"index.js\",','\"main\": \"index.html\",' } | Set-Content package.json2" +move /y package.json2 package.json +cd .. +iscc C:\vagrant\duniter.iss /DROOT_PATH=%cd%\duniter_release move %cd%\duniter_release\Duniter.exe C:\vagrant\duniter-desktop-%DUNITER_TAG%-windows-x64.exe echo "Build done: binary available at duniter-desktop-%DUNITER_TAG%-windows-x64.exe" diff --git a/release/arch/windows/duniter.iss b/release/arch/windows/duniter.iss index 5ff020ee562b0b673351f1b7638a6155908fca64..3b1f268ff94f88bf8e94b279dfb25e3f33183bba 100644 --- a/release/arch/windows/duniter.iss +++ b/release/arch/windows/duniter.iss @@ -8,14 +8,14 @@ #endif #define MyAppSrc ROOT_PATH -#define MyAppExe ROOT_PATH + "\nw\" + MyAppExeName +#define MyAppExe ROOT_PATH + "\" + MyAppExeName #pragma message MyAppSrc #if !FileExists(MyAppExe) #error "Unable to find MyAppExe" #endif -#define MyAppVerStr "v1.2.6" +#define MyAppVerStr "v1.3.8" [Setup] AppName={#MyAppName} @@ -32,7 +32,7 @@ OutputDir={#ROOT_PATH} OutputBaseFilename={#MyAppName} Compression=lzma SolidCompression=yes -UninstallDisplayIcon={app}\nw\{#MyAppExeName} +UninstallDisplayIcon={app}\{#MyAppExeName} ArchitecturesInstallIn64BitMode=x64 [Languages] @@ -43,23 +43,22 @@ Name: "french"; MessagesFile: "compiler:Languages\French.isl" Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked [Files] -Source: "{#MyAppSrc}\nw\*"; DestDir: "{app}\nw\"; Flags: ignoreversion recursesubdirs -Source: "{#MyAppSrc}\sources\*"; DestDir: "{app}\sources\"; Flags: ignoreversion recursesubdirs +Source: "{#MyAppSrc}\*"; DestDir: "{app}\"; Flags: ignoreversion recursesubdirs [Icons] -Name: "{group}\{#MyAppName}"; IconFilename: "{app}\nw\duniter.ico"; Filename: "{app}\nw\{#MyAppExeName}" +Name: "{group}\{#MyAppName}"; IconFilename: "{app}\duniter.ico"; Filename: "{app}\{#MyAppExeName}" Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" -Name: "{commondesktop}\{#MyAppName}"; IconFilename: "{app}\nw\duniter.ico"; Filename: "{app}\nw\{#MyAppExeName}"; Tasks: desktopicon +Name: "{commondesktop}\{#MyAppName}"; IconFilename: "{app}\duniter.ico"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon [Run] -Filename: "{app}\nw\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent [Setup] ; NOTE: The value of AppId uniquely identifies this application. ; Do not use the same AppId value in installers for other applications. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) AppId={{E01B0960-74D2-8ACD-734E-8B3CB033B07F} -LicenseFile="{#MyAppSrc}\sources\LICENSE" +LicenseFile="{#MyAppSrc}\LICENSE" [Code] diff --git a/release/new_version.sh b/release/new_version.sh index 4ada664b58c60f007173b8fd7fe4f2983f94c50d..67bddca85de65eea143f267749e5bc67734ef879 100755 --- a/release/new_version.sh +++ b/release/new_version.sh @@ -16,8 +16,7 @@ if [[ $1 =~ ^[0-9]+.[0-9]+.[0-9]+((a|b)[0-9]+)?$ ]]; then sed -i "s/define MyAppVerStr.*/define MyAppVerStr \"v$1\"/g" release/arch/windows/duniter.iss # GUI containers version - sed -i "s/name\": .*/name\": \"v$1\",/g" gui/package.json - sed -i "s/title\": .*/title\": \"v$1\",/g" gui/package.json + sed -i "s/title\": .*/title\": \"v$1\",/g" package.json sed -i "s/<title>Duniter.*<\/title>/<title>Duniter $1<\/title>/g" gui/index.html # Bump the install.sh @@ -25,7 +24,7 @@ if [[ $1 =~ ^[0-9]+.[0-9]+.[0-9]+((a|b)[0-9]+)?$ ]]; then # Commit git reset HEAD - git add install.sh package.json test/integration/branches.js gui/package.json gui/index.html release/arch/debian/package/DEBIAN/control install.sh release/arch/windows/duniter.iss + git add install.sh package.json test/integration/branches.js gui/index.html release/arch/debian/package/DEBIAN/control install.sh release/arch/windows/duniter.iss git commit -m "v$1" git tag "v$1" else diff --git a/server.js b/server.js index e8cb1a2dc305528b209ee64b42e59630c63e9253..602031142119b9e26990b91a2fd8a5f5a21d32ca 100644 --- a/server.js +++ b/server.js @@ -9,7 +9,7 @@ const archiver = require('archiver'); const unzip = require('unzip2'); const fs = require('fs'); const daemonize = require("daemonize2") -const parsers = require('./app/lib/streams/parsers'); +const parsers = require('duniter-common').parsers; const constants = require('./app/lib/constants'); const fileDAL = require('./app/lib/dal/fileDAL'); const jsonpckg = require('./package.json'); @@ -30,27 +30,6 @@ function Server (home, memoryOnly, overrideConf) { that.version = jsonpckg.version; that.logger = logger; - // External libs - that.lib = {}; - that.lib.keyring = require('duniter-common').keyring; - that.lib.Identity = require('./app/lib/entity/identity'); - that.lib.Certification = require('./app/lib/entity/certification'); - that.lib.Transaction = require('./app/lib/entity/transaction'); - that.lib.Peer = require('./app/lib/entity/peer'); - that.lib.Membership = require('./app/lib/entity/membership'); - that.lib.Block = require('./app/lib/entity/block'); - that.lib.Stat = require('./app/lib/entity/stat'); - that.lib.rawer = require('duniter-common').rawer; - that.lib.parsers = require('./app/lib/streams/parsers'); - that.lib.http2raw = require('duniter-bma').duniter.methods.http2raw; - that.lib.dos2unix = require('duniter-common').dos2unix; - that.lib.bma = require('duniter-bma').duniter.methods.bma; - that.lib.constants = require('./app/lib/constants'); - that.lib.ucp = require('duniter-common').buid; - that.lib.hashf = require('duniter-common').hashf; - that.lib.indexer = require('./app/lib/dup/indexer'); - that.lib.rules = require('./app/lib/rules'); - that.MerkleService = require("./app/lib/helpers/merkle"); that.IdentityService = require('./app/service/IdentityService')(); that.MembershipService = require('./app/service/MembershipService')(); @@ -110,6 +89,7 @@ function Server (home, memoryOnly, overrideConf) { ud0: constants.CONTRACT.DEFAULT.UD0, stepMax: constants.CONTRACT.DEFAULT.STEPMAX, sigPeriod: constants.CONTRACT.DEFAULT.SIGPERIOD, + msPeriod: constants.CONTRACT.DEFAULT.MSPERIOD, sigStock: constants.CONTRACT.DEFAULT.SIGSTOCK, sigWindow: constants.CONTRACT.DEFAULT.SIGWINDOW, sigValidity: constants.CONTRACT.DEFAULT.SIGVALIDITY, @@ -131,6 +111,13 @@ function Server (home, memoryOnly, overrideConf) { that.conf[key] = defaultValues[key]; } }); + // 1.3.X: the msPeriod = msWindow + that.conf.msPeriod = that.conf.msPeriod || that.conf.msWindow + // Default keypair + if (!that.conf.pair || !that.conf.pair.pub || !that.conf.pair.sec) { + // Create a random key + that.conf.pair = keyring.randomKey().json() + } // Extract key pair that.keyPair = keyring.Key(that.conf.pair.pub, that.conf.pair.sec); that.sign = that.keyPair.sign; @@ -187,8 +174,8 @@ function Server (home, memoryOnly, overrideConf) { this.submitP = (obj, isInnerWrite) => Q.nbind(this.submit, this)(obj, isInnerWrite); - this.initDAL = () => co(function*() { - yield that.dal.init(); + this.initDAL = (conf) => co(function*() { + yield that.dal.init(conf); // Maintenance let head_1 = yield that.dal.bindexDAL.head(1); if (head_1) { @@ -225,22 +212,26 @@ function Server (home, memoryOnly, overrideConf) { }); this.resetAll = (done) => co(function*() { + yield that.resetDataHook() + yield that.resetConfigHook() const files = ['stats', 'cores', 'current', directory.DUNITER_DB_NAME, directory.DUNITER_DB_NAME + '.db', directory.DUNITER_DB_NAME + '.log', directory.WOTB_FILE, 'export.zip', 'import.zip', 'conf']; const dirs = ['blocks', 'blockchain', 'ud_history', 'branches', 'certs', 'txs', 'cores', 'sources', 'links', 'ms', 'identities', 'peers', 'indicators', 'leveldb']; return resetFiles(files, dirs, done); }); this.resetData = (done) => co(function*(){ + yield that.resetDataHook() const files = ['stats', 'cores', 'current', directory.DUNITER_DB_NAME, directory.DUNITER_DB_NAME + '.db', directory.DUNITER_DB_NAME + '.log', directory.WOTB_FILE]; const dirs = ['blocks', 'ud_history', 'branches', 'certs', 'txs', 'cores', 'sources', 'links', 'ms', 'identities', 'peers', 'indicators', 'leveldb']; yield resetFiles(files, dirs, done); }); - this.resetConf = (done) => { + this.resetConf = (done) => co(function*() { + yield that.resetConfigHook() const files = ['conf']; const dirs = []; return resetFiles(files, dirs, done); - }; + }); this.resetStats = (done) => { const files = ['stats']; @@ -364,7 +355,7 @@ function Server (home, memoryOnly, overrideConf) { this.writeRaw = (raw, type) => co(function *() { const parser = documentsMapping[type] && documentsMapping[type].parser; - const obj = parser.syncWrite(raw); + const obj = parser.syncWrite(raw, logger); return yield that.singleWritePromise(obj); }); @@ -380,12 +371,14 @@ function Server (home, memoryOnly, overrideConf) { */ this.getDaemon = function getDaemon(overrideCommand, insteadOfCmd) { const mainModule = process.argv[1] + const cwd = path.resolve(mainModule, '../..') const argv = getCommand(overrideCommand, insteadOfCmd) return daemonize.setup({ main: mainModule, name: directory.INSTANCE_NAME, pidfile: path.join(directory.INSTANCE_HOME, "app.pid"), - argv + argv, + cwd }); } @@ -455,10 +448,20 @@ function Server (home, memoryOnly, overrideConf) { */ this.generatorNewCertsToLinks = () => Promise.resolve({}) - /* + /** * Default hook on file system plugging. To be overriden by module system. */ this.onPluggedFSHook = () => Promise.resolve({}) + + /** + * Default hook on data reset. To be overriden by module system. + */ + this.resetDataHook = () => Promise.resolve({}) + + /** + * Default hook on data reset. To be overriden by module system. + */ + this.resetConfigHook = () => Promise.resolve({}) } util.inherits(Server, stream.Duplex); diff --git a/test/dal/dal.js b/test/dal/dal.js index 6be1ca575fcbee7d416eb0130241dedaeb56be8c..e31968f1e53848ef2254f9b8991987434e3076f2 100644 --- a/test/dal/dal.js +++ b/test/dal/dal.js @@ -100,10 +100,10 @@ describe("DAL", function(){ return fileDAL.saveConf({ currency: "meta_brouzouf" }); })); - it('should have DB version 20', () => co(function *() { + it('should have DB version 21', () => co(function *() { let version = yield fileDAL.getDBVersion(); should.exist(version); - version.should.equal(20); + version.should.equal(22); })); it('should have no peer in a first time', function(){ diff --git a/test/dal/source_dal.js b/test/dal/source_dal.js index 3b5cf3286c287df9f8ceecb2a3fcd54b3c5d18d5..7458cbfc0a4142aeff095311dadf9aeab2251778 100644 --- a/test/dal/source_dal.js +++ b/test/dal/source_dal.js @@ -3,7 +3,7 @@ const co = require('co'); const should = require('should'); const FileDAL = require('../../app/lib/dal/fileDAL'); const dir = require('../../app/lib/system/directory'); -const indexer = require('../../app/lib/dup/indexer'); +const indexer = require('duniter-common').indexer; const toolbox = require('../integration/tools/toolbox'); let dal; diff --git a/test/dal/triming.js b/test/dal/triming.js index 0014c17a0373739bf4cf75ef596c24d96e6e414d..f6091a019fca1c31c9950cc61f73e2248b97b437 100644 --- a/test/dal/triming.js +++ b/test/dal/triming.js @@ -3,7 +3,7 @@ const co = require('co'); const should = require('should'); const FileDAL = require('../../app/lib/dal/fileDAL'); const dir = require('../../app/lib/system/directory'); -const indexer = require('../../app/lib/dup/indexer'); +const indexer = require('duniter-common').indexer; const toolbox = require('../integration/tools/toolbox'); let dal; diff --git a/test/data/blocks.js b/test/data/blocks.js deleted file mode 100644 index 9500a38f7f5a1590a00cde7a914e941313ea54fc..0000000000000000000000000000000000000000 --- a/test/data/blocks.js +++ /dev/null @@ -1,4100 +0,0 @@ - -module.exports = { - WRONG_SIGNATURE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 50\n" + - "PoWMin: 1\n" + - "Time: 1411775999\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - VALID_ROOT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: duniter_unit_test_currency\n" + - "Number: 0\n" + - "PoWMin: 0\n" + - "Time: 1483614905\n" + - "MedianTime: 1483614905\n" + - "UnitBase: 0\n" + - "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\n" + - "IssuersFrame: 1\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 0\n" + - "Parameters: 0.007376575:3600:120:0:40:604800:31536000:1:604800:604800:0.9:31536000:3:20:960:10:0.6666666666666666:1483614905:1483614905:100\n" + - "MembersCount: 2\n" + - "Identities:\n" + - "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tic\n" + - "DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:lcekuS0eP2dpFL99imJcwvDAwx49diiDMkG8Lj7FLkC/6IJ0tgNjUzCIZgMGi7bL5tODRiWi9B49UMXb8b3MAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tic\n" + - "DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:80pUx9YBk0RwqrVrQQA+PuxoNn21A8NwQ3824CQPU1ad9R1oDXc/pU6NVpQv92LM8gaWs/Pm1mLXNNVnr+m6BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:0:vMaYgBSnU+83AYOVQCZAx1XLpg/F1MmMztDfCnZvl8hPs4LE9tcDvCrrFogAwMEW2N7Y0gCH62/fBMgw4KrGCA==\n" + - "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:0:RKIGMgYIhB9FmjPbmyo4egPufg/iTpBznYGZp5hjK1WZ1a9imQldLNUMe0eiPlSKJTK/JD3gOlCiynOEY2csBA==\n" + - "Transactions:\n" + - "InnerHash: 7A4E76A9A3410594AC9AED94B14AD9892426D76EDAF735CFE6C66432E422A63F\n" + - "Nonce: 300000000001\n" + - "WJourHkd6NnMxKDSEfrsiB7qE0mGbiFHSwy0cE8/q/is6hTd0mzlMNBPxDhoPkAiocfXJrQuIVeG0/ygxQrTBw==\n", - - WRONG_PROOF_OF_WORK: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 1\n" + - "PoWMin: 17\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 97E7DBF5D3AC27A4AFB797365304B7922917B6ADCDEFD736F20E38ADE982A47D\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - ROOT_WITHOUT_PARAMETERS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 0\n" + - "Time: 1411775999\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 1\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - NON_ROOT_WITH_PARAMETERS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 5\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "Parameters: 0.7376575:100:157680000:0:40:7200:31536000:1:1000:1000:0.9:31536000:3:1:60:10:0.67:1511776000:1511776000:1511776000\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - ROOT_WITH_PREVIOUS_HASH: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855\n" + - "MembersCount: 0\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - ROOT_WITH_PREVIOUS_ISSUER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - NON_ROOT_WITHOUT_PREVIOUS_HASH: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 1\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - NON_ROOT_WITHOUT_PREVIOUS_ISSUER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 1\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 97E7DBF5D3AC27A4AFB797365304B7922917B6ADCDEFD736F20E38ADE982A47D\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - COLLIDING_UIDS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:NJE8nYU4Im+KQDRdoAn5gcfic+Gjjzp0Pp0iji/Fzh9JIThoQeUDDew4Q5vJBEg/Aw7gPnIg+11TbLkIGa/ODQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - COLLIDING_PUBKEYS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:NJE8nYU4Im+KQDRdoAn5gcfic+Gjjzp0Pp0iji/Fzh9JIThoQeUDDew4Q5vJBEg/Aw7gPnIg+11TbLkIGa/ODQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_DATE_LOWER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 50\n" + - "PoWMin: 1\n" + - "Time: 1411775999\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_DATE_HIGHER_BUT_TOO_FEW: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 10\n" + - "PoWMin: 1\n" + - "Time: 1411776059\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_DATE_HIGHER_BUT_TOO_HIGH: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 10\n" + - "PoWMin: 1\n" + - "Time: 1411785481\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_ROOT_TIMES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776001\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - GOOD_DATE_HIGHER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 20\n" + - "PoWMin: 1\n" + - "Time: 1411776060\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_IDTY_MATCH_JOINS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - MULTIPLE_JOINERS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 1\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - MULTIPLE_ACTIVES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 1\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - MULTIPLE_LEAVES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - MULTIPLE_EXCLUDED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - MULTIPLE_OVER_ALL: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - MULTIPLE_CERTIFICATIONS_FROM_SAME_ISSUER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 2\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - IDENTICAL_CERTIFICATIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - LEAVER_WITH_CERTIFICATIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:I9kYCknNTp9zYS4CflAMk4Xh1yQIaP1H3PgPHJeQZQNkBavyqddXsq5DUzscsi2kRttJw6C/MATSD8KyZYPNAg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - EXCLUDED_WITH_CERTIFICATIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONGLY_SIGNED_IDENTITIES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:Die9lYNW1u/w50AfuaXwb4MJc3aKA3WfJwiy531TqHIGC+VNnRKjMmrwMptN+a+dL6INjLrhMrPqoK60IkTlDQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONGLY_SIGNED_JOIN: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV3Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONGLY_SIGNED_ACTIVE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV3Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONGLY_SIGNED_LEAVE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:I9kYCknNTp9zYS4CflAMk4Xh1yQIaP1H3PgPHJeQZQNkBavyqddXsq5DUzscsi2kRttJw6C/MATSD8KyZYPNAg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - CORRECTLY_SIGNED_LEAVE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:I9kYCknNTp9zYS4CflAMk4Xh1yQIaP1H3PgPHJeQZQNkBavyqddXsq5DUzscsi2kRttJw6C/MATSD8KyZYPNAg==:1411850496\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONGLY_SIGNED_CERTIFICATION: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 29890\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:vTvKYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - UNKNOWN_CERTIFIER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:vTvKYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - UNKNOWN_CERTIFIED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:1411844654:vTvKYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - EXISTING_UID: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:Die9lYNW1u/w50AfuaXwb4MJc3aKA3WfJwiy+31TqHIGC+VNnRKjMmrwMptN+a+dL6INjLrhMrPqoK60IkTlDQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:EXISTING\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - EXISTING_PUBKEY: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH:Die9lYNW1u/w50AfuaXwb4MJc3aKA3WfJwiy+31TqHIGC+VNnRKjMmrwMptN+a+dL6INjLrhMrPqoK60IkTlDQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TOO_EARLY_CERTIFICATION_REPLAY: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:Die9lYNW1u/w50AfuaXwb4MJc3aKA3WfJwiy+31TqHIGC+VNnRKjMmrwMptN+a+dL6INjLrhMrPqoK60IkTlDQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:1411844654:vTvKYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:1411844658:2KmmmIL8eK/TACjOqTqO5ZG/tgMYWWV8zRICWFQJuqWyYVg/y5wzXyHrgfpdMYhwYMRBhwbMk1sPNLo/kzp0AA==\n" + - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:DU4JlHxJtIb2Z7Ag4Jy+z0qjNNo5jzN5EvTUWOTRRzeb6LbOClw2X+pmb0mV/wpVKd/lJrUHAWeKMDHG4MukCA==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:kr2JA6wCGfbNKGpyM86BscsFk22aA9oiAon8mWRPl4G8UpJKZs3tjuPRAw5+04KLCRWl/TT1TumDCkeEjev7DA==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - EXPIRED_CERTIFICATIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 90\n" + - "PoWMin: 1\n" + - "Time: 1443333600\n" + - "MedianTime: 1443333600\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Joiners:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:70:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - EXPIRED_MEMBERSHIP: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 90\n" + - "PoWMin: 1\n" + - "Time: 1443333600\n" + - "MedianTime: 1443333600\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Joiners:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:70-5918CE7F40186F8E0BD8F239986A723FCC329927B999885B32DAAE40EA8BEDB6:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REVOKED_JOINER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 113\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - NOT_ENOUGH_CERTIFICATIONS_JOINER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 3\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - NOT_ENOUGH_CERTIFICATIONS_JOINER_BLOCK_0: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - OUTDISTANCED_JOINER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 3\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-0C1C080CA81F6D763C6C42B7D043DF40DDABC2E27D47E0FE27DEF0E65D795280:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - VALID_NEXT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 3\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 5\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_PREVIOUS_HASH: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 97E7DBF5D3AC27A4AFB797365304B7922917B6ADCDEFD736F20E38ADE982A47D\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_PREVIOUS_ISSUER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_DIFFERENT_ISSUERS_COUNT_FOLLOWING_V2: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_DIFFERENT_ISSUERS_COUNT_FOLLOWING_V3: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_ISSUERS_FRAME_FOLLOWING_V2: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_ISSUERS_FRAME_FOLLOWING_V3: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_ISSUER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_JOIN_BLOCK_TARGET_ROOT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:44-9F118AC87B062F23F193761E081082BB661547CF9A0C243CD3994E99C78A74C3:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_JOIN_ROOT_NUMBER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:44-9F118AC87B062F23F193761E081082BB661547CF9A0C243CD3994E99C78A74C3:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_JOIN_ROOT_HASH: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-9F118AC87B062F23F193761E081082BB661547CF9A0C243CD3994E99C78A74C3:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_JOIN_NUMBER_TOO_LOW: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 12\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:2-65DDE908DC06D42EC8AAAE4AB716C299ECD4891740349BCF50EF3D70C947CBE0:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_JOIN_BLOCK_TARGET: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:44-9F118AC87B062F23F193761E081082BB661547CF9A0C243CD3994E99C78A74C3:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_JOIN_ALREADY_MEMBER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:3-65DDE908DC06D42EC8AAAE4AB716C299ECD4891740349BCF50EF3D70C947CBE0:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_ACTIVE_BLOCK_TARGET: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 51\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8\n" + - "PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:44-9F118AC87B062F23F193761E081082BB661547CF9A0C243CD3994E99C78A74C3:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - KICKED_NOT_EXCLUDED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 4\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 1\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - KICKED_EXCLUDED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 4\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 1\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_MEMBERS_COUNT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 4\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - NO_LEADING_ZERO: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 3\n" + - "PoWMin: 8\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 10\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REQUIRES_4_LEADING_ZEROS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 60\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REQUIRES_7_LEADING_ZEROS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 61\n" + - "PoWMin: 6\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 11\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REQUIRES_6_LEADING_ZEROS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 67\n" + - "PoWMin: 8\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 4\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REQUIRES_5_LEADING_ZEROS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 63\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REQUIRES_7_LEADING_ZEROS_AGAIN: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 64\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - FIRST_BLOCK_OF_NEWCOMER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 65\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 2\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - SECOND_BLOCK_OF_NEWCOMER: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 66\n" + - "PoWMin: 160\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: AbCCJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 10\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_ROOT_DATES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776002\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_MEDIAN_TIME_ODD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 101\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_MEDIAN_TIME_EVEN: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 102\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - GOOD_MEDIAN_TIME_ODD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 103\n" + - "PoWMin: 1\n" + - "Time: 161\n" + - "MedianTime: 161\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - GOOD_MEDIAN_TIME_EVEN: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 104\n" + - "PoWMin: 1\n" + - "Time: 162\n" + - "MedianTime: 162\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - WRONG_CONFIRMED_DATE_MUST_CONFIRM: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 72\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - ROOT_BLOCK_WITH_UD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:s9DSBEAIbLi1HjBvXaHySApHo0HBkE9Ibxm10k/zUvmP49+FLg1IbXGj0JK6Y5SsywTcPWyQXseqXGSeGiIjAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:Te6R+OlWveuHKkegVDpg2hyse2ojBRfCAdCjMwtqMZx662qdgbMD9+xdZTXIjLRMtdsQ973EEZtwMc3hJkcdBw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - UD_BLOCK_WIHTOUT_UD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 80\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - UD_BLOCK_WIHTOUT_BASE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 80\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - V3_ROOT_BLOCK_NOBASE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - V3_ROOT_BLOCK_POSITIVE_BASE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 1\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_UD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 81\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_UD_V3: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 81\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UniversalDividend: 100\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_UNIT_BASE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 160\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411778000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 1\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_UNIT_BASE_NO_UD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 160\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 8\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_UNLEGITIMATE_UD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 82\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_UNLEGITIMATE_UD_2: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - FIRST_UD_BLOCK_WITH_UD_THAT_SHOULDNT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 20\n" + - "PoWMin: 1\n" + - "Time: 1411773099\n" + - "MedianTime: 1411773099\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - FIRST_UD_BLOCK_WITH_UD_THAT_SHOULD: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 20\n" + - "PoWMin: 1\n" + - "Time: 1411773100\n" + - "MedianTime: 1411773100\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITHOUT_TRANSACTIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_GOOD_TRANSACTIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:3:6:6:3:0:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp\n" + - "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB\n" + - "T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:4\n" + - "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:46\n" + - "T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:66\n" + - "T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:176\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:46\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "30:4:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "156:4:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)\n" + - "49:4:SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX\n" + - "2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_TRANSACTION_SUMS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:3:6:6:3:0:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp\n" + - "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB\n" + - "T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:4\n" + - "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:46\n" + - "T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:66\n" + - "T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:176\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:46\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "30:4:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "156:4:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)\n" + - "50:4:SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX\n" + - "2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_TRANSACTION_UNIT_BASES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:3:6:6:3:0:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp\n" + - "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB\n" + - "T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:4\n" + - "T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:46\n" + - "T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:66\n" + - "T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:176\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:46\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "30:4:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "156:3:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)\n" + - "49:4:SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX\n" + - "2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_UD_SOURCE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:1:1:1:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:33\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_TX_SOURCE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:1:1:1:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:44\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_UNAVAILABLE_UD_SOURCE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:1:1:1:1:0:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "D:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:55\n" + - "0:SIG(0)\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_UNAVAILABLE_TX_SOURCE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:1:1:1:1:1:0:0\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITHOUT_ISSUERS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:0:2:2:1:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "4500:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "4500:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITHOUT_SOURCES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:0:0:1:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITHOUT_RECIPIENT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:2:2:0:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "300:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "300:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITH_DUPLICATED_SOURCE_SINGLE_TX: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:3:3:1:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "400:5:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "200:4:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "200:4:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "120:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITH_EMPTY_TX_CONDITIONS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:2:2:2:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "200:1:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "200:1:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "40:0:()\n" + - "40:0: \n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WRONG_TOTAL: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:2:2:2:0:0\n" + - "5-2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "2:2:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "1:2:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "40:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "70:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_V3_GOOD_AMOUNTS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:3:3:17:1:0\n" + - "33089-00004C8D3A7EAA34ADD20E36268F7A141A45B8D47C0872EFDB00187810E0BBFD\n" + - "TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS\n" + - "17602605:0:T:E4E8486E20D521AAB329376431BD633A59FE847EF533C38CDD2C9F6E820FF786:14\n" + - "800:1:T:E9BDCC49762D17757B1AA8C52744CD182DF3FFC8EA9B237267A1B3B33ABE089B:0\n" + - "1897916:1:T:04A9E034116E436E581C01B9B58150A38615C06D12AE434614D5A08F6B409B1C:0\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "5:0:SIG(TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS)\n" + - "6:1:SIG(TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS)\n" + - "7:2:SIG(TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS)\n" + - "60:3:SIG(DesHja7gonANRJB7YUkfCgQpnDjgGeDXAeArdhcbXPmJ)\n" + - "170:3:SIG(HGYV5C16mrdvE9vpb1S9nMDHkVPsubBgANs9pSb6HWCV)\n" + - "210:3:SIG(HxWwfnVXpfec957STN97q6cMSzefkbXdApRTwVuUFUyc)\n" + - "110:3:SIG(9bZEATXBGPUSsk8oAYi4KAChg3rHKwNt67hVdErbNGCW)\n" + - "200:3:SIG(8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU)\n" + - "100:3:SIG(2eijdARyo6FuTVX6kZPbVziRB8wq87sGXpCth9eaUNX4)\n" + - "160:3:SIG(HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk)\n" + - "90:3:SIG(8KTEFQS78HwEz1NK627rNsYwENxNXJyvtyMAyfKPXZRB)\n" + - "180:3:SIG(XeBpJwRLkF5J4mnwyEDriEcNB13iFpe1MAKR4mH3fzN)\n" + - "130:3:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "130:3:SIG(4eDissnRvTq7JSgbmnL62ogQcrCLzw2zdrxA4q1yuczs)\n" + - "100:3:SIG(2pyPsXM8UCB88jP2NRM4rUHxb63qm89JMEWbpoRrhyDK)\n" + - "40:3:SIG(6KXBjAFceD1gp8RBVZfy5YQyKFXG8GaX8tKaLAyPWHrj)\n" + - "34909:3:SIG(TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS)\n" + - "REMU:22684:22851\n" + - "Iu9NripkuUAeYhhUyeiW9PSTkYFu4kM8ZEtFUgfh44qsuF5PaM38zy3/IszWtJ1i6HGQsbrxDiOVem6Gu+tyDA==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_TOO_LONG: - "Version: 10\n" + - "Type: Block\n" + - "Currency: test_net\n" + - "Number: 33520\n" + - "PoWMin: 77\n" + - "Time: 1472124036\n" + - "MedianTime: 1472124036\n" + - "UnitBase: 3\n" + - "Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "IssuersFrame: 52\n" + - "IssuersFrameVar: -2\n" + - "DifferentIssuersCount: 9\n" + - "PreviousHash: 00001E78E26DD813024EEFBC8F5C50BBA8B30DD1DB5C4F492D9606EE12C06BB4\n" + - "PreviousIssuer: 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of\n" + - "MembersCount: 128\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:48:48:2:0:0\n" + - "33518-00001D9E2EA1F967667528817FAF17ECBACE6150EBB875A2196B4457C0366D2A\n" + - "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "60:3:T:2A74F44780925586EA4C01BEE9DA5042FE8BDB0FB0506B9D69990750B555AC91:15\n" + - "1829442:3:T:FAC74B122B951F99C28B75587CFE002DC8340B053281050747D480E1F9E9193D:1\n" + - "1000:3:T:0C4C6D1321698DA41084A84C1DCD34769EB1C744933885CA3BF4A73BACB5C348:7\n" + - "1500:3:T:060BDC4B0E1D9BB01BF91F5082700C51BBDB9BDA1051BD13F6DCF1F6C5064664:8\n" + - "6000:3:T:B514D9CAF277F4DBE98B8ECC61014DB1609BA924903A884ABF969FFBB1E1C3F6:8\n" + - "4500:3:T:B4A735DE1C5860C3B02AD68420BC5949B26B905F83C2E6E1F88D7D4490350C6F:8\n" + - "4500:3:T:A2407DBDA4F687DB4B6CE5020EB64DD8F6CA71D761FB80F0D379B9E574CF134E:5\n" + - "5750:3:T:120AA878EEB49D33C64C87661BADBE154B5ECAAC05502C478AC79F4E465E4EBC:3\n" + - "16805:3:T:0562B378C254D538E4B73B928AD25CD3EACE2C2C8D662D1D48AF4B7860620B4D:0\n" + - "7250:3:T:C0D99A2E3271606CB99384DD881CF2DE5F36180728464A4B88B33A0AFDDCA587:9\n" + - "9750:3:T:180E64F8C76416455B4B34029F05E3C87D1F0E65AF7128358F7A6D874AFAA492:6\n" + - "14000:3:T:CFBA4FB960BBDB9DD56BEE0ABCF68C04F71A51910F148FC219A72D2DD5F24F58:3\n" + - "6750:3:T:570BD788DE59A5A99564026FAAEF7F2F1A398E858FE745D3A0ABE7C71040A6A3:4\n" + - "6250:3:T:6ABBA329813201CBA66D0A8A682BE7986F1F80918FF2A5809B864EA0E134ABA4:3\n" + - "7500:3:T:3B34FC6AD7543CE3671E6E302576A92A6B97BE1C15DEA1DBAB2D327A2911306B:3\n" + - "5000:3:T:443B53D39DC3551CB3E49A1AE856E115F0571C154C432094D472D1C70BA368A8:8\n" + - "6750:3:T:BDA9E8104D8458C65628A647086A3331C724E895E0EF24B9BB3B6144B27AC554:5\n" + - "8250:3:T:A67E6D09AD60339255297A05ECA04E3E20AB290AB9CA1A5DE787BD67FE64F544:4\n" + - "7250:3:T:DD2C145C4F2940EC1FAF1CAC830A52F01F0AA0A3AB9D88DD075BFEAEEBDAC27A:3\n" + - "6000:3:T:2B1B033D6E56C67C251C24F11941BAE1D3CBE7B71FB9E910018461CD9E4C6C65:6\n" + - "5500:3:T:75B5FC3419CEC4553FEBED80437CC8816041757932DC9803FF061E77B77A86F6:8\n" + - "8000:3:T:1DBC2228962C9154AD37993F67F497FC51B38768A4DCCD8872B8DF9B8AB7A5D8:7\n" + - "5750:3:T:D3E329ED2003A86876EBAC64F8727459D9F9478A5E4D614BA439786D49CFE51E:5\n" + - "7250:3:T:956457195A5C5700CF8F7A89597F90A5A60F3124E3F4ED9D6D4D58DB1B7E8C3B:6\n" + - "6000:3:T:EA45AFC115379BF663DA6BB517409ACC3D45E66291FF7D1767CA1030334A124B:5\n" + - "4750:3:T:A7664F399173A3EC98519DC5F1428416ED962FFEF7AA44075F0AAAA64A6E5880:5\n" + - "5750:3:T:D25272F1D778B52798B7A51CF0CE21F7C5812F841374508F4367872D4A47F0F7:3\n" + - "4750:3:T:1556A77A6A1019484770F5AE2905EA58A7D9B434552B85772AE6EF1C96C138C6:7\n" + - "4000:3:T:C9E4360176A5908DFB1F550D8295FC74DA062851ED087FE3F24275BC9E7D1E82:8\n" + - "4000:3:T:C519A4D03F4725EF97B2D9EB88D13C3AAB4F1F0F30B84D6D8B4E8849506BAF4D:8\n" + - "4500:3:T:D4B87D5FF3A517C622C75662F0D2746CD94AAC6365FAA3D41670B0320FA7F89E:5\n" + - "5500:3:T:5918DE9FB72A329F20684F12E69BC3FE01CEE638A9FA7E3080F5FA025FA8F480:4\n" + - "5250:3:T:DC32942E881ED8221CAD5A4DD55C2CB672F827407773064B4E8D8E8327CBC578:3\n" + - "6250:3:T:9E01B679E2B9BD4E06FA8787EDBEEB77EA99E73CD90CCD5011D24DE68BFFBD08:3\n" + - "5250:3:T:FDF089AA99BA44E0A2C66F6389DD4BBDB2200DF07C993146305353A9BD290ADC:4\n" + - "6250:3:T:392409C3FBC2F72C23841089A7A4258F2915D4B09C963EC309F49072DD686E89:4\n" + - "6000:3:T:F3DC72E0BC3FE36F0C4055831D66ED13FA90875335D12648B8ABA777B0966EB1:4\n" + - "5250:3:T:ADB9EC0BE8B20D33DAC2EADDE29C67F3931F23A3856855F42704C72360619027:6\n" + - "5000:3:T:6D7C4808CD9D8158DBDD69FEED6C29E6743E8ED075FD1C8D1BDEC2456C63A910:9\n" + - "6000:3:T:49500A1D9CAB37244C33F8EACFF449907790BC32D7323D748373B1D8F02C2FBC:3\n" + - "10500:3:T:F4651339A9C1D29A78F06F30FD05819F4F9DF5C599867D4278170DDB9A22AA4E:6\n" + - "8000:3:T:999C1E9631F1F5DB1EF5DBB7933C97A3D215FC7D12538C353D9740DF2A49D61E:4\n" + - "6500:3:T:B7B629039D1B87D478C3008AB743F71FE69F40E373A8279A6BDD06460BC88803:6\n" + - "5500:3:T:F51FC58E86630A00C8CE9E6EE633B6DAB2AB824C818F6A89DE2ABDFE82B2B07F:6\n" + - "6500:3:T:0C8A317ED208529660DDA43B1688489C7EE6EE5470BC6EA24C683180D55B9B64:6\n" + - "7500:3:T:DA6F7ABDE903366FD1BB92A025459F0D3A1C39D40D9AAF9DEA1015AAEBB112D3:5\n" + - "5250:3:T:7197A1785D81F4AA3C179E86E2D4DA32D36999B49E8BCDAACE38B5B100AECAB8:6\n" + - "2305438:3:T:0FC57133A2CA3A1413E2FC2606F5004A9A6F107DC6E72A3348B5C7A8039ED852:1\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "6:SIG(0)\n" + - "7:SIG(0)\n" + - "8:SIG(0)\n" + - "9:SIG(0)\n" + - "10:SIG(0)\n" + - "11:SIG(0)\n" + - "12:SIG(0)\n" + - "13:SIG(0)\n" + - "14:SIG(0)\n" + - "15:SIG(0)\n" + - "16:SIG(0)\n" + - "17:SIG(0)\n" + - "18:SIG(0)\n" + - "19:SIG(0)\n" + - "20:SIG(0)\n" + - "21:SIG(0)\n" + - "22:SIG(0)\n" + - "23:SIG(0)\n" + - "24:SIG(0)\n" + - "25:SIG(0)\n" + - "26:SIG(0)\n" + - "27:SIG(0)\n" + - "28:SIG(0)\n" + - "29:SIG(0)\n" + - "30:SIG(0)\n" + - "31:SIG(0)\n" + - "32:SIG(0)\n" + - "33:SIG(0)\n" + - "34:SIG(0)\n" + - "35:SIG(0)\n" + - "36:SIG(0)\n" + - "37:SIG(0)\n" + - "38:SIG(0)\n" + - "39:SIG(0)\n" + - "40:SIG(0)\n" + - "41:SIG(0)\n" + - "42:SIG(0)\n" + - "43:SIG(0)\n" + - "44:SIG(0)\n" + - "45:SIG(0)\n" + - "46:SIG(0)\n" + - "47:SIG(0)\n" + - "2706:3:SIG(TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS)\n" + - "4417789:3:SIG(HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk)\n" + - "ue7NjWPfPXxPNqvlGgr/K4jZjyHlUdYVl6dq+RXJ5RMuu8xBoo6bKhTKOyz/vXZz2clnwV/FqPDdDsWImxCmAg==\n" + - "InnerHash: 1C9EF3BCCBB14DA060F172855D18F7D979FBA752E55BB288E253806E4980E5AC\n" + - "Nonce: 0\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - OUTPUT_TOO_LONG: - "Version: 10\n" + - "Type: Block\n" + - "Currency: test_net\n" + - "Number: 33520\n" + - "PoWMin: 77\n" + - "Time: 1472124036\n" + - "MedianTime: 1472124036\n" + - "UnitBase: 3\n" + - "Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "IssuersFrame: 52\n" + - "IssuersFrameVar: -2\n" + - "DifferentIssuersCount: 9\n" + - "PreviousHash: 00001E78E26DD813024EEFBC8F5C50BBA8B30DD1DB5C4F492D9606EE12C06BB4\n" + - "PreviousIssuer: 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of\n" + - "MembersCount: 128\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:1:1:1:0:0\n" + - "33518-00001D9E2EA1F967667528817FAF17ECBACE6150EBB875A2196B4457C0366D2A\n" + - "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "60:3:T:2A74F44780925586EA4C01BEE9DA5042FE8BDB0FB0506B9D69990750B555AC91:15\n" + - "0:SIG(0)\n" + - "60:3:(SIG(EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4)|| XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4))\n" + - "ue7NjWPfPXxPNqvlGgr/K4jZjyHlUdYVl6dq+RXJ5RMuu8xBoo6bKhTKOyz/vXZz2clnwV/FqPDdDsWImxCmAg==\n" + - "InnerHash: 1C9EF3BCCBB14DA060F172855D18F7D979FBA752E55BB288E253806E4980E5AC\n" + - "Nonce: 0\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - UNLOCK_TOO_LONG: - "Version: 10\n" + - "Type: Block\n" + - "Currency: test_net\n" + - "Number: 33520\n" + - "PoWMin: 77\n" + - "Time: 1472124036\n" + - "MedianTime: 1472124036\n" + - "UnitBase: 3\n" + - "Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "IssuersFrame: 52\n" + - "IssuersFrameVar: -2\n" + - "DifferentIssuersCount: 9\n" + - "PreviousHash: 00001E78E26DD813024EEFBC8F5C50BBA8B30DD1DB5C4F492D9606EE12C06BB4\n" + - "PreviousIssuer: 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of\n" + - "MembersCount: 128\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:1:1:1:0:0\n" + - "33518-00001D9E2EA1F967667528817FAF17ECBACE6150EBB875A2196B4457C0366D2A\n" + - "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "60:3:T:2A74F44780925586EA4C01BEE9DA5042FE8BDB0FB0506B9D69990750B555AC91:15\n" + - "0:SIG(0) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789) XHX(123456789)\n" + - "60:3:SIG(EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D)\n" + - "ue7NjWPfPXxPNqvlGgr/K4jZjyHlUdYVl6dq+RXJ5RMuu8xBoo6bKhTKOyz/vXZz2clnwV/FqPDdDsWImxCmAg==\n" + - "InnerHash: 1C9EF3BCCBB14DA060F172855D18F7D979FBA752E55BB288E253806E4980E5AC\n" + - "Nonce: 0\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WRONG_TRANSFORM: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:3:3:3:0:0\n" + - "5-2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "1000:1:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "200:2:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "30:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "900:1:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "220:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "29:3:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WRONG_TRANSFORM_LOW_BASE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:6:6:8:1:0\n" + - "33753-0000054FC8AC7B450BA7D8BA7ED873FEDD5BF1E98D5D3B0DEE38DED55CB80CB3\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "150605:3:T:01B1AB40E7C1021712FF40D5605037C0ACEECA547BF519ABDCB6473A9F6BDF45:1\n" + - "297705:3:D:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:33530\n" + - "2244725:3:T:507CBE120DB654645B55431A9967789ACB7CD260EA962B839F1708834D1E5491:0\n" + - "972091:2:D:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:30324\n" + - "3808457:2:T:657229C5433FB9FFE64BF2E795E79DA796E0B1AF536DC740ECC26CCBBE104C33:1\n" + - "4:2:T:507CBE120DB654645B55431A9967789ACB7CD260EA962B839F1708834D1E5491:1\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "3171064:3:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "3:2:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "4:1:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "8:0:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "25:3:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "8:2:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "5:1:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "2:0:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "all 10.6517\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_TX_V3_TOO_HIGH_OUTPUT_BASE: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 101\n" + - "IssuersFrameVar: 11\n" + - "DifferentIssuersCount: 4\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:1:1:1:0:0\n" + - "5-2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "10:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:4:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITH_DUPLICATED_SOURCE_MULTIPLE_TX: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:2:2:1:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "200:1:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "100:1:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "80:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "TX:10:1:1:1:1:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "200:1:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "40:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - TRANSACTION_WITH_WRONG_SIGNATURES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 83\n" + - "PoWMin: 1\n" + - "Time: 1411777000\n" + - "MedianTime: 1411777000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:2:2:2:1:0:0\n" + - "3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "600:5:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "600:5:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "80:0:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - CERT_BASED_ON_NON_ZERO_FOR_ROOT: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:1:vTvKYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - CERT_BASED_ON_NON_EXISTING_BLOCK: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 1\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:CCCCJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:111:vTvKYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REVOKED_WITH_MEMBERSHIPS: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REVOKED_WITH_DUPLICATES: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - REVOKED_NOT_IN_EXCLUDED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_UNKNOWN_REVOKED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "HATTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "HATTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_YET_REVOKED: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "BBTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "BBTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", - - BLOCK_WITH_WRONG_REVOCATION_SIG: - "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 0\n" + - "PoWMin: 1\n" + - "Time: 1411776000\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 0\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "CCTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "CCTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "Certifications:\n" + - "Transactions:\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n" -}; diff --git a/test/fast/block/block_format.js b/test/fast/block/block_format.js deleted file mode 100644 index 8593e1a2b691e72de5e6c1d01a8b634adb841e19..0000000000000000000000000000000000000000 --- a/test/fast/block/block_format.js +++ /dev/null @@ -1,78 +0,0 @@ -"use strict"; -var should = require('should'); -var parsers = require('../../../app/lib/streams/parsers'); - -const raw = "Version: 10\n" + - "Type: Block\n" + - "Currency: test_net\n" + - "Number: 32029\n" + - "PoWMin: 72\n" + - "Time: 1471640455\n" + - "MedianTime: 1471640455\n" + - "UnitBase: 3\n" + - "Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "IssuersFrame: 50\n" + - "IssuersFrameVar: -5\n" + - "DifferentIssuersCount: 8\n" + - "PreviousHash: 00001A8B07B4F5BD5473B83ECC02217E0DDE64A31D695B734C5D88F470B45606\n" + - "PreviousIssuer: E2uioubZeK5SDMoxkTkizRnhE8qDL24v5oUNNa1sQKMH\n" + - "MembersCount: 124\n" + - "Identities:\n" + - "Joiners:\n" + - "Actives:\n" + - "Leavers:\n" + - "Revoked:\n" + - "Excluded:\n" + - "Certifications:\n" + - "Transactions:\n" + - "TX:10:1:6:6:2:1:0\n" + - "32028-00001A8B07B4F5BD5473B83ECC02217E0DDE64A31D695B734C5D88F470B45606\n" + - "F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL\n" + - "106930:3:D:F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL:30580\n" + - "117623:3:D:F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL:30882\n" + - "129386:3:D:F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL:31142\n" + - "140010:3:D:F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL:31404\n" + - "152769:3:D:F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL:31684\n" + - "168046:3:D:F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL:31966\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "168046:3:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "646718:3:SIG(F1pirjHYJYimekfvjVp2SGrVQSsJXb4H8JYKJddLzwVL)\n" + - "developpement JavaScript explorateur\n" + - "9WR/NRQaIbEuNmatwRytS6QdFjUYME2/ghH/N0KrRF0a6WqG4RvlUEnbzSFpQT4wJ9tTb4cvf0MOW9ZmLli8Cg==\n" + - "InnerHash: 6AEFB6C53390077861F834E5EE7B6222CC6A474040DF22E4FA669B66D5FA13AA\n" + - "Nonce: 0\n" + - "mqzcL5FW0ZMz7/aPpV8vLb6KzMYXl3WYI4bdm6Usq34tSgvROoAOp1uSuyqFBHNd7hggfR/8tACCPhkJMVNLCw==\n"; - -describe("Block format", function(){ - - var parser = parsers.parseBlock; - - it('a valid block should be well formatted', () => parser.syncWrite(raw)); - - describe("should be rejected", function(){ - - it('a block without signature', () => { - try { - parser.syncWrite(raw.replace("mqzcL5FW0ZMz7/aPpV8vLb6KzMYXl3WYI4bdm6Usq34tSgvROoAOp1uSuyqFBHNd7hggfR/8tACCPhkJMVNLCw==\n", "")); - should.not.exist('Should have thrown a format error.'); - } catch (err) { - should.exist(err); - } - }); - - it('a block with wrong pubkey format', () => { - try { - parser.syncWrite(raw.replace("HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:", "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvY:")); - should.not.exist('Should have thrown a format error.'); - } catch (err) { - should.exist(err); - } - }); - }); - -}); diff --git a/test/fast/block/block_global.excluded b/test/fast/block/block_global.excluded deleted file mode 100644 index 35a3cb581c60362034beefdf2a94d668e244534a..0000000000000000000000000000000000000000 --- a/test/fast/block/block_global.excluded +++ /dev/null @@ -1,678 +0,0 @@ -"use strict"; -var co = require('co'); -var Q = require('q'); -var _ = require('underscore'); -var async = require('async'); -var should = require('should'); -var rules = require('../../../app/lib/rules'); -var wotb = require('../../../app/lib/wot'); -var parsers = require('../../../app/lib/streams/parsers'); -var blocks = require('../../data/blocks'); -var parser = parsers.parseBlock; -var Block = require('../../../app/lib/entity/block'); -var Identity = require('../../../app/lib/entity/identity'); - -var conf = { - currency: 'bb', - msValidity: 365.25 * 24 * 3600, // 1 year - sigValidity: 365.25 * 24 * 3600, // 1 year - sigQty: 1, - xpercent: 0.9, - powZeroMin: 1, - powPeriod: 18, - incDateMin: 10, - dt: 100, - ud0: 100, - c: 0.1, - medianTimeBlocks: 200, - percentRot: 2 / 3, - blockRot: 300, - dtDiffEval: 500, - stepMax: 1 -}; - -function getDAL(overrides) { - return _.extend({ - wotb: wotb.memoryInstance(), - getCurrentBlockOrNull: () => Q(null), - getWrittenIdtyByUID: () => Q(null), - getWrittenIdtyByPubkey: () => Q(null), - getToBeKicked: () => Q([]), - isLeaving: () => Q(false), - getPreviousLinks: () => Q(null), - getLastValidFrom: () => Q(null), - lastUDBlock: () => Q(null), - getBlock: () => Q(null), - isMember: () => Q(false), - getBlocksBetween: () => Q([]), - lastBlockOfIssuer: () => Q(null) - }, overrides); -} - -/** - * TODO: reimplement tests according to new convention: - * - * - Name: protocol-brg<number>-<title>.js - * - Content: see existing tests - */ - -describe.skip("Block global coherence:", function(){ - - it('a valid block should not have any error', validate(blocks.VALID_ROOT, getDAL(), { - getIssuerPersonalizedDifficulty: () => Q(1), - getvHEAD_1: () => Q({ version : 2 }) - }, function (err) { - should.not.exist(err); - })); - - it('a valid (next) block should not have any error', validate(blocks.VALID_NEXT, getDAL({ - getCurrentBlockOrNull: () => Q({ number: 2, hash: '52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57', issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', membersCount: 3, time: 1411776000, medianTime: 1411776000 }), - getBlock: (number) => { - if (number == 1) { - return Q({ time: 1411776000, powMin: 1 }); - } - if (number == 2) { - return Q({ number: 3, powMin: 1 }); - } - return Q(null); - }, - isMember: () => Q(true), - getBlocksBetween: () => Q([{time:1411776000},{time:1411776000},{time:1411776000}]) - }), { - getIssuerPersonalizedDifficulty: () => Q(2), - getvHEAD_1: () => Q({ version : 2 }) - }, function (err) { - should.not.exist(err); - })); - - it('a block with wrong PreviousHash should fail', test(rules.GLOBAL.checkPreviousHash, blocks.WRONG_PREVIOUS_HASH, { - getCurrentBlockOrNull: () => Q({ number: 50, hash: '4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8', issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', membersCount: 3 }) - }, function (err) { - should.exist(err); - err.message.should.equal('PreviousHash not matching hash of current block'); - })); - - it('a block with wrong PreviousIssuer should fail', test(rules.GLOBAL.checkPreviousIssuer, blocks.WRONG_PREVIOUS_ISSUER, { - getCurrentBlockOrNull: () => Q({ number: 50, hash: '4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8', issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', membersCount: 3 }) - }, function (err) { - should.exist(err); - err.message.should.equal('PreviousIssuer not matching issuer of current block'); - })); - - it('a block with wrong DifferentIssuersCount following V2 should fail', test(rules.GLOBAL.checkDifferentIssuersCount, blocks.WRONG_DIFFERENT_ISSUERS_COUNT_FOLLOWING_V2, { - getCurrentBlockOrNull: () => Q({ version: 2 }), - getBlocksBetween: () => Q([]) - }, function (err) { - should.exist(err); - err.message.should.equal('DifferentIssuersCount is not correct'); - })); - - it('a block with wrong DifferentIssuersCount following V3 should fail', test(rules.GLOBAL.checkDifferentIssuersCount, blocks.WRONG_DIFFERENT_ISSUERS_COUNT_FOLLOWING_V3, { - getCurrentBlockOrNull: () => Q({ version: 3, issuersCount: 4 }), - getBlocksBetween: () => Q([ - // 5 blocks, 4 different issuers - { issuer: 'A' }, - { issuer: 'B' }, - { issuer: 'A' }, - { issuer: 'C' }, - { issuer: 'D' } - ]) - }, function (err) { - should.exist(err); - err.message.should.equal('DifferentIssuersCount is not correct'); - })); - - it('a block with wrong IssuersFrame following V2 should fail', test(rules.GLOBAL.checkIssuersFrame, blocks.WRONG_ISSUERS_FRAME_FOLLOWING_V2, { - getCurrentBlockOrNull: () => Q({ version: 2 }) - }, function (err) { - should.exist(err); - err.message.should.equal('IssuersFrame is not correct'); - })); - - it('a block with wrong IssuersFrame following V3 should fail', test(rules.GLOBAL.checkIssuersFrameVar, blocks.WRONG_ISSUERS_FRAME_FOLLOWING_V3, { - getCurrentBlockOrNull: () => Q({ version: 3, issuersCount: 3, issuersFrame: 56, issuersFrameVar: 6 }) - }, function (err) { - should.exist(err); - err.message.should.equal('IssuersFrameVar is not correct'); - })); - - it('a block with wrong Issuer should fail', test(rules.GLOBAL.checkIssuerIsMember, blocks.WRONG_ISSUER, { - isMember: () => Q(false) - }, function (err) { - should.exist(err); - err.message.should.equal('Issuer is not a member'); - })); - - it('a block with joiner for root block without root number shoud fail', test(rules.GLOBAL.checkJoiners, blocks.WRONG_JOIN_ROOT_NUMBER, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Number must be 0 for root block\'s memberships'); - })); - - it('a block with joiner for root block without root hash shoud fail', test(rules.GLOBAL.checkJoiners, blocks.WRONG_JOIN_ROOT_HASH, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Hash must be E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 for root block\'s memberships'); - })); - - it('a block with joiner targeting unexisting block fail', test(rules.GLOBAL.checkJoiners, blocks.WRONG_JOIN_BLOCK_TARGET, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Membership based on an unexisting block'); - })); - - it('a block with joiner membership number lower or equal than previous should fail', test(rules.GLOBAL.checkJoiners, blocks.WRONG_JOIN_NUMBER_TOO_LOW, { - getCurrentBlockOrNull: () => Q(null), - getWrittenIdtyByPubkey: () => Q({ currentMSN: 2 }), - getBlockByNumberAndHash: () => Q({ number: 3, powMin: 1 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Membership\'s number must be greater than last membership of the pubkey'); - })); - - it('a block with joiner membership of a yet member should fail', test(rules.GLOBAL.checkJoiners, blocks.WRONG_JOIN_ALREADY_MEMBER, { - isMember: () => Q(true), - getWrittenIdtyByPubkey: () => Q({ currentMSN: 2, member: true }), - getBlockByNumberAndHash: () => Q({ number: 3, powMin: 1 }), - getCurrentBlockOrNull: () => Q({ number: 50, hash: '4C8800825C44A22F230AFC0D140BF1930331A686899D16EBE4C58C9F34C609E8', issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', membersCount: 3 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Cannot be in joiners if already a member'); - })); - - it('a block with at least one revoked joiner should fail', test(rules.GLOBAL.checkJoinersAreNotRevoked, blocks.REVOKED_JOINER, { - getWrittenIdtyByPubkey: () => Q({ currentMSN: 2, revoked: true }) - }, function (err) { - should.exist(err); - err.message.should.equal('Revoked pubkeys cannot join'); - })); - - it('a block with at least one joiner without enough certifications should fail', test(rules.GLOBAL.checkJoinersHaveEnoughCertifications, blocks.NOT_ENOUGH_CERTIFICATIONS_JOINER, { - getValidLinksTo: () => Q([]) - }, function (err) { - should.exist(err); - err.message.should.equal('Joiner/Active does not gathers enough certifications'); - })); - - it('a block with at least one joiner without enough certifications should succeed', test(rules.GLOBAL.checkJoinersHaveEnoughCertifications, blocks.NOT_ENOUGH_CERTIFICATIONS_JOINER_BLOCK_0, { - }, function (err) { - should.not.exist(err); - })); - - it('a block with expired membership should fail', test(rules.GLOBAL.checkJoiners, blocks.EXPIRED_MEMBERSHIP, { - getWrittenIdtyByPubkey: () => Q({ currentMSN: 2 }), - getBlockByNumberAndHash: () => Q({ medianTime: 1411775000, powMin: 1 }), - getCurrentBlockOrNull: () => Q({ time: 1443333600, medianTime: 1443333600 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Membership has expired'); - })); - - it('a block with at least one joiner outdistanced from WoT should fail', test(rules.GLOBAL.checkJoinersAreNotOudistanced, blocks.OUTDISTANCED_JOINER, { - wotb: { - addNode: () => 1, - setEnabled: () => 1, - addLink: () => 1, - removeLink: () => 1, - removeNode: () => 1, - isOutdistanced: () => true - }, - getCurrentBlockOrNull: () => Q({ number: 2, hash: '52DC8A585C5D89571C511BB83F7E7D3382F0041452064B1272E65F0B42B82D57', issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', membersCount: 3, time: 1411776000, medianTime: 1411776000 }), - getWrittenIdtyByPubkey: () => Q({ wotb_id: 0 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Joiner/Active is outdistanced from WoT'); - })); - - it('a block with active targeting unexisting block fail', test(rules.GLOBAL.checkActives, blocks.WRONG_ACTIVE_BLOCK_TARGET, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Membership based on an unexisting block'); - })); - - it('a block with certification of unknown pubkey should fail', test(rules.GLOBAL.checkCertificationsAreValid, blocks.WRONGLY_SIGNED_CERTIFICATION, { - getCurrentBlockOrNull: () => Q(null), - getBlock: () => Q({}), - getBlockByNumberAndHash: () => Q({}) - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong signature for certification'); - })); - - it('a block with certification to non-zero block for root block should fail', test(rules.GLOBAL.checkCertificationsAreValid, blocks.CERT_BASED_ON_NON_ZERO_FOR_ROOT, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Number must be 0 for root block\'s certifications'); - })); - - it('a block with certification to unknown block should fail', test(rules.GLOBAL.checkCertificationsAreValid, blocks.CERT_BASED_ON_NON_EXISTING_BLOCK, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Certification based on an unexisting block'); - })); - - it('a block with expired certifications should fail', test(rules.GLOBAL.checkCertificationsAreValid, blocks.EXPIRED_CERTIFICATIONS, { - getCurrentBlockOrNull: () => Q({ time: 1443333600, medianTime: 1443333600 }), - getBlock: () => Q({ medianTime: 1411775000, powMin: 1 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Certification has expired'); - })); - - it('a block with certification from non-member pubkey should fail', test(rules.GLOBAL.checkCertificationsAreMadeByMembers, blocks.UNKNOWN_CERTIFIER, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Certification from non-member'); - })); - - it('a block with certification to non-member pubkey should fail', test(rules.GLOBAL.checkCertificationsAreMadeToMembers, blocks.UNKNOWN_CERTIFIED, { - isMember: () => Q(false) - }, function (err) { - should.exist(err); - err.message.should.equal('Certification to non-member'); - })); - - it('a block with already used UserID should fail', test(rules.GLOBAL.checkIdentityUnicity, blocks.EXISTING_UID, { - getWrittenIdtyByUID: () => Q({}) - }, function (err) { - should.exist(err); - err.message.should.equal('Identity already used'); - })); - - it('a block with already used pubkey should fail', test(rules.GLOBAL.checkPubkeyUnicity, blocks.EXISTING_PUBKEY, { - getWrittenIdtyByPubkey: () => Q({}) - }, function (err) { - should.exist(err); - err.message.should.equal('Pubkey already used'); - })); - - it('a block with too early certification replay should fail', test(rules.GLOBAL.checkCertificationsDelayIsRespected, blocks.TOO_EARLY_CERTIFICATION_REPLAY, { - getPreviousLinks: (from, to) => { - if (from == 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU' - && to == 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC') { - // Exactly 1 second remaining - return Q({ timestamp: '1380218401' }); - } - return Q(null); - } - }, function (err) { - should.exist(err); - err.message.should.equal('A similar certification is already active'); - })); - - it('a block with kicked members not written under Excluded field should fail', test(rules.GLOBAL.checkKickedMembersAreExcluded, blocks.KICKED_NOT_EXCLUDED, { - getToBeKicked: () => Q([{}]) - }, function (err) { - should.exist(err); - err.message.should.equal('All kicked members must be present under Excluded members'); - })); - - it('a block with kicked members well written under Excluded field should succeed', test(rules.GLOBAL.checkKickedMembersAreExcluded, blocks.KICKED_EXCLUDED, { - getToBeKicked: () => Q([ - { pubkey: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' }, - { pubkey: 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU' } - ]) - }, function (err) { - should.not.exist(err); - })); - it('a block with kicked members not well written under Excluded field should fail', test(rules.GLOBAL.checkKickedMembersAreExcluded, blocks.KICKED_EXCLUDED, { - getToBeKicked: () => Q([ - { pubkey: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' }, - { pubkey: 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU' }, - { pubkey: 'D2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU' } - ]) - }, function (err) { - should.exist(err); - err.message.should.equal('All kicked members must be present under Excluded members'); - })); - - it('a block with wrong members count should fail', test(rules.GLOBAL.checkMembersCountIsGood, blocks.WRONG_MEMBERS_COUNT, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong members count'); - })); - - it('a block not starting with a leading zero should fail', test(rules.GLOBAL.checkProofOfWork, blocks.NO_LEADING_ZERO, { - bcContext: { - getIssuerPersonalizedDifficulty: () => Q(8) - } - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong proof-of-work level: given 0 zeros and \'F\', required was 0 zeros and an hexa char between [0-7]'); - })); - - it('a block requiring 2 leading zeros but providing less should fail', test(rules.GLOBAL.checkProofOfWork, blocks.REQUIRES_7_LEADING_ZEROS, { - bcContext: { - getIssuerPersonalizedDifficulty: () => Q(12) - } - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong proof-of-work level: given 0 zeros and \'B\', required was 0 zeros and an hexa char between [0-3]'); - })); - - it('a block requiring 1 leading zeros but providing less should fail', test(rules.GLOBAL.checkProofOfWork, blocks.REQUIRES_6_LEADING_ZEROS, { - bcContext: { - getIssuerPersonalizedDifficulty: () => Q(8) - } - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong proof-of-work level: given 0 zeros and \'8\', required was 0 zeros and an hexa char between [0-7]'); - })); - - it('a block requiring 1 leading zeros as first block of newcomer should succeed', test(rules.GLOBAL.checkProofOfWork, blocks.FIRST_BLOCK_OF_NEWCOMER, { - bcContext: { - getIssuerPersonalizedDifficulty: () => Q(1) - } - }, function (err) { - should.not.exist(err); - })); - - it('a block requiring 40 leading zeros as second block of newcomer should fail', test(rules.GLOBAL.checkProofOfWork, blocks.SECOND_BLOCK_OF_NEWCOMER, { - bcContext: { - getIssuerPersonalizedDifficulty: () => Q(160) - } - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong proof-of-work level: given 0 zeros and \'F\', required was 10 zeros and an hexa char between [0-9A-F]'); - })); - - it('a root block should not fail for time reason', test(rules.GLOBAL.checkTimes, blocks.WRONG_ROOT_DATES, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.not.exist(err); - })); - - it('a block with wrong median for an odd number of blocks should fail', test(rules.GLOBAL.checkTimes, blocks.WRONG_MEDIAN_TIME_ODD, { - getBlocksBetween: () => Q([{time: 1},{time: 12}]) - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong MedianTime'); - })); - - it('a block with wrong median for an even number of blocks should fail', test(rules.GLOBAL.checkTimes, blocks.WRONG_MEDIAN_TIME_EVEN, { - getBlocksBetween: () => Q([{time: 1},{time: 12}]) - }, function (err) { - should.exist(err); - err.message.should.equal('Wrong MedianTime'); - })); - - it('a block whose median time is correct (odd) should pass', test(rules.GLOBAL.checkTimes, blocks.GOOD_MEDIAN_TIME_ODD, { - getBlocksBetween: () => { - let times = []; - for (let i = 0; i < 103; i++) - times.push({ time: 161 }); - return Q(times); - } - }, function (err) { - should.not.exist(err); - })); - - it('a block whose median time is correct (even) should pass', test(rules.GLOBAL.checkTimes, blocks.GOOD_MEDIAN_TIME_EVEN, { - getBlocksBetween: () => { - let times = []; - for (let i = 0; i < 104; i++) - times.push({ time: 162 }); - return Q(times); - } - }, function (err) { - should.not.exist(err); - })); - - it('a root block with Universal Dividend should fail', test(rules.GLOBAL.checkUD, blocks.ROOT_BLOCK_WITH_UD, { - lastUDBlock: () => Q(null), - getBlock: () => Q(null), - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('Root block cannot have UniversalDividend field'); - })); - - it('first block with Universal Dividend should not happen before root time + dt', test(rules.GLOBAL.checkUD, blocks.FIRST_UD_BLOCK_WITH_UD_THAT_SHOULDNT, { - lastUDBlock: () => Q(null), - getBlock: () => Q({ hash: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', medianTime: 1411773000, powMin: 1 }), - getCurrentBlockOrNull: () => Q({ number: 19, time: 1411773000, medianTime: 1411773000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('This block cannot have UniversalDividend'); - })); - - it('first block with Universal Dividend should happen on root time + dt', test(rules.GLOBAL.checkUD, blocks.FIRST_UD_BLOCK_WITH_UD_THAT_SHOULD, { - lastUDBlock: () => Q(null), - getBlock: () => Q({ hash: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', medianTime: 1411773000, powMin: 1 }), - getCurrentBlockOrNull: () => Q({ number: 19, time: 1411773000, medianTime: 1411773000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Block must have a UniversalDividend field'); - })); - - it('a block without Universal Dividend whereas it have to have one should fail', test(rules.GLOBAL.checkUD, blocks.UD_BLOCK_WIHTOUT_UD, { - lastUDBlock: () => Q(null), - getBlock: () => Q({ hash: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', medianTime: 1411773000, powMin: 1 }), - getCurrentBlockOrNull: () => Q({ number: 19, time: 1411773000, medianTime: 1411773000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('Block must have a UniversalDividend field'); - })); - - it('a block with wrong (version 2) Universal Dividend value should fail', test(rules.GLOBAL.checkUD, blocks.BLOCK_WITH_WRONG_UD, { - lastUDBlock: () => Q({ UDTime: 1411776900, medianTime: 1411776900, monetaryMass: 3620 * 10000, dividend: 110, unitbase: 4 }), - getBlock: () => Q(), - getCurrentBlockOrNull: () => Q({ time: 1411777000, medianTime: 1411777000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('UniversalDividend must be equal to 121'); - })); - - it('a block with wrong (version 3) Universal Dividend value should fail', test(rules.GLOBAL.checkUD, blocks.BLOCK_WITH_WRONG_UD_V3, { - lastUDBlock: () => Q({ UDTime: 1411776900, medianTime: 1411776900, dividend: 110, unitbase: 4 }), - getBlock: () => Q(), - getCurrentBlockOrNull: () => Q({ time: 1411777000, medianTime: 1411777000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('UniversalDividend must be equal to 121'); - })); - - it('a block with wrong UnitBase value should fail', test(rules.GLOBAL.checkUD, blocks.BLOCK_WITH_WRONG_UNIT_BASE, { - lastUDBlock: () => Q({ UDTime: 1411777000, medianTime: 1411777000, monetaryMass: 12345678900, dividend: 100, unitbase: 2 }), - getBlock: () => Q(), - getCurrentBlockOrNull: () => Q({ time: 1411777000, medianTime: 1411777000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('UnitBase must be equal to 3'); - })); - - it('a block without UD with wrong UnitBase value should fail', test(rules.GLOBAL.checkUD, blocks.BLOCK_WITH_WRONG_UNIT_BASE_NO_UD, { - lastUDBlock: () => Q({ UDTime: 1411777000, medianTime: 1411777000, monetaryMass: 12345678900, dividend: 100, unitbase: 8 }), - getBlock: () => Q(), - getCurrentBlockOrNull: () => Q({ time: 1411777000, medianTime: 1411777000, unitbase: 5 }) - }, function (err) { - should.exist(err); - err.message.should.equal('UnitBase must be equal to previous unit base = 5'); - })); - - it('a root block with unlegitimated Universal Dividend presence should fail', test(rules.GLOBAL.checkUD, blocks.BLOCK_UNLEGITIMATE_UD, { - lastUDBlock: () => Q({ UDTime: 1411777000, medianTime: 1411777000, monetaryMass: 3620 * 10000, dividend: 110, unitbase: 4 }), - getBlock: () => Q(), - getCurrentBlockOrNull: () => Q({ time: 1411777000, medianTime: 1411777000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('This block cannot have UniversalDividend'); - })); - - it('a root block with unlegitimated Universal Dividend presence should fail', test(rules.GLOBAL.checkUD, blocks.BLOCK_UNLEGITIMATE_UD_2, { - lastUDBlock: () => Q({ UDTime: 1411777000, medianTime: 1411777000, monetaryMass: 3620 * 10000, dividend: 110, unitbase: 4 }), - getBlock: () => Q(), - getCurrentBlockOrNull: () => Q({ time: 1411777000, medianTime: 1411777000 }) - }, function (err) { - should.exist(err); - err.message.should.equal('This block cannot have UniversalDividend'); - })); - - - it('a block without transactions should pass', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITHOUT_TRANSACTIONS, { - getCurrentBlockOrNull: () => Q(null) - }, function (err) { - should.not.exist(err); - })); - - it('a block with good transactions should pass', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITH_GOOD_TRANSACTIONS, { - getCurrentBlockOrNull: () => Q({ unitbase: 5 }), - getSource: (id, noffset) => { - if (id == '6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3' && noffset == 4) return Q({ amount: 0, base: 4 }); - if (id == '3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435' && noffset == 10) return Q({ amount: 0, base: 3 }); - if (id == 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' && noffset == 46) return Q({ amount: 0, base: 4 }); - if (id == 'A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956' && noffset == 66) return Q({ amount: 235, base: 4 }); - if (id == '67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B' && noffset == 176) return Q({ amount: 0, base: 4 }); - return Q(null); - } - }, function (err) { - should.not.exist(err); - })); - - it('a block with wrong transaction sum should fail', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITH_WRONG_TRANSACTION_SUMS, { - getCurrentBlockOrNull: () => Q({ unitbase: 5 }), - getSource: (id, noffset) => { - if (id == '6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3' && noffset == 4) return Q({ amount: 0, base: 4 }); - if (id == '3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435' && noffset == 10) return Q({ amount: 0, base: 3 }); - if (id == 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' && noffset == 46) return Q({ amount: 0, base: 4 }); - if (id == 'A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956' && noffset == 66) return Q({ amount: 235, base: 4 }); - if (id == '67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B' && noffset == 176) return Q({ amount: 0, base: 4 }); - return Q(null); - } - }, function (err) { - should.exist(err); - err.uerr.message.should.equal('Sum of inputs must equal sum of outputs'); - })); - - it('a block with wrong transaction unit bases should fail', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITH_WRONG_TRANSACTION_SUMS, { - getCurrentBlockOrNull: () => Q({ unitbase: 5 }), - getSource: (id, noffset) => { - if (id == '6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3' && noffset == 4) return Q({ amount: 0, base: 4 }); - if (id == '3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435' && noffset == 10) return Q({ amount: 0, base: 3 }); - if (id == 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' && noffset == 46) return Q({ amount: 0, base: 4 }); - if (id == 'A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956' && noffset == 66) return Q({ amount: 235, base: 4 }); - if (id == '67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B' && noffset == 176) return Q({ amount: 0, base: 4 }); - return Q(null); - } - }, function (err) { - should.exist(err); - err.uerr.message.should.equal('Sum of inputs must equal sum of outputs'); - })); - - it('a block with whose transaction has too high unit bases should fail', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITH_WRONG_TRANSACTION_UNIT_BASES, { - getCurrentBlockOrNull: () => Q({ unitbase: 2 }), - getSource: (id, noffset) => { - if (id == '6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3' && noffset == 4) return Q({ amount: 0, base: 4 }); - if (id == '3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435' && noffset == 10) return Q({ amount: 0, base: 3 }); - if (id == 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' && noffset == 46) return Q({ amount: 0, base: 4 }); - if (id == 'A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956' && noffset == 66) return Q({ amount: 235, base: 4 }); - if (id == '67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B' && noffset == 176) return Q({ amount: 0, base: 4 }); - return Q(null); - } - }, function (err) { - should.exist(err); - err.uerr.message.should.equal('Wrong unit base for outputs'); - })); - - it('a block with unavailable UD source should fail', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITH_UNAVAILABLE_UD_SOURCE, { - getCurrentBlockOrNull: () => Q({ unitbase: 5 }), - getSource: (id, noffset) => { - if (id == '6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3' && noffset == 4) return Q({ amount: 0, base: 4 }); - if (id == '3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435' && noffset == 10) return Q({ amount: 0, base: 3 }); - if (id == 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' && noffset == 46) return Q({ amount: 0, base: 4 }); - if (id == 'A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956' && noffset == 66) return Q({ amount: 235, base: 4 }); - if (id == '67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B' && noffset == 176) return Q({ amount: 0, base: 4 }); - return Q(null); - } - }, function (err) { - should.exist(err); - err.should.have.property('uerr').property('message').equal('Source already consumed'); - })); - - it('a block with unavailable TX source should fail', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_WITH_UNAVAILABLE_TX_SOURCE, { - getCurrentBlockOrNull: () => Q({ unitbase: 5 }), - getSource: (id, noffset) => { - if (id == '6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3' && noffset == 4) return Q({ amount: 0, base: 4 }); - if (id == '3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435' && noffset == 10) return Q({ amount: 0, base: 3 }); - if (id == 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' && noffset == 46) return Q({ amount: 0, base: 4 }); - if (id == 'A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956' && noffset == 66) return Q({ amount: 235, base: 4 }); - if (id == '67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B' && noffset == 176) return Q({ amount: 0, base: 4 }); - return Q(null); - } - }, function (err) { - should.exist(err); - err.should.have.property('uerr').property('message').equal('Source already consumed'); - })); - - it('a block with a too high unit base should fail', test(rules.GLOBAL.checkSourcesAvailability, blocks.BLOCK_TX_V3_TOO_HIGH_OUTPUT_BASE, { - getCurrentBlockOrNull: () => Q({ unitbase: 3 }), - getSource: () => Q({ base: 1, amount: 10 }) - }, function (err) { - should.exist(err); - err.should.have.property('uerr').property('message').equal('Wrong unit base for outputs'); - })); - - it('a block with an unknown member revoked should fail', test(rules.GLOBAL.checkRevoked, blocks.BLOCK_UNKNOWN_REVOKED, { - getWrittenIdtyByPubkey: () => Q(null) - }, function (err) { - should.exist(err); - err.message.should.equal('A pubkey who was never a member cannot be revoked'); - })); - - it('a block with a yet revoked identity should fail', test(rules.GLOBAL.checkRevoked, blocks.BLOCK_WITH_YET_REVOKED, { - getWrittenIdtyByPubkey: () => Q({ revoked: true }) - }, function (err) { - should.exist(err); - err.message.should.equal('A revoked identity cannot be revoked again'); - })); - - it('a block with a wrong revocation signature should fail', test(rules.GLOBAL.checkRevoked, blocks.BLOCK_WITH_WRONG_REVOCATION_SIG, { - getWrittenIdtyByPubkey: () => Q({}) - }, function (err) { - should.exist(err); - err.message.should.equal('Revocation signature must match'); - })); -}); - -function test (rule, raw, dal, callback) { - return function() { - return co(function *() { - let obj = parser.syncWrite(raw); - let block = new Block(obj); - if (rule == rules.GLOBAL.checkProofOfWork || rule == rules.GLOBAL.checkVersion) { - yield rule(block, dal.bcContext); - } else if (rule.length == 2) { - yield rule(block, dal); - } else { - yield rule(block, conf, dal); - } - }) - .then(callback).catch(callback); - }; -} - -function validate (raw, dal, bcContext, callback) { - var block; - return function() { - return Q.Promise(function(resolve, reject){ - async.waterfall([ - function (next){ - block = new Block(parser.syncWrite(raw)); - rules.CHECK.ASYNC.ALL_GLOBAL(block, conf, dal, bcContext, next); - } - ], function (err) { - err && console.error(err.stack); - err ? reject(err) : resolve(); - }); - }) - .then(callback).catch(callback); - }; -} diff --git a/test/fast/block/block_local.js b/test/fast/block/block_local.js deleted file mode 100644 index 00dfe70d7365f366c86aa7cc3a6184a76f582fae..0000000000000000000000000000000000000000 --- a/test/fast/block/block_local.js +++ /dev/null @@ -1,104 +0,0 @@ -"use strict"; -var co = require('co'); -var should = require('should'); -var parsers = require('../../../app/lib/streams/parsers'); -var blocks = require('../../data/blocks'); -var rules = require('../../../app/lib/rules'); -var parser = parsers.parseBlock; -var Block = require('../../../app/lib/entity/block'); -var Configuration = require('../../../app/lib/entity/configuration'); - -var conf = Configuration.statics.complete({ - sigQty: 1, - powZeroMin: 1, - powPeriod: 18, - incDateMin: 10, - avgGenTime: 60, - medianTimeBlocks: 20, - dt: 100, - ud0: 100, - c: 0.1 -}); - -describe("Block local coherence", function(){ - - it('a valid block should be well formatted', test(rules.ALIAS.ALL_LOCAL_BUT_POW_AND_SIGNATURE, blocks.VALID_ROOT)); - - describe("should be rejected", function(){ - - it('if wrong signature block', test(rules.LOCAL.checkBlockSignature, blocks.WRONG_SIGNATURE, 'Block\'s signature must match')); - it('if root block does not have Parameters', test(rules.LOCAL.checkParameters, blocks.ROOT_WITHOUT_PARAMETERS, 'Parameters must be provided for root block')); - it('if proof-of-work does not match PoWMin field', test(rules.LOCAL.checkProofOfWork, blocks.WRONG_PROOF_OF_WORK, 'Not a proof-of-work')); - it('if non-root has Parameters', test(rules.LOCAL.checkParameters, blocks.NON_ROOT_WITH_PARAMETERS, 'Parameters must not be provided for non-root block')); - it('if root block has PreviousHash', test(rules.LOCAL.checkPreviousHash, blocks.ROOT_WITH_PREVIOUS_HASH, 'PreviousHash must not be provided for root block')); - it('if root block has PreviousIssuer', test(rules.LOCAL.checkPreviousIssuer, blocks.ROOT_WITH_PREVIOUS_ISSUER, 'PreviousIssuer must not be provided for root block')); - it('if non-root block does not have PreviousHash', test(rules.LOCAL.checkPreviousHash, blocks.NON_ROOT_WITHOUT_PREVIOUS_HASH, 'PreviousHash must be provided for non-root block')); - it('if non-root block does not have PreviousIssuer', test(rules.LOCAL.checkPreviousIssuer, blocks.NON_ROOT_WITHOUT_PREVIOUS_ISSUER, 'PreviousIssuer must be provided for non-root block')); - it('a V2 block with Dividend must have UnitBase field', test(rules.LOCAL.checkUnitBase, blocks.UD_BLOCK_WIHTOUT_BASE, 'Document has unkown fields or wrong line ending format')); - it('a V3 root block must have UnitBase field', test(rules.LOCAL.checkUnitBase, blocks.V3_ROOT_BLOCK_NOBASE, 'Document has unkown fields or wrong line ending format')); - it('a V3 root block must have UnitBase field equal 0', test(rules.LOCAL.checkUnitBase, blocks.V3_ROOT_BLOCK_POSITIVE_BASE, 'UnitBase must equal 0 for root block')); - it('a block with wrong date (in past)', test(rules.LOCAL.checkBlockTimes, blocks.WRONG_DATE_LOWER, 'A block must have its Time between MedianTime and MedianTime + 1440')); - it('a block with wrong date (in future, but too far)', test(rules.LOCAL.checkBlockTimes, blocks.WRONG_DATE_HIGHER_BUT_TOO_HIGH, 'A block must have its Time between MedianTime and MedianTime + 1440')); - it('a root block with different time & medianTime should fail', test(rules.LOCAL.checkBlockTimes, blocks.WRONG_ROOT_TIMES, 'Root block must have Time equal MedianTime')); - it('a block with good date', test(rules.LOCAL.checkBlockTimes, blocks.GOOD_DATE_HIGHER)); - it('Block cannot contain wrongly signed identities', test(rules.LOCAL.checkIdentitiesSignature, blocks.WRONGLY_SIGNED_IDENTITIES, 'Identity\'s signature must match')); - it('block with colliding uids in identities', test(rules.LOCAL.checkIdentitiesUserIDConflict, blocks.COLLIDING_UIDS, 'Block must not contain twice same identity uid')); - it('a block with colliding pubkeys in identities', test(rules.LOCAL.checkIdentitiesPubkeyConflict, blocks.COLLIDING_PUBKEYS, 'Block must not contain twice same identity pubkey')); - it('a block with identities not matchin joins', test(rules.LOCAL.checkIdentitiesMatchJoin, blocks.WRONG_IDTY_MATCH_JOINS, 'Each identity must match a newcomer line with same userid and certts')); - it('Block cannot contain wrongly signed join', test(rules.LOCAL.checkMembershipsSignature, blocks.WRONGLY_SIGNED_JOIN, 'Membership\'s signature must match')); - it('Block cannot contain wrongly signed active', test(rules.LOCAL.checkMembershipsSignature, blocks.WRONGLY_SIGNED_ACTIVE, 'Membership\'s signature must match')); - it('Block cannot contain wrongly signed leave', test(rules.LOCAL.checkMembershipsSignature, blocks.WRONGLY_SIGNED_LEAVE, 'Membership\'s signature must match')); - it('Block cannot contain a same pubkey more than once in joiners', test(rules.LOCAL.checkPubkeyUnicity, blocks.MULTIPLE_JOINERS, 'Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded')); - it('Block cannot contain a same pubkey more than once in actives', test(rules.LOCAL.checkPubkeyUnicity, blocks.MULTIPLE_ACTIVES, 'Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded')); - it('Block cannot contain a same pubkey more than once in leavers', test(rules.LOCAL.checkPubkeyUnicity, blocks.MULTIPLE_LEAVES, 'Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded')); - it('Block cannot contain a same pubkey more than once in excluded', test(rules.LOCAL.checkPubkeyUnicity, blocks.MULTIPLE_EXCLUDED, 'Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded')); - it('Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded', test(rules.LOCAL.checkPubkeyUnicity, blocks.MULTIPLE_OVER_ALL, 'Block cannot contain a same pubkey more than once in joiners, actives, leavers and excluded')); - it('Block cannot have revoked key in joiners,actives,leavers', test(rules.LOCAL.checkMembershipUnicity, blocks.REVOKED_WITH_MEMBERSHIPS, 'Unicity constraint PUBLIC_KEY on MINDEX is not respected')); - it('Block cannot have revoked key duplicates', test(rules.LOCAL.checkRevokedUnicity, blocks.REVOKED_WITH_DUPLICATES, 'A single revocation per member is allowed')); - it('Block revoked keys must be in excluded', test(rules.LOCAL.checkRevokedAreExcluded, blocks.REVOKED_NOT_IN_EXCLUDED, 'A revoked member must be excluded')); - it('Block cannot contain 2 certifications from same issuer', test(rules.LOCAL.checkCertificationOneByIssuer, blocks.MULTIPLE_CERTIFICATIONS_FROM_SAME_ISSUER, 'Block cannot contain two certifications from same issuer')); - it('Block cannot contain identical certifications', test(rules.LOCAL.checkCertificationUnicity, blocks.IDENTICAL_CERTIFICATIONS, 'Block cannot contain identical certifications (A -> B)')); - it('Block cannot contain certifications concerning a leaver', test(rules.LOCAL.checkCertificationIsntForLeaverOrExcluded, blocks.LEAVER_WITH_CERTIFICATIONS, 'Block cannot contain certifications concerning leavers or excluded members')); - it('Block cannot contain certifications concerning an excluded member', test(rules.LOCAL.checkCertificationIsntForLeaverOrExcluded, blocks.EXCLUDED_WITH_CERTIFICATIONS, 'Block cannot contain certifications concerning leavers or excluded members')); - it('Block cannot contain transactions without issuers (1)', test(rules.LOCAL.checkTxIssuers, blocks.TRANSACTION_WITHOUT_ISSUERS, 'A transaction must have at least 1 issuer')); - it('Block cannot contain transactions without issuers (2)', test(rules.LOCAL.checkTxSources, blocks.TRANSACTION_WITHOUT_SOURCES, 'A transaction must have at least 1 source')); - it('Block cannot contain transactions without issuers (3)', test(rules.LOCAL.checkTxRecipients, blocks.TRANSACTION_WITHOUT_RECIPIENT, 'A transaction must have at least 1 recipient')); - it('Block cannot contain transactions with identical sources in one transaction', test(rules.LOCAL.checkTxSources, blocks.TRANSACTION_WITH_DUPLICATED_SOURCE_SINGLE_TX, 'It cannot exist 2 identical sources for transactions inside a given block')); - it('Block cannot contain transactions with identical sources in a pack of transactions', test(rules.LOCAL.checkTxSources, blocks.TRANSACTION_WITH_DUPLICATED_SOURCE_MULTIPLE_TX, 'It cannot exist 2 identical sources for transactions inside a given block')); - it('Block cannot contain transactions with empty output conditions', test(rules.LOCAL.checkTxRecipients, blocks.TRANSACTION_WITH_EMPTY_TX_CONDITIONS, 'Empty conditions are forbidden')); - it('Block cannot contain transactions with wrong total', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TOTAL, 'Transaction inputs sum must equal outputs sum')); - it('Block cannot contain transactions with wrong base transformation', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TRANSFORM, 'Transaction output base amount does not equal previous base deltas')); - it('Block cannot contain transactions with unexisting lower base in sources', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TRANSFORM_LOW_BASE, 'Transaction output base amount does not equal previous base deltas')); - it('Block cannot contain transactions with more than 100 lines', test(rules.LOCAL.checkTxLen, blocks.TRANSACTION_TOO_LONG, 'A transaction has a maximum size of 100 lines')); - it('Block cannot contain transactions with a too large output', test(rules.LOCAL.checkTxLen, blocks.OUTPUT_TOO_LONG, 'A transaction output has a maximum size of 2000 characters')); - it('Block cannot contain transactions with a too large unlock', test(rules.LOCAL.checkTxLen, blocks.UNLOCK_TOO_LONG, 'A transaction unlock has a maximum size of 2000 characters')); - it('Block cannot be refused with a good V3 transaction', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_V3_GOOD_AMOUNTS)); - it('Block cannot contain transactions with wrong signatures', test(rules.LOCAL.checkTxSignature, blocks.TRANSACTION_WITH_WRONG_SIGNATURES, 'Signature from a transaction must match')); - }); - -}); - - -function test (rule, raw, expectedMessage) { - return () => co(function *() { - try { - let obj = parser.syncWrite(raw); - let block = new Block(obj); - yield rule(block, conf); // conf parameter is not always used - if (expectedMessage) { - throw 'Test should have thrown an error'; - } - } catch (e) { - console.error(e.stack || e); - if (!expectedMessage) { - console.error(e.stack || e); - } - if (e.uerr) { - // This is a controlled error - e.uerr.message.should.equal(expectedMessage); - } else { - e.message.should.equal(expectedMessage); - } - } - }); -} diff --git a/test/fast/block/protocol-brg106-number.js b/test/fast/block/protocol-brg106-number.js deleted file mode 100644 index 018a3bd070d80cc7bc12e2b8552894ed5b6ede87..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg106-number.js +++ /dev/null @@ -1,49 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -describe("Protocol BR_G106 - Garbaging", function(){ - - it('An account with balance < 1,00 should be cleaned up', () => co(function*(){ - const sindex = []; - const dal = { - sindexDAL: { - findLowerThan: () => co(function*() { - return [ - { amount: 10, base: 0, tx: 'A' }, - { amount: 22, base: 0, tx: 'B' }, - { amount: 15, base: 0, tx: null } // UD - ]; - }), - getAvailableForConditions: (conditions) => co(function*() { - return [ - { amount: 10, base: 0, tx: 'A' }, - { amount: 22, base: 0, tx: 'B' }, - { amount: 15, base: 0, tx: null } // UD - ]; - }) - } - }; - const HEAD = { unitBase: 0 }; - const cleaning = yield indexer.ruleIndexGarbageSmallAccounts(HEAD, sindex, dal); - cleaning.should.have.length(3); - cleaning[0].should.have.property('amount').equal(10); - cleaning[0].should.have.property('base').equal(0); - cleaning[0].should.have.property('tx').equal('A'); - cleaning[0].should.have.property('consumed').equal(true); - cleaning[0].should.have.property('op').equal('UPDATE'); - - cleaning[1].should.have.property('amount').equal(22); - cleaning[1].should.have.property('base').equal(0); - cleaning[1].should.have.property('tx').equal('B'); - cleaning[1].should.have.property('consumed').equal(true); - cleaning[1].should.have.property('op').equal('UPDATE'); - - cleaning[2].should.have.property('amount').equal(15); - cleaning[2].should.have.property('base').equal(0); - cleaning[2].should.have.property('tx').equal(null); - cleaning[2].should.have.property('consumed').equal(true); - cleaning[2].should.have.property('op').equal('UPDATE'); - })); -}); diff --git a/test/fast/block/protocol-brg107-udEffectiveTime.js b/test/fast/block/protocol-brg107-udEffectiveTime.js deleted file mode 100644 index f5fd8e1b87dfd74de4a5558c91e0f31cc5323094..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg107-udEffectiveTime.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -describe("Protocol BR_G107 - udReevalTime", function(){ - - it('root block good udReevalTime', () => co(function*(){ - const conf = { udReevalTime0: 1500000000 }; - const HEAD_1 = null; - const HEAD = { number: 0 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udReevalTime.should.equal(conf.udReevalTime0); - })); - - it('block with medianTime < udReevalTime', () => co(function*(){ - const conf = { dt: 100, dtReeval: 20 }; - const HEAD_1 = { number: 59, udReevalTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000899 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udReevalTime.should.equal(HEAD_1.udReevalTime); - })); - - it('block with medianTime == udReevalTime', () => co(function*(){ - const conf = { dt: 100, dtReeval: 20 }; - const HEAD_1 = { number: 59, udReevalTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000900 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udReevalTime.should.equal(HEAD_1.udReevalTime + conf.dtReeval); - })); - - it('block with medianTime > udReevalTime', () => co(function*(){ - const conf = { dt: 100, dtReeval: 20 }; - const HEAD_1 = { number: 59, udReevalTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000901 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udReevalTime.should.equal(HEAD_1.udReevalTime + conf.dtReeval); - })); - -}); diff --git a/test/fast/block/protocol-brg11-udTime.js b/test/fast/block/protocol-brg11-udTime.js deleted file mode 100644 index 41d1b463438118f3031c6d98a20ac68f2cf9855f..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg11-udTime.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -describe("Protocol BR_G11 - udTime", function(){ - - it('root block good udTime', () => co(function*(){ - const conf = { udTime0: 1500000000 }; - const HEAD_1 = null; - const HEAD = { number: 0 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(conf.udTime0); - })); - - it('block with medianTime < udTime', () => co(function*(){ - const conf = { dt: 100 }; - const HEAD_1 = { number: 59, udTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000899 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(HEAD_1.udTime); - })); - - it('block with medianTime == udTime', () => co(function*(){ - const conf = { dt: 100 }; - const HEAD_1 = { number: 59, udTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000900 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(HEAD_1.udTime + conf.dt); - })); - - it('block with medianTime > udTime', () => co(function*(){ - const conf = { dt: 100 }; - const HEAD_1 = { number: 59, udTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000901 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(HEAD_1.udTime + conf.dt); - })); - -}); diff --git a/test/fast/block/protocol-brg13-dividend.js b/test/fast/block/protocol-brg13-dividend.js deleted file mode 100644 index 48dd0bc9edad03d9de26ed1daafafd0a71c18aa5..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg13-dividend.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -describe("Protocol BR_G13 - dividend", function(){ - - it('root block has no dividend', () => co(function*(){ - const conf = { udTime0: 1500000000, dt: 100 }; - const HEAD_1 = null; - const HEAD = { number: 0 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - indexer.prepareDividend(HEAD, HEAD_1, conf); - should.equal(HEAD.dividend, null); - })); - - it('block with medianTime < udTime has no dividend', () => co(function*(){ - const conf = { dt: 100 }; - const HEAD_1 = { number: 59, udTime: 1500000900 }; - const HEAD = { number: 60, medianTime: 1500000899 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - indexer.prepareDividend(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(HEAD_1.udTime); - should.equal(HEAD.dividend, null); - })); - - it('block with medianTime == udTime', () => co(function*(){ - const conf = { dt: 100, dtReeval: 100, c: 0.0488 }; - const HEAD_1 = { number: 59, udTime: 1500000900, udReevalTime: 1500000900, dividend: 100, mass: 18000, massReeval: 18000, unitBase: 1 }; - const HEAD = { number: 60, medianTime: 1500000900, membersCount: 3 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - indexer.prepareDividend(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(HEAD_1.udTime + conf.dt); - should.equal(HEAD.dividend, 102); - })); - - it('block with medianTime > udTime', () => co(function*(){ - const conf = { dt: 100, dtReeval: 100, c: 0.0488 }; - const HEAD_1 = { number: 59, udTime: 1500000900, udReevalTime: 1500000900, dividend: 100, mass: 18000, massReeval: 18000, unitBase: 1 }; - const HEAD = { number: 60, medianTime: 1500000901, membersCount: 3 }; - indexer.prepareUDTime(HEAD, HEAD_1, conf); - indexer.prepareDividend(HEAD, HEAD_1, conf); - HEAD.udTime.should.equal(HEAD_1.udTime + conf.dt); - should.equal(HEAD.dividend, 102); - })); - -}); diff --git a/test/fast/block/protocol-brg49-version.js b/test/fast/block/protocol-brg49-version.js deleted file mode 100644 index 7509289190a35939c5df88012279d4f8544c9c7b..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg49-version.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -const FAIL = false; -const SUCCESS = true; - -describe("Protocol BR_G49 - Version", function(){ - - it('V13 following V12 should fail', () => co(function*(){ - const HEAD_1 = { number: 17, version: 13 }; - const HEAD = { number: 18, version: 12 }; - indexer.ruleVersion(HEAD, HEAD_1).should.equal(FAIL); - })); - - it('V14 following V12 should fail', () => co(function*(){ - const HEAD_1 = { number: 17, version: 14 }; - const HEAD = { number: 18, version: 12 }; - indexer.ruleVersion(HEAD, HEAD_1).should.equal(FAIL); - })); - - it('V13 following V14 should succeed', () => co(function*(){ - const HEAD_1 = { number: 17, version: 13 }; - const HEAD = { number: 18, version: 14 }; - indexer.ruleVersion(HEAD, HEAD_1).should.equal(SUCCESS); - })); - - it('V13 following V15 should fail', () => co(function*(){ - const HEAD_1 = { number: 17, version: 13 }; - const HEAD = { number: 18, version: 15 }; - indexer.ruleVersion(HEAD, HEAD_1).should.equal(FAIL); - })); -}); diff --git a/test/fast/block/protocol-brg50-blocksize.js b/test/fast/block/protocol-brg50-blocksize.js deleted file mode 100644 index 30b4ab42ae1065b9182f1a630ef71d41ca307f4d..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg50-blocksize.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -const FAIL = false; -const SUCCESS = true; - -describe("Protocol BR_G50 - Block size", function(){ - - it('2 for an AVG(10) should succeed', () => co(function*(){ - const HEAD = { number: 24, bsize: 2, avgBlockSize: 10 }; - indexer.ruleBlockSize(HEAD).should.equal(SUCCESS); - })); - - it('400 for an AVG(10) should succeed', () => co(function*(){ - const HEAD = { number: 24, bsize: 400, avgBlockSize: 10 }; - indexer.ruleBlockSize(HEAD).should.equal(SUCCESS); - })); - - it('499 for an AVG(10) should succeed', () => co(function*(){ - const HEAD = { number: 24, bsize: 499, avgBlockSize: 10 }; - indexer.ruleBlockSize(HEAD).should.equal(SUCCESS); - })); - - it('500 for an AVG(10) should fail', () => co(function*(){ - const HEAD = { number: 24, bsize: 500, avgBlockSize: 10 }; - indexer.ruleBlockSize(HEAD).should.equal(FAIL); - })); - - it('500 for an AVG(454) should fail', () => co(function*(){ - const HEAD = { number: 24, bsize: 500, avgBlockSize: 454 }; - indexer.ruleBlockSize(HEAD).should.equal(FAIL); - })); - - it('500 for an AVG(455) should succeed', () => co(function*(){ - const HEAD = { number: 24, bsize: 500, avgBlockSize: 455 }; - indexer.ruleBlockSize(HEAD).should.equal(SUCCESS); - })); - - it('1100 for an AVG(1000) should fail', () => co(function*(){ - const HEAD = { number: 24, bsize: 1100, avgBlockSize: 1000 }; - indexer.ruleBlockSize(HEAD).should.equal(FAIL); - })); - - it('1100 for an AVG(1001) should succeed', () => co(function*(){ - const HEAD = { number: 24, bsize: 1100, avgBlockSize: 1001 }; - indexer.ruleBlockSize(HEAD).should.equal(SUCCESS); - })); - - it('1100 for block#0 should succeed', () => co(function*(){ - const HEAD = { number: 0, bsize: 1100, avgBlockSize: 0 }; - indexer.ruleBlockSize(HEAD).should.equal(SUCCESS); - })); -}); diff --git a/test/fast/block/protocol-brg51-number.js b/test/fast/block/protocol-brg51-number.js deleted file mode 100644 index 12abe494540e15401dc9eded2d523bec30395b58..0000000000000000000000000000000000000000 --- a/test/fast/block/protocol-brg51-number.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; -const co = require('co'); -const should = require('should'); -const indexer = require('../../../app/lib/dup/indexer'); - -const FAIL = false; -const SUCCESS = true; - -describe("Protocol BR_G51 - Number", function(){ - - it('1 following 1 should fail', () => co(function*(){ - const block = { number: 1 }; - const HEAD_1 = { number: 1 }; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(FAIL); - })); - - it('1 following 0 should succeed', () => co(function*(){ - const block = { number: 1 }; - const HEAD_1 = { number: 0 }; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(SUCCESS); - })); - - it('0 following 0 should fail', () => co(function*(){ - const block = { number: 0 }; - const HEAD_1 = { number: 0 }; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(FAIL); - })); - - it('0 following nothing should succeed', () => co(function*(){ - const block = { number: 0 }; - const HEAD_1 = null; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(SUCCESS); - })); - - it('4 following nothing should fail', () => co(function*(){ - const block = { number: 4 }; - const HEAD_1 = null; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(FAIL); - })); - - it('4 following 2 should fail', () => co(function*(){ - const block = { number: 4 }; - const HEAD_1 = { number: 2 }; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(FAIL); - })); - - it('4 following 3 should succeed', () => co(function*(){ - const block = { number: 4 }; - const HEAD_1 = { number: 3 }; - const HEAD = {}; - indexer.prepareNumber(HEAD, HEAD_1); - indexer.ruleNumber(block, HEAD).should.equal(SUCCESS); - })); - -}); diff --git a/test/fast/peering.js b/test/fast/peering.js deleted file mode 100644 index 2bfb93ea8fe79db03eb0bec71b18a8f229ad6795..0000000000000000000000000000000000000000 --- a/test/fast/peering.js +++ /dev/null @@ -1,63 +0,0 @@ -"use strict"; -var should = require('should'); -var assert = require('assert'); -var parsers = require('../../app/lib/streams/parsers'); - -var rawPeer = "" + - "Version: 10\n" + - "Type: Peer\n" + - "Currency: beta_brousouf\n" + - "PublicKey: 3Z7w5g4gC9oxwEbATnmK2UFgGWhLZPmZQb5dRxvNrXDu\n" + - "Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855\n" + - "Endpoints:\n" + - "BASIC_MERKLED_API duniter.twiced.fr 88.163.127.43 9101\n" + - "OTHER_PROTOCOL 88.163.127.43 9102\n" + - "bvuKzc6+cGWMGC8FIkZHN8kdQhaRL/MK60KYyw5vJqkKEgxXbygQHAzfoojeSY4gPKIu4FggBkR1HndSEm2FAQ==\n"; - -var Peer = require('../../app/lib/entity/peer'); - -describe('Peer', function(){ - - describe('of some key', function(){ - - var pr; - - before(function(done) { - pr = new Peer(parsers.parsePeer.syncWrite(rawPeer)); - done(); - }); - - it('should be version 10', function(){ - assert.equal(pr.version, 10); - }); - - it('should have beta_brousoufs currency name', function(){ - assert.equal(pr.currency, 'beta_brousouf'); - }); - - it('should have public key', function(){ - assert.equal(pr.pubkey, '3Z7w5g4gC9oxwEbATnmK2UFgGWhLZPmZQb5dRxvNrXDu'); - }); - - it('should have 2 endpoints', function(){ - assert.equal(pr.endpoints.length, 2); - }); - - it('should have DNS', function(){ - assert.equal(pr.getDns(), 'duniter.twiced.fr'); - }); - - it('should have IPv4', function(){ - should.exist(pr.getIPv4()); - assert.equal(pr.getIPv4(), "88.163.127.43"); - }); - - it('should have no IPv6 address', function(){ - should.not.exist(pr.getIPv6()); - }); - - it('should have port 9101', function(){ - assert.equal(pr.getPort(), 9101); - }); - }); -}); diff --git a/test/fast/tx_format.js b/test/fast/tx_format.js deleted file mode 100644 index f679724fdfb17f3c1cf02cdc2988919b88aa5617..0000000000000000000000000000000000000000 --- a/test/fast/tx_format.js +++ /dev/null @@ -1,28 +0,0 @@ -"use strict"; -var should = require('should'); -var parsers = require('../../app/lib/streams/parsers'); - -var raw = "Version: 10\n" + - "Type: Transaction\n" + - "Currency: test_net\n" + - "Blockstamp: 3-2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "Locktime: 0\n" + - "Issuers:\n" + - "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" + - "Inputs:\n" + - "100000:0:D:HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:3428\n" + - "Unlocks:\n" + - "0:SIG(0)\n" + - "Outputs:\n" + - "1000:0:SIG(yGKRRB18B4eaZQdksWBZubea4VJKFSSpii2okemP7x1)\n" + - "99000:0:SIG(HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk)\n" + - "Comment: reessai\n" + - "P6MxJ/2SdkvNDyIyWuOkTz3MUwsgsfo70j+rpWeQWcm6GdvKQsbplB8482Ar1HMz2q0h5V3tfMqjCuAeWVQ+Ag==\n"; - -describe("Transaction format", function(){ - - var parser = parsers.parseTransaction; - - it('a valid block should be well formatted', () => parser.syncWrite(raw)); - -}); diff --git a/test/fast/v1.0-local-index.js b/test/fast/v1.0-local-index.js deleted file mode 100644 index c00efd19fc6e39e06b77d377fd253b63e14b335e..0000000000000000000000000000000000000000 --- a/test/fast/v1.0-local-index.js +++ /dev/null @@ -1,158 +0,0 @@ -"use strict"; - -const _ = require('underscore'); -const should = require('should'); -const parsers = require('../../app/lib/streams/parsers'); -const indexer = require('../../app/lib/dup/indexer'); -const constants = require('../../app/lib/constants'); - -const raw = "Version: 10\n" + - "Type: Block\n" + - "Currency: beta_brousouf\n" + - "Number: 10\n" + - "PoWMin: 1\n" + - "Time: 1411785481\n" + - "MedianTime: 1411776000\n" + - "UnitBase: 2\n" + - "Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "IssuersFrame: 100\n" + - "IssuersFrameVar: 0\n" + - "DifferentIssuersCount: 3\n" + - "PreviousHash: 2A27BD040B16B7AF59DDD88890E616987F4DD28AA47B9ABDBBEE46257B88E945\n" + - "PreviousIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" + - "MembersCount: 3\n" + - "Identities:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:CTmlh3tO4B8f8IbL8iDy5ZEr3jZDcxkPmDmRPQY74C39MRLXi0CKUP+oFzTZPYmyUC7fZrUXrb3LwRKWw1jEBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "Joiners:\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" + - "65dKz7JEvZzy6Znr9hATtvm7Kd9fCwxhWKgyrbyL2jhX:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Actives:\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" + - "Leavers:\n" + - "HEgBcwtkrnWBgwDqELYht6aBZrmjm8jQY4DtFRjcB437:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tac\n" + - "Revoked:\n" + - "EKWJvwPaYuLTv1VoCEtZLmtUTxTC5gWVfdWeRgKgZChN:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==\n" + - "Excluded:\n" + - "EKWJvwPaYuLTv1VoCEtZLmtUTxTC5gWVfdWeRgKgZChN\n" + - "BNmj8fnZuDtpvismiWnFneJkPHpB98bZdc5ozNYzBW78\n" + - "Certifications:\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:CK6UDDJM3d0weE1RVtzFJnw/+J507lPAtspleHc59T4+N1tzQj1RRGWrzPiTknCjnCO6SxBSJX0B+MIUWrpNAw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:a7SFapoVaXq27NU+wZj4afmxp0SbwLGqLJih8pfX6TRKPvNp/V93fbKixbqg10cwa1CadNenztxq3ZgOivqADw==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:bJyoM2Tz4hltVXkLvYHOOmLP4qqh2fx7aMLkS5q0cMoEg5AFER3iETj13uoFyhz8yiAKESyAZSDjjQwp8A1QDw==\n" + - "F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:0:h8D/dx/z5K2dx06ktp7fnmLRdxkdV5wRkJgnmEvKy2k55mM2RyREpHfD7t/1CC5Ew+UD0V9N27PfaoLxZc1KCQ==\n" + - "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:0:eefk9Gg0Ijz0GvrNnRc55CCCBd4yk8j0fNzWzVZFKR3kZ7lsKav6dWyAsaVhlNG5S6XwEwvPoMwKJq1Vn7OjBg==\n" + - "Transactions:\n" + - "TX:10:1:6:6:8:1:0\n" + - "33753-0000054FC8AC7B450BA7D8BA7ED873FEDD5BF1E98D5D3B0DEE38DED55CB80CB3\n" + - "G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" + - "150605:3:T:01B1AB40E7C1021712FF40D5605037C0ACEECA547BF519ABDCB6473A9F6BDF45:1\n" + - "297705:3:D:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:33530\n" + - "2244725:3:T:507CBE120DB654645B55431A9967789ACB7CD260EA962B839F1708834D1E5491:0\n" + - "972091:2:D:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:30324\n" + - "3808457:2:T:657229C5433FB9FFE64BF2E795E79DA796E0B1AF536DC740ECC26CCBBE104C33:1\n" + - "4:2:T:507CBE120DB654645B55431A9967789ACB7CD260EA962B839F1708834D1E5491:1\n" + - "0:SIG(0)\n" + - "1:SIG(0)\n" + - "2:SIG(0)\n" + - "3:SIG(0)\n" + - "4:SIG(0)\n" + - "5:SIG(0)\n" + - "3171064:3:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "3:2:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "4:1:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "8:0:SIG(5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of)\n" + - "25:3:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "8:2:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "5:1:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "2:0:SIG(G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU)\n" + - "all 10.6517\n" + - "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r\n" + - "TX:10:1:1:1:1:0:0\n" + - "5-2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326\n" + - "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY\n" + - "10:3:T:2C31D8915801E759F6D4FF3DA8DA983D7D56DCF4F8D94619FCFAD4B128362326:88\n" + - "0:SIG(0)\n" + - "1:4:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)\n" + - "I6gJkJIQJ9vwDRXZ6kdBsOArQ3zzMYPmFxDbJqseBVq5NWlmJ7l7oY9iWtqhPF38rp7/iitbgyftsRR8djOGDg==\n" + - "InnerHash: DE837CA3F49C423A6A6C124819ABA31A41C1C4A4E2728B5721DF891B98FA8D0D\n" + - "Nonce: 1\n" + - "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n"; - -describe("v1.0 Local Index", function(){ - - let block, index; - - before(() => { - block = parsers.parseBlock.syncWrite(raw); - index = indexer.localIndex(block, { sigValidity: 100, msValidity: 40 }); - }); - - it('should have 30 index entries', () => { - index.should.have.length(30); - }); - - /********* - * IINDEX - ********/ - - it('should have 4 iindex entries', () => { - _(index).where({ index: constants.I_INDEX}).should.have.length(4); - }); - - it('should have 1 iindex CREATE entries', () => { - _(index).where({ index: constants.I_INDEX, op: constants.IDX_CREATE }).should.have.length(1); - }); - - it('should have 3 iindex UPDATE entries', () => { - _(index).where({ index: constants.I_INDEX, op: constants.IDX_UPDATE }).should.have.length(3); - }); - - /********* - * MINDEX - ********/ - - it('should have 5 mindex entries', () => { - _(index).where({ index: constants.M_INDEX}).should.have.length(5); - }); - - it('should have 1 mindex CREATE entries', () => { - _(index).where({ index: constants.M_INDEX, op: constants.IDX_CREATE }).should.have.length(1); - }); - - it('should have 4 mindex UPDATE entries', () => { - _(index).where({ index: constants.M_INDEX, op: constants.IDX_UPDATE }).should.have.length(4); - }); - - /********* - * CINDEX - ********/ - - it('should have 5 cindex entries', () => { - _(index).where({ index: constants.C_INDEX}).should.have.length(5); - }); - - it('should have 5 cindex CREATE entries', () => { - _(index).where({ index: constants.C_INDEX, op: constants.IDX_CREATE }).should.have.length(5); - }); - - it('should have 0 cindex UPDATE entries', () => { - _(index).where({ index: constants.C_INDEX, op: constants.IDX_UPDATE }).should.have.length(0); - }); - - /********* - * SINDEX - ********/ - - it('should have 16 cindex entries', () => { - _(index).where({ index: constants.S_INDEX}).should.have.length(16); - }); - - it('should have 9 cindex CREATE entries', () => { - _(index).where({ index: constants.S_INDEX, op: constants.IDX_CREATE }).should.have.length(9); - }); - - it('should have 7 cindex UPDATE entries', () => { - _(index).where({ index: constants.S_INDEX, op: constants.IDX_UPDATE }).should.have.length(7); - }); - -}); diff --git a/test/integration/branches.js b/test/integration/branches.js index c8fb3bacc02829cf5469b1e7f0a3e39b174e5581..c2ee1f4c9c0780ed8956b4cb5b5c9cfe69f238e5 100644 --- a/test/integration/branches.js +++ b/test/integration/branches.js @@ -43,7 +43,7 @@ describe("Branches", () => co(function*() { it('should have a 3 blocks fork window size', function() { return expectAnswer(rp('http://127.0.0.1:7778/node/summary', { json: true }), function(res) { res.should.have.property('duniter').property('software').equal('duniter'); - res.should.have.property('duniter').property('version').equal('1.2.6'); + res.should.have.property('duniter').property('version').equal('1.3.8'); res.should.have.property('duniter').property('forkWindowSize').equal(3); }); }); diff --git a/test/integration/continuous-proof.js b/test/integration/continuous-proof.js index 34dcd21a9700b57eac63b9f9c4e2004b9834a41d..6a6ce36c24d13f775b5518cec2943f72b7f95c8b 100644 --- a/test/integration/continuous-proof.js +++ b/test/integration/continuous-proof.js @@ -13,8 +13,11 @@ process.on('unhandledRejection', (reason) => { console.error(reason); }); +const NB_CORES_FOR_COMPUTATION = 1 // For simple tests. Can be changed to test multiple cores. + const s1 = toolbox.server({ cpu: 1, + nbCores: NB_CORES_FOR_COMPUTATION, powDelay: 1000, powMin: 32, pair: { @@ -26,8 +29,6 @@ const s1 = toolbox.server({ const i1 = user('i1', { pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'}, { server: s1 }); const i2 = user('i2', { pub: 'DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV', sec: '468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7'}, { server: s1 }); -constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; // For simple tests. Can be changed to test multiple cores. - describe("Continous proof-of-work", function() { before(() => co(function*() { @@ -97,6 +98,7 @@ describe("Continous proof-of-work", function() { it('testing a network', () => co(function*() { const res = yield toolbox.simpleNetworkOf2NodesAnd2Users({ + nbCores: NB_CORES_FOR_COMPUTATION, powMin: 16 }), s2 = res.s1, s3 = res.s2; yield s2.commit(); @@ -114,6 +116,7 @@ describe("Continous proof-of-work", function() { it('testing proof-of-work during a block pulling', () => co(function*() { const res = yield toolbox.simpleNetworkOf2NodesAnd2Users({ + nbCores: NB_CORES_FOR_COMPUTATION, powMin: 0 }), s2 = res.s1, s3 = res.s2; yield s2.commit(); diff --git a/test/integration/documents-currency.js b/test/integration/documents-currency.js index 4324a8d1e15556875a6ccc89b1051a9b75089d11..bb20ece76db048ef9dac42f676e5781064ebdafd 100644 --- a/test/integration/documents-currency.js +++ b/test/integration/documents-currency.js @@ -162,6 +162,7 @@ describe("Document pool currency", function() { it('Peer with wrong currency should be rejected', () => co(function*() { try { const peer = yield toc2.makePeer(['BASIC_MERKLED_API localhost 10901'], { + version: 10, currency: "wrong_currency" }); yield s2.postPeer(peer); diff --git a/test/integration/grammar-test.js b/test/integration/grammar-test.js deleted file mode 100644 index 345d76f276cbbc8a4e0901fbe7429e2e744032c1..0000000000000000000000000000000000000000 --- a/test/integration/grammar-test.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; - -const unlock = require('../../app/lib/ucp/txunlock'); -const should = require('should'); - -describe('Grammar', () => { - - let k1 = "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd"; - let k2 = "GgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd"; - let Ha = "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"; - let Hz = "594E519AE499312B29433B7DD8A97FF068DEFCBA9755B6D5D00E84C524D67B06"; - - it('SIG should work', () => { - - unlock('SIG(' + k1 + ')', [{ pubkey: k1, sigOK: true }]).should.equal(true); - unlock('SIG(' + k1 + ')', [{ pubkey: k1, sigOK: false }]).should.equal(false); - unlock('SIG(' + k1 + ')', [{ pubkey: k2, sigOK: false }]).should.equal(false); - unlock('SIG(' + k1 + ')', [{ pubkey: k2, sigOK: true }]).should.equal(false); - }); - - it('XHX should work', () => { - - unlock('XHX(' + Ha + ')', ['a']).should.equal(true); - unlock('XHX(' + Hz + ')', ['z']).should.equal(true); - unlock('XHX(' + Hz + ')', ['a']).should.equal(false); - unlock('XHX(' + Ha + ')', ['z']).should.equal(false); - }); - - it('&& keywork should work', () => { - - unlock('SIG(' + k1 + ') && SIG(' + k2 + ')', [{ pubkey: k1, sigOK: true }, { pubkey: k1, sigOK: true }]).should.equal(false); - unlock('SIG(' + k1 + ') && SIG(' + k2 + ')', [{ pubkey: k1, sigOK: true }, { pubkey: k2, sigOK: false }]).should.equal(false); - unlock('SIG(' + k1 + ') && SIG(' + k2 + ')', [{ pubkey: k1, sigOK: true }, { pubkey: k2, sigOK: true }]).should.equal(true); - }); - - it('|| keywork should work', () => { - - unlock('SIG(' + k1 + ') || SIG(' + k2 + ')', [{ pubkey: k1, sigOK: true }, { pubkey: k2, sigOK: true }]).should.equal(true); - unlock('SIG(' + k1 + ') || SIG(' + k2 + ')', [{ pubkey: k1, sigOK: false }, { pubkey: k2, sigOK: true }]).should.equal(true); - unlock('SIG(' + k1 + ') || SIG(' + k2 + ')', [{ pubkey: k1, sigOK: true }, { pubkey: k2, sigOK: false }]).should.equal(true); - unlock('SIG(' + k1 + ') || SIG(' + k2 + ')', [{ pubkey: k1, sigOK: false }, { pubkey: k2, sigOK: false }]).should.equal(false); - }); - - it('|| && keyworks combined should work', () => { - - unlock('SIG(' + k1 + ') || (SIG(' + k1 + ') && SIG(' + k2 + '))', [{ pubkey: k1, sigOK: true },{ pubkey: k1, sigOK: true },{ pubkey: k2, sigOK: true }]).should.equal(true); - unlock('SIG(' + k2 + ') || (SIG(' + k1 + ') && SIG(' + k2 + '))', [{ pubkey: k2, sigOK: false },{ pubkey: k1, sigOK: true },{ pubkey: k2, sigOK: false }]).should.equal(false); - }); - - it('SIG XHX functions combined should work', () => { - - unlock('SIG(' + k1 + ') && XHX(' + Ha + ')', [{ pubkey: k1, sigOK: true },'a']).should.equal(true); - unlock('SIG(' + k1 + ') && XHX(' + Ha + ')', [{ pubkey: k1, sigOK: true },'z']).should.equal(false); - unlock('SIG(' + k1 + ') || XHX(' + Ha + ')', [{ pubkey: k1, sigOK: true },'a']).should.equal(true); - unlock('SIG(' + k1 + ') || XHX(' + Ha + ')', [{ pubkey: k1, sigOK: true },'z']).should.equal(true); - unlock('SIG(' + k1 + ') || XHX(' + Ha + ')', [{ pubkey: k1, sigOK: false },'z']).should.equal(false); - unlock('SIG(' + k1 + ') || XHX(' + Ha + ')', [{ pubkey: k1, sigOK: false },'a']).should.equal(true); - }); - - it('SIG, XHX, &&, || words combined should work', () => { - - unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: true },'a','z']).should.equal(true); - unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: true },'a','a']).should.equal(true); - unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: true },'z','a']).should.equal(false); - unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'a','a']).should.equal(false); - unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'a','z']).should.equal(true); - unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'z','z']).should.equal(true); - unlock('(SIG(EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4))', [{ pubkey: k1, sigOK: false },'1234']).should.equal(true); - }); -}); diff --git a/test/integration/identity-pulling.js b/test/integration/identity-pulling.js index d462ac8fd82271f224c775df5607204a49354b77..6379137328e1e40b4028ba1332c2f32f4d6d330c 100644 --- a/test/integration/identity-pulling.js +++ b/test/integration/identity-pulling.js @@ -6,9 +6,6 @@ const assert = require('assert'); const user = require('./tools/user'); const commit = require('./tools/commit'); const toolbox = require('./tools/toolbox'); -const Identity = require('../../app/lib/entity/identity'); -const Certification = require('../../app/lib/entity/certification'); -const Membership = require('../../app/lib/entity/membership'); const s1 = toolbox.server({ pair: { diff --git a/test/integration/membership_chainability.js b/test/integration/membership_chainability.js new file mode 100644 index 0000000000000000000000000000000000000000..62aa5e99cfcd3f55bda44f0f49a9d06422eab8e5 --- /dev/null +++ b/test/integration/membership_chainability.js @@ -0,0 +1,93 @@ +"use strict" + +const co = require('co') +const should = require('should') +const toolbox = require('./tools/toolbox') + +describe("Membership chainability", function() { + + describe("before July 2017", () => { + + const now = 1482220000 + let s1, cat + + const conf = { + msPeriod: 20, + nbCores: 1, + msValidity: 10000, + udTime0: now, + udReevalTime0: now, + sigQty: 1, + medianTimeBlocks: 1 // The medianTime always equals previous block's medianTime + } + + before(() => co(function*() { + const res1 = yield toolbox.simpleNodeWith2Users(conf) + s1 = res1.s1 + cat = res1.cat + yield s1.commit({ time: now }) + yield s1.commit({ time: now }) + yield s1.commit({ time: now, actives: [ + 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:QA2gKg6x2PhqMyKhi3hWBXuRJuRwd8G6WGHGNZIEicUR2kjE8Y3WScLyaMNQAZF3s7ewvUvpWkewopd5ugr+Bg==:1-4A21CEA1EA7C3BB0A22DEC87C5AECB38E69DB70A269CEC3644B8149B322C7669:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat' + ]}) + })) + + it('current should be the 2nd', () => s1.expect('/blockchain/current', (res) => { + res.should.have.property('number').equal(2) + res.should.have.property('actives').length(1) + })) + }) + + describe("after July 2017", () => { + + const now = 1498860000 + let s1, cat + + const conf = { + msPeriod: 20, + nbCores: 1, + msValidity: 10000, + udTime0: now, + udReevalTime0: now, + sigQty: 1, + medianTimeBlocks: 1 // The medianTime always equals previous block's medianTime + } + + before(() => co(function*() { + const res1 = yield toolbox.simpleNodeWith2Users(conf) + s1 = res1.s1 + cat = res1.cat + yield s1.commit({ time: now }) + yield s1.commit({ time: now + 20 }) + })) + + it('should refuse a block with a too early membership in it', () => co(function*() { + yield toolbox.shouldFail(s1.commit({ + time: now + 20, + actives: ['HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:H2jum4LLenc/69vZAFw2OppLxVQgNtp+7XL+M9nSvAGjxMf8jBEAeQ/nrfDP3Lrk2SvDvp5Hice5jFboHVdxAQ==:1-2989DEFA8BD18F111B3686EB14ED91EE7C509C9D74EE5C96AECBD4F3CA5E0FB6:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat'] + }), '500 - "{\\n \\"ucode\\": 1002,\\n \\"message\\": \\"ruleMembershipPeriod\\"\\n}"') + })) + + it('should not be able to renew immediately', () => co(function*() { + yield cat.join() + yield s1.commit({ time: now + 20 }) + yield s1.expect('/blockchain/block/2', (res) => { + res.should.have.property('number').equal(2) + res.should.have.property('joiners').length(0) + }) + })) + + it('should be able to renew after 20 sec', () => co(function*() { + yield s1.commit({ time: now + 20 }) + yield s1.expect('/blockchain/block/3', (res) => { + res.should.have.property('number').equal(3) + res.should.have.property('actives').length(1) + }) + })) + + it('current should be the 4th', () => s1.expect('/blockchain/current', (res) => { + res.should.have.property('number').equal(3) + res.should.have.property('actives').length(1) + })) + }) +}) diff --git a/test/integration/peerings.js b/test/integration/peerings.js index 0afcd684fa1f197561feedd5616b884289f8253b..23e204edb2c0a5e079ea767b1e8c03212c89db46 100644 --- a/test/integration/peerings.js +++ b/test/integration/peerings.js @@ -115,9 +115,9 @@ describe("Network", function() { yield sync(0, 0, s1, s2); // Server 3 syncs block 0 yield sync(0, 0, s1, s3); - yield nodeS1.getPeer().then((peer) => nodeS2.postPeer(new Peer(peer).getRawSigned())); - yield nodeS2.getPeer().then((peer) => nodeS1.postPeer(new Peer(peer).getRawSigned())); - yield nodeS3.getPeer().then((peer) => nodeS1.postPeer(new Peer(peer).getRawSigned())); + yield nodeS1.getPeer().then((peer) => nodeS2.postPeer(new Peer(peer).getRawSigned())).catch(e => console.error(e)) + yield nodeS2.getPeer().then((peer) => nodeS1.postPeer(new Peer(peer).getRawSigned())).catch(e => console.error(e)) + yield nodeS3.getPeer().then((peer) => nodeS1.postPeer(new Peer(peer).getRawSigned())).catch(e => console.error(e)) yield commitS1(); yield [ until(s2, 'block', 1), diff --git a/test/integration/proof-of-work.js b/test/integration/proof-of-work.js index 5c092a195bd5e810e47fcba8119d7e1a9b7945c8..078c8c36601d44b060c57ed98f312bcd2124cf35 100644 --- a/test/integration/proof-of-work.js +++ b/test/integration/proof-of-work.js @@ -17,10 +17,12 @@ keyring from Key ***/ const intermediateProofs = []; +const NB_CORES_FOR_COMPUTATION = 1 // For simple tests. Can be changed to test multiple cores. const prover = blockProver({ push: (data) => intermediateProofs.push(data), conf: { + nbCores: NB_CORES_FOR_COMPUTATION, cpu: 1.0, // 80%, pair: { pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', @@ -35,8 +37,6 @@ const now = 1474382274 * 1000; const MUST_START_WITH_A_ZERO = 16; const MUST_START_WITH_TWO_ZEROS = 32; -constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; // For simple tests. Can be changed to test multiple cores. - describe("Proof-of-work", function() { it('should be able to find an easy PoW', () => co(function*() { diff --git a/test/integration/scenarios/hello-plugin.js b/test/integration/scenarios/hello-plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..a73aefa0cc98d2e209fd475bb2d8e34cc4b79157 --- /dev/null +++ b/test/integration/scenarios/hello-plugin.js @@ -0,0 +1,18 @@ +"use strict" + +const co = require('co') + +module.exports = { + duniter: { + cli: [{ + name: 'hello-world', + desc: 'Says hello from \`duniter\` command.', + logs: false, + onDatabaseExecute: (server, conf, program, params) => co(function*() { + const msg = 'Hello world! from within Duniter.' + console.log(msg) + return msg + }) + }] + } +} diff --git a/test/integration/server-sandbox.js b/test/integration/server-sandbox.js index c612425007a6a0a0d7d24a7ed211a416c16a4006..24f8581dc596796b8d459a483221a14a4fd014a7 100644 --- a/test/integration/server-sandbox.js +++ b/test/integration/server-sandbox.js @@ -3,6 +3,7 @@ const co = require('co'); const should = require('should'); const bma = require('duniter-bma').duniter.methods.bma; +const common = require('duniter-common'); const user = require('./tools/user'); const commit = require('./tools/commit'); const toolbox = require('./tools/toolbox'); @@ -248,8 +249,11 @@ describe("Sandboxes", function() { describe('Transaction', () => { - const tmp = constants.TRANSACTION_MAX_TRIES; - constants.TRANSACTION_MAX_TRIES = 2; + const tmp = common.constants.TRANSACTION_MAX_TRIES; + + before(() => { + common.constants.TRANSACTION_MAX_TRIES = 2; + }) it('should accept 2 transactions of 20, 30 units', () => co(function *() { yield i4.send(20, i1); @@ -269,7 +273,7 @@ describe("Sandboxes", function() { yield s1.commit(); yield s1.commit(); (yield s1.dal.txsDAL.getSandboxRoom()).should.equal(2); - constants.TRANSACTION_MAX_TRIES = tmp; + common.constants.TRANSACTION_MAX_TRIES = tmp; })); }); }); diff --git a/test/integration/sources_property.js b/test/integration/sources_property.js new file mode 100644 index 0000000000000000000000000000000000000000..8812bd4e220ab1923d3d2063c428d68af89795e8 --- /dev/null +++ b/test/integration/sources_property.js @@ -0,0 +1,49 @@ +"use strict"; + +const co = require('co'); +const _ = require('underscore'); +const should = require('should'); +const assert = require('assert'); +const constants = require('../../app/lib/constants'); +const bma = require('duniter-bma').duniter.methods.bma; +const toolbox = require('./tools/toolbox'); +const node = require('./tools/node'); +const unit = require('./tools/unit'); +const http = require('./tools/http'); + +const now = 1480000000; + +const conf = { + dt: 1000, + ud0: 200, + udTime0: now - 1, // So we have a UD right on block#1 + medianTimeBlocks: 1 // Easy: medianTime(b) = time(b-1) +}; + +let s1, cat, tac + +describe("Sources property", function() { + + before(() => co(function*() { + const res = yield toolbox.simpleNodeWith2Users(conf); + s1 = res.s1; + cat = res.cat; + tac = res.tac; + yield s1.commit({ time: now }); + yield s1.commit({ time: now + 1 }); + })); + + it('it should exist block#1 with UD of 200', () => s1.expect('/blockchain/block/1', (block) => { + should.exists(block); + assert.equal(block.number, 1); + assert.equal(block.dividend, 200); + })); + + it('it should exist sources for HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', () => s1.expect('/tx/sources/HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', (res) => { + assert.equal(res.sources.length, 1) + })); + + it('it should NOT exist sources if we change one letter to uppercased version', () => s1.expect('/tx/sources/HGTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', (res) => { + assert.equal(res.sources.length, 0) + })); +}); diff --git a/test/integration/tools/node.js b/test/integration/tools/node.js index 545293678af696d41bf239fab3cc9b0474339e39..f430bd39d46e21e8f64fb187ae4d3f65f488f030 100644 --- a/test/integration/tools/node.js +++ b/test/integration/tools/node.js @@ -5,7 +5,6 @@ var rp = require('request-promise'); var _ = require('underscore'); var async = require('async'); var request = require('request'); -var rules = require('../../../app/lib/rules'); var contacter = require('duniter-crawler').duniter.methods.contacter; var duniter = require('../../../index'); var multicaster = require('../../../app/lib/streams/multicaster'); diff --git a/test/integration/tools/toolbox.js b/test/integration/tools/toolbox.js index 8a42e7fef26a7794673d7af7367ed2740c06b322..aadc5d3c894cdfd63532406396524d4124660cc4 100644 --- a/test/integration/tools/toolbox.js +++ b/test/integration/tools/toolbox.js @@ -30,9 +30,12 @@ module.exports = { shouldFail: (promise, message) => co(function*() { try { yield promise; - throw { "message": '{ "message": "Should have thrown an error" }' }; + throw '{ "message": "Should have thrown an error" }' } catch(e) { - const err = JSON.parse(e) + let err = e + if (typeof e === "string") { + err = JSON.parse(e) + } err.should.have.property('message').equal(message); } }), diff --git a/test/integration/tools/user.js b/test/integration/tools/user.js index 0243bd1ac61ceb4d7bc9962d6b2771e573b92017..8c968a0e3ecbb4dc0d0e900222ecd42b69ef06d6 100644 --- a/test/integration/tools/user.js +++ b/test/integration/tools/user.js @@ -5,10 +5,11 @@ const _ = require('underscore'); const async = require('async'); const request = require('request'); const contacter = require('duniter-crawler').duniter.methods.contacter; -const ucp = require('duniter-common').buid; -const parsers = require('../../../app/lib/streams/parsers'); -const keyring = require('duniter-common').keyring; -const rawer = require('duniter-common').rawer; +const common = require('duniter-common'); +const ucp = common.buid; +const parsers = require('duniter-common').parsers; +const keyring = common.keyring; +const rawer = common.rawer; const constants = require('../../../app/lib/constants'); const Identity = require('../../../app/lib/entity/identity'); const Certification = require('../../../app/lib/entity/certification'); @@ -214,7 +215,7 @@ function User (uid, options, node) { } let http = yield getContacter(); let current = yield http.getCurrent(); - let version = current && Math.min(constants.LAST_VERSION_FOR_TX, current.version); + let version = current && Math.min(common.constants.LAST_VERSION_FOR_TX, current.version); let json = yield http.getSources(pub); let i = 0; let cumulated = 0; diff --git a/test/integration/transactions-chaining.js b/test/integration/transactions-chaining.js index 02ee9ce64b9c0547d187ad563198c32e964b23db..a995064e14ca2a42cfd299aae0308d7961b8f545 100644 --- a/test/integration/transactions-chaining.js +++ b/test/integration/transactions-chaining.js @@ -6,6 +6,7 @@ const should = require('should'); const assert = require('assert'); const constants = require('../../app/lib/constants'); const bma = require('duniter-bma').duniter.methods.bma; +const common = require('duniter-common'); const toolbox = require('./tools/toolbox'); const node = require('./tools/node'); const user = require('./tools/user'); @@ -65,8 +66,8 @@ describe("Transaction chaining", function() { blockstamp: [current.number, current.hash].join('-'), theseOutputsStart: 1 }); - const tmp = constants.TRANSACTION_MAX_TRIES = 2; - constants.TRANSACTION_MAX_TRIES = 2; + const tmp = common.constants.TRANSACTION_MAX_TRIES; + common.constants.TRANSACTION_MAX_TRIES = 2; yield unit.shouldNotFail(toc.sendTX(tx1)); yield unit.shouldNotFail(toc.sendTX(tx2)); (yield s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(1); @@ -77,7 +78,7 @@ describe("Transaction chaining", function() { yield s1.commit({ time: now + 7210 }); // TX2 commited (yield s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(0); (yield s1.get('/tx/sources/DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV')).should.have.property('sources').length(3); // The UD + 1040 + 160 units sent by toc - constants.TRANSACTION_MAX_TRIES = tmp; + common.constants.TRANSACTION_MAX_TRIES = tmp; })); }); }); diff --git a/test/integration/transactions-cltv.js b/test/integration/transactions-cltv.js index f2a955c4ef9c9ac8638e2594f27bdd6f93b428f6..eb0a89c7742eccb2e0663e16cf140242da74d5c7 100644 --- a/test/integration/transactions-cltv.js +++ b/test/integration/transactions-cltv.js @@ -39,7 +39,7 @@ describe("Transactions: CLTV", function() { assert.equal(block.dividend, 200); })); - it('with SIG and XHX', () => co(function *() { + it('with SIG and CLTV', () => co(function *() { let tx1 = yield cat.prepareITX(200, tac); yield unit.shouldNotFail(cat.sendTX(tx1)); yield s1.commit({ time: now + 19 }); // TODO: why not in the same block? diff --git a/test/integration/transactions-csv.js b/test/integration/transactions-csv.js index 7a176270f0282d365bafb857706467ab0dfe4aa1..5ce58c9e175ba2b55127ab7f7b344b24123822d9 100644 --- a/test/integration/transactions-csv.js +++ b/test/integration/transactions-csv.js @@ -39,7 +39,7 @@ describe("Transactions: CSV", function() { assert.equal(block.dividend, 200); })); - it('with SIG and XHX', () => co(function *() { + it('with SIG and CSV', () => co(function *() { let tx1 = yield cat.prepareITX(200, tac); yield unit.shouldNotFail(cat.sendTX(tx1)); yield s1.commit({ time: now + 19 }); // TODO: why not in the same block? diff --git a/test/integration/transactions-pruning.js b/test/integration/transactions-pruning.js index f70685dde3c6ad0a3fa6b3342b39a2104530cad9..afb4126208041671ddfc859847c48f5bd7575f38 100644 --- a/test/integration/transactions-pruning.js +++ b/test/integration/transactions-pruning.js @@ -8,6 +8,7 @@ const until = require('./tools/until'); const toolbox = require('./tools/toolbox'); const Peer = require('../../app/lib/entity/peer'); const constants = require('../../app/lib/constants'); +const common = require('duniter-common'); const s1 = toolbox.server({ currency: 'currency_one', @@ -60,12 +61,12 @@ describe("Transactions pruning", function() { })); it('double spending transaction should have been pruned', () => co(function*() { - const tmp = constants.TRANSACTION_MAX_TRIES; - constants.TRANSACTION_MAX_TRIES = 1; + const tmp = common.constants.TRANSACTION_MAX_TRIES; + common.constants.TRANSACTION_MAX_TRIES = 1; yield s1.commit(); yield s1.expect('/tx/history/HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', (res) => { res.history.should.have.property('sending').length(0); }); - constants.TRANSACTION_MAX_TRIES = tmp; + common.constants.TRANSACTION_MAX_TRIES = tmp; })); }); diff --git a/test/integration/transactions-test.js b/test/integration/transactions-test.js index 851a1f5b3093171b8ba694be7739df7fee39fd1b..c7faddd2285df7b39d218c023c11458882c97f9b 100644 --- a/test/integration/transactions-test.js +++ b/test/integration/transactions-test.js @@ -22,6 +22,7 @@ describe("Testing transactions", function() { pub: 'DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV', sec: '468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7' }, + nbCores: 1, dt: 7210, ud0: 1200, udTime0: now + 7210, @@ -35,7 +36,6 @@ describe("Testing transactions", function() { before(() => co(function*() { - constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1 yield s1.initWithDAL().then(bma).then((bmapi) => bmapi.openConnections()); // Self certifications yield tic.createIdentity(); @@ -79,12 +79,12 @@ describe("Testing transactions", function() { const txSrc = _.findWhere(res.sources, { type: 'T' }); assert.equal(txSrc.amount, 690); }) - const tx = yield s1.get('/tx/hash/5645ED3A022201BC4C225CEF76E3DE7A0FC8DAFDB6C7211E7C1C214AABC7B1CE') + const tx = yield s1.get('/tx/hash/0D41759A8FB1350ADCC21ADBD799BC124722BC1CBCBB15355EF00494B4CD44D0') assert.notEqual(tx, null) assert.deepEqual(tx, { "comment": "", "currency": "duniter_unit_test_currency", - "hash": "5645ED3A022201BC4C225CEF76E3DE7A0FC8DAFDB6C7211E7C1C214AABC7B1CE", + "hash": "0D41759A8FB1350ADCC21ADBD799BC124722BC1CBCBB15355EF00494B4CD44D0", "inputs": [ "1200:0:D:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:2" ], @@ -98,7 +98,7 @@ describe("Testing transactions", function() { ], "raw": "", "signatures": [ - "3KDs6xjn6itMqk36IKlyfH5YOkz069Or0BDVzeL0lU6BMjS3CpM2+Ak3cC041dxk8Te+/smviOu3wHzjapHtDQ==" + "waKIjrO0lMBU+1pDPOEOC55OQeCUIczEkV7bUI6bgMIs7AzrRZSFsOnRzdbUDAnx/3SqhgRiqedzgtXVD/cYBA==" ], "unlocks": [ "0:SIG(0)" diff --git a/test/integration/v1.0-double-dividend.js b/test/integration/v1.0-double-dividend.js index e9a6fbbc61ad87ad90245b4ab47af98b83623825..fde26bb813628f3044dae3c31356ca6aa8f69674 100644 --- a/test/integration/v1.0-double-dividend.js +++ b/test/integration/v1.0-double-dividend.js @@ -18,9 +18,6 @@ const conf = { medianTimeBlocks: 1 // The medianTime always equals previous block's medianTime }; -constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; -constants.NB_DIGITS_UD = 4; - let s1, cat, tac; describe("Protocol 1.0 Dividend Update", function() { diff --git a/test/integration/v1.0-g1-dividend-long-run.js b/test/integration/v1.0-g1-dividend-long-run.js index 29d6642028f8caa6f3035c0c45f85487041d1167..4cd3a0266b14aab0f22926dc6d702cee41e280d6 100644 --- a/test/integration/v1.0-g1-dividend-long-run.js +++ b/test/integration/v1.0-g1-dividend-long-run.js @@ -26,8 +26,6 @@ const conf = { avgGenTime: 3600 * 24 // 1 bloc a day }; -constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; - let s1, cat, tac; describe("Protocol 1.0 Ğ1 Dividend - long run", function() { diff --git a/test/integration/v1.0-g1-dividend.js b/test/integration/v1.0-g1-dividend.js index d403856fcde4d77b64ce931c3989ede323affc7c..14bf41ca57911f8e21c4d3fe216791c65c8b3017 100644 --- a/test/integration/v1.0-g1-dividend.js +++ b/test/integration/v1.0-g1-dividend.js @@ -23,8 +23,6 @@ const conf = { avgGenTime: 3600 * 24 // 1 bloc a day }; -constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; - let s1, cat, tac; describe("Protocol 1.0 Ğ1 Dividend", function() { diff --git a/test/integration/v1.0-modules-api.js b/test/integration/v1.0-modules-api.js index a480a8faae2359a2352747012c84def68994c504..3355194a2907b6fa74fb2d9d7d3089b5635124ab 100644 --- a/test/integration/v1.0-modules-api.js +++ b/test/integration/v1.0-modules-api.js @@ -4,13 +4,22 @@ const co = require('co'); const _ = require('underscore'); const should = require('should'); const util = require('util'); +const path = require('path'); const stream = require('stream'); const duniter = require('../../index'); -const parsers = require('../../app/lib/streams/parsers/index'); +const parsers = require('duniter-common').parsers; const querablep = require('querablep'); describe("v1.0 Module API", () => { + it('should be able to execute `hello` command with quickRun', () => co(function*() { + duniter.statics.quickRunGetArgs = () => ['', '', 'hello-world'] + duniter.statics.onRunDone = () => { /* Do not exit the process */ } + const absolutePath = path.join(__dirname, './scenarios/hello-plugin.js') + const res = yield duniter.statics.quickRun(absolutePath) + res.should.equal('Hello world! from within Duniter.') + })) + it('should be able to execute `hello` command', () => co(function*() { const sStack = duniter.statics.simpleStack(); diff --git a/test/integration/v1.0-source-garbaging.disabled b/test/integration/v1.0-source-garbaging.disabled index 50cd271326770d00a3ebd3420e5dd5a9727ac95c..3a9920d17f647796dd4140f965b3f9c35995c84f 100644 --- a/test/integration/v1.0-source-garbaging.disabled +++ b/test/integration/v1.0-source-garbaging.disabled @@ -18,7 +18,6 @@ const conf = { medianTimeBlocks: 1 // The medianTime always equals previous block's medianTime }; -constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; constants.NB_DIGITS_UD = 4; let s1, cat, tac; diff --git a/yarn.lock b/yarn.lock index 8b988fa547b8b0a3c5bdfbf8b9fa1c835df3ddd4..e72d963cfb87cbef6f4b98be0ecbd2161b661516 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,6 +18,13 @@ accept-encoding@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/accept-encoding/-/accept-encoding-0.1.0.tgz#5dd88b8df71f1dc2e5cc6b9565ecce1e399a333e" +accepts@~1.2.12: + version "1.2.13" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" + dependencies: + mime-types "~2.1.6" + negotiator "0.5.3" + accepts@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" @@ -39,6 +46,10 @@ acorn@^5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" +adm-zip@0.4.7, adm-zip@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" + ajv-keywords@^1.0.0: version "1.5.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" @@ -83,8 +94,8 @@ ansi@^0.3.0, ansi@~0.3.1: resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" aproba@^1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.1.tgz#95d3600f07710aa0e9298c726ad5ecf2eacbabab" + version "1.1.2" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" archiver-utils@^1.3.0: version "1.3.0" @@ -220,8 +231,20 @@ balanced-match@^0.4.1: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" base-x@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-2.0.5.tgz#11967f90b42995cfdb5f50a1be499d7675db4fce" + version "2.0.6" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-2.0.6.tgz#4582a91ebcec99ee06f4e4032030b0cf1c2941d8" + dependencies: + safe-buffer "^5.0.1" + +base-x@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.2.tgz#bf873861b7514279b7969f340929eab87c11d130" + dependencies: + safe-buffer "^5.0.1" + +basic-auth@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" basic-auth@~1.1.0: version "1.1.0" @@ -272,6 +295,21 @@ bluebird@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" +body-parser@1.15.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.15.1.tgz#9bceef0669b8f8b943f0ad8ce5d95716bd740fd2" + dependencies: + bytes "2.3.0" + content-type "~1.0.1" + debug "~2.2.0" + depd "~1.1.0" + http-errors "~1.4.0" + iconv-lite "0.4.13" + on-finished "~2.3.0" + qs "6.1.0" + raw-body "~2.1.6" + type-is "~1.6.12" + body-parser@1.17.1: version "1.17.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47" @@ -312,11 +350,17 @@ bs58@4.0.0: dependencies: base-x "^2.0.1" +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + dependencies: + base-x "^3.0.2" + buffer-crc32@^0.2.1: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" -buffer-shims@^1.0.0, buffer-shims@~1.0.0: +buffer-shims@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" @@ -331,6 +375,10 @@ busboy@*: dicer "0.2.5" readable-stream "1.1.x" +bytes@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070" + bytes@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" @@ -513,11 +561,15 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" +content-disposition@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" + content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" -content-type@~1.0.2: +content-type@~1.0.1, content-type@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" @@ -525,6 +577,10 @@ cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" +cookie@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.5.tgz#6ab9948a4b1ae21952cd2588530a4722d4044d7c" + cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" @@ -623,12 +679,18 @@ debug@2.6.1: dependencies: ms "0.7.2" -debug@2.6.7, debug@^2.1.1, debug@^2.2.0: +debug@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" dependencies: ms "2.0.0" +debug@^2.1.1, debug@^2.2.0: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + debug@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" @@ -704,15 +766,16 @@ doctrine@^1.2.2: esutils "^2.0.2" isarray "^1.0.0" -duniter-bma@1.1.2, duniter-bma@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/duniter-bma/-/duniter-bma-1.1.2.tgz#179e24e70d7dcfcedebdc26a211e42ce1714bf4c" +duniter-bma@1.3.x: + version "1.3.2" + resolved "https://registry.yarnpkg.com/duniter-bma/-/duniter-bma-1.3.2.tgz#9a44aa362cd3f576b157dd68402f26ce9495caee" dependencies: async "2.2.0" body-parser "1.17.1" co "4.6.0" cors "2.8.2" ddos "0.1.16" + duniter-common "^1.3.0" errorhandler "1.5.0" event-stream "3.3.4" express "4.15.2" @@ -721,29 +784,31 @@ duniter-bma@1.1.2, duniter-bma@^1.1.0: inquirer "3.0.6" morgan "1.8.1" nnupnp "1.0.2" + node-pre-gyp "^0.6.34" q "1.5.0" - request "2.81.0" - request-promise "4.2.0" underscore "1.8.3" ws "1.1.1" -duniter-common@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/duniter-common/-/duniter-common-1.0.1.tgz#a768503c1ee2ceca89c5e5314692d79f64aeb949" +duniter-common@1.3.x, duniter-common@^1.3.0, duniter-common@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/duniter-common/-/duniter-common-1.3.5.tgz#b727117a2c9463d0486b7c0feb845df60b65e247" dependencies: + bs58 "^4.0.0" co "4.6.0" - naclb "1.3.7" - node-pre-gyp "0.6.32" + jison "0.4.17" + naclb "1.3.9" + seedrandom "^2.4.3" tweetnacl "0.14.3" + underscore "1.8.3" -duniter-crawler@1.1.4, duniter-crawler@^1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/duniter-crawler/-/duniter-crawler-1.1.4.tgz#fe6544c01aae0e0041ae46176118b57ebf46c0d1" +duniter-crawler@1.3.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/duniter-crawler/-/duniter-crawler-1.3.6.tgz#1a944f67a11f59b74656fa315b22cbaa4c41088d" dependencies: async "2.2.0" co "4.6.0" - duniter-bma "^1.1.0" - duniter-common "^1.0.0" + duniter-bma "1.3.x" + duniter-common "1.3.x" moment "2.18.1" multimeter "0.1.1" querablep "0.1.0" @@ -751,12 +816,35 @@ duniter-crawler@1.1.4, duniter-crawler@^1.1.0: request-promise "4.2.0" underscore "1.8.3" -duniter-keypair@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/duniter-keypair/-/duniter-keypair-1.1.3.tgz#2ed198e6097ad2ce5c929760cfe568a64137f90e" +"duniter-currency-monit@https://github.com/duniter/duniter-currency-monit/archive/module-0.1.tar.gz": + version "0.3.2" + resolved "https://github.com/duniter/duniter-currency-monit/archive/module-0.1.tar.gz#eb8c89307baa186ffacff513507ee216e72ab30f" + dependencies: + adm-zip "^0.4.7" + body-parser "1.15.1" + co "^4.6.0" + commander "2.9.0" + event-stream "3.3.4" + express "4.13.4" + fs-extra "^3.0.1" + http "0.0.0" + morgan "1.7.0" + node-pre-gyp "^0.6.34" + q "1.5.0" + request "^2.81.0" + request-promise "4.2.0" + rimraf "^2.6.1" + tmp "^0.0.31" + underscore "1.8.3" + ws "1.1.1" + +duniter-keypair@1.3.X, duniter-keypair@1.3.x: + version "1.3.4" + resolved "https://registry.yarnpkg.com/duniter-keypair/-/duniter-keypair-1.3.4.tgz#0f13cbf3130ad3720bb853d4440b78a6b7106c6b" dependencies: bs58 "4.0.0" co "4.6.0" + duniter-common "1.3.x" inquirer "^3.0.6" js-yaml "3.8.2" node-pre-gyp "0.6.34" @@ -765,20 +853,45 @@ duniter-keypair@1.1.3: tweetnacl "0.14.5" tweetnacl-util "0.15.0" -duniter-prover@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/duniter-prover/-/duniter-prover-1.1.2.tgz#9b445ea074099b8d819c213ea4b42db035541a1e" +duniter-prover@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/duniter-prover/-/duniter-prover-1.3.3.tgz#2575119c7996b16bde3ad0032d248ce179080064" dependencies: async "2.2.0" co "4.6.0" - duniter-common "^1.0.0" - duniter-crawler "^1.1.0" + duniter-common "1.3.x" + duniter-crawler "1.3.x" inquirer "3.0.6" moment "2.18.1" node-uuid "1.4.8" querablep "0.1.0" + underscore "1.8.3" + +duniter-ui@1.3.x: + version "1.3.10" + resolved "https://registry.yarnpkg.com/duniter-ui/-/duniter-ui-1.3.10.tgz#17946cc638efff79e05874c09869ba76c66f7290" + dependencies: + adm-zip "0.4.7" + body-parser "1.17.1" + co "4.6.0" + cors "2.8.2" + duniter-bma "1.3.x" + duniter-common "1.3.x" + duniter-crawler "1.3.x" + duniter-currency-monit "https://github.com/duniter/duniter-currency-monit/archive/module-0.1.tar.gz" + duniter-keypair "1.3.x" + event-stream "3.3.4" + express "4.15.2" + express-fileupload "0.0.5" + fs-extra "2.1.2" + materialize-css "0.98.1" + moment "2.18.1" + node-pre-gyp "0.6.34" + q "1.5.0" request "2.81.0" request-promise "4.2.0" + rimraf "2.6.1" + tmp "0.0.31" underscore "1.8.3" duplexer@~0.1.1: @@ -817,8 +930,8 @@ errorhandler@1.5.0: escape-html "~1.0.3" es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.20" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.20.tgz#72a9b4fd5832797ba1bb65dceb2e25c04241c492" + version "0.10.23" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.23.tgz#7578b51be974207a5487821b56538c224e4e7b38" dependencies: es6-iterator "2" es6-symbol "~3.1" @@ -1055,6 +1168,10 @@ esutils@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" +etag@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" + etag@~1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051" @@ -1094,6 +1211,36 @@ express-fileupload@0.0.5: fs-extra "^0.22.1" streamifier "^0.1.1" +express@4.13.4: + version "4.13.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.13.4.tgz#3c0b76f3c77590c8345739061ec0bd3ba067ec24" + dependencies: + accepts "~1.2.12" + array-flatten "1.1.1" + content-disposition "0.5.1" + content-type "~1.0.1" + cookie "0.1.5" + cookie-signature "1.0.6" + debug "~2.2.0" + depd "~1.1.0" + escape-html "~1.0.3" + etag "~1.7.0" + finalhandler "0.4.1" + fresh "0.3.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.1" + path-to-regexp "0.1.7" + proxy-addr "~1.0.10" + qs "4.0.0" + range-parser "~1.0.3" + send "0.13.1" + serve-static "~1.10.2" + type-is "~1.6.6" + utils-merge "1.0.0" + vary "~1.0.1" + express@4.15.2: version "4.15.2" resolved "https://registry.yarnpkg.com/express/-/express-4.15.2.tgz#af107fc148504457f2dca9a6f2571d7129b97b35" @@ -1132,9 +1279,11 @@ extend@^3.0.0, extend@~3.0.0: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" external-editor@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" tmp "^0.0.31" extsprintf@1.0.2: @@ -1180,6 +1329,15 @@ fileset@0.2.x: glob "5.x" minimatch "2.x" +finalhandler@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.1.tgz#85a17c6c59a94717d262d61230d4b0ebe3d4a14d" + dependencies: + debug "~2.2.0" + escape-html "~1.0.3" + on-finished "~2.3.0" + unpipe "~1.0.0" + finalhandler@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" @@ -1233,6 +1391,10 @@ forwarded@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" +fresh@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" + fresh@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e" @@ -1241,6 +1403,13 @@ from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" +fs-extra@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + fs-extra@^0.22.1: version "0.22.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.22.1.tgz#5fd6f8049dc976ca19eb2355d658173cabcce056" @@ -1249,6 +1418,14 @@ fs-extra@^0.22.1: jsonfile "^2.1.0" rimraf "^2.2.8" +fs-extra@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1337,13 +1514,13 @@ glob@5.0.5, glob@5.x: path-is-absolute "^1.0.0" glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" @@ -1352,8 +1529,8 @@ globals@^6.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-6.4.1.tgz#8498032b3b6d1cc81eebc5f79690d8fe29fabf4f" globals@^9.14.0: - version "9.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" globby@^5.0.0: version "5.0.0" @@ -1388,9 +1565,13 @@ growl@1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428" +hammerjs@^2.0.4: + version "2.0.8" + resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" + handlebars@^4.0.1: - version "4.0.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.8.tgz#22b875cd3f0e6cbea30314f144e82bc7a72ff420" + version "4.0.10" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -1459,6 +1640,20 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" +http-errors@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" + dependencies: + inherits "~2.0.1" + statuses "1" + +http-errors@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.4.0.tgz#6c0242dea6b3df7afda153c71089b31c6e82aabf" + dependencies: + inherits "2.0.1" + statuses ">= 1.2.1 < 2" + http-errors@~1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257" @@ -1484,13 +1679,25 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +http@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/http/-/http-0.0.0.tgz#86e6326d29c5d039de9fac584a45689f929f4f72" + +iconv-lite@0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" + iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" +iconv-lite@^0.4.17: + version "0.4.17" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" + ignore@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.0.tgz#3812d22cbe9125f2c2b4915755a1b8abd745a001" + version "3.3.3" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" imurmurhash@^0.1.4: version "0.1.4" @@ -1507,6 +1714,10 @@ inherits@2, inherits@2.0.3, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" @@ -1568,6 +1779,10 @@ ip@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/ip/-/ip-0.0.1.tgz#bbc68d7cc448560a63fbe99237a01bc50fdca7ec" +ipaddr.js@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.0.5.tgz#5fa78cf301b825c78abc3042d812723049ea23c7" + ipaddr.js@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec" @@ -1691,24 +1906,22 @@ jison@0.4.17: lex-parser "~0.1.3" nomnom "1.5.2" -jodid25519@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" - dependencies: - jsbn "~0.1.0" +jquery@^2.1.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-2.2.4.tgz#2c89d6889b5eac522a7eea32c14521559c6cbf02" js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@3.0.1: +js-yaml@3.0.1, js-yaml@3.x: version "3.0.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.0.1.tgz#76405fea5bce30fc8f405d48c6dca7f0a32c6afe" dependencies: argparse "~ 0.1.11" esprima "~ 1.0.2" -js-yaml@3.8.2, js-yaml@3.x, js-yaml@^3.2.5, js-yaml@^3.5.1: +js-yaml@3.8.2, js-yaml@^3.2.5, js-yaml@^3.5.1: version "3.8.2" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" dependencies: @@ -1719,6 +1932,10 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.4.2.tgz#2aa107f142af4121d145659d44f50830961e699a" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -1739,6 +1956,12 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.0.tgz#92e7c7444e5ffd5fa32e6a9ae8b85034df8347d0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -1844,6 +2067,14 @@ map-stream@~0.1.0: buffers "~0.1.1" readable-stream "~1.0.0" +materialize-css@0.98.1: + version "0.98.1" + resolved "https://registry.yarnpkg.com/materialize-css/-/materialize-css-0.98.1.tgz#7276895b2c998b53e26deaa0c23a0484c0851d99" + dependencies: + hammerjs "^2.0.4" + jquery "^2.1.4" + node-archiver "^0.3.0" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -1867,7 +2098,7 @@ mime-db@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" -mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.6, mime-types@~2.1.7: version "2.1.15" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" dependencies: @@ -1903,7 +2134,7 @@ minimatch@2.x, minimatch@^2.0.1: dependencies: brace-expansion "^1.0.0" -minimatch@^3.0.0, minimatch@^3.0.2: +minimatch@^3.0.0, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -1974,6 +2205,16 @@ moment@2.18.1: version "2.18.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" +morgan@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.7.0.tgz#eb10ca8e50d1abe0f8d3dad5c0201d052d981c62" + dependencies: + basic-auth "~1.0.3" + debug "~2.2.0" + depd "~1.1.0" + on-finished "~2.3.0" + on-headers "~1.0.1" + morgan@1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.1.tgz#f93023d3887bd27b78dfd6023cea7892ee27a4b1" @@ -2018,13 +2259,13 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -naclb@1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/naclb/-/naclb-1.3.7.tgz#df606c3ae4442e67932c9aaeaf36eebef8860b48" +naclb@1.3.9: + version "1.3.9" + resolved "https://registry.yarnpkg.com/naclb/-/naclb-1.3.9.tgz#8fdf893682a71494b964b24f4b59429d02998ef7" dependencies: bindings "1.2.1" nan "2.2.0" - node-pre-gyp "0.6.23" + node-pre-gyp "0.6.33" nan@2.2.0: version "2.2.0" @@ -2042,6 +2283,10 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +negotiator@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -2055,6 +2300,13 @@ nnupnp@1.0.2: request "2.10.0" xml2js "0.1.14" +node-archiver@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/node-archiver/-/node-archiver-0.3.0.tgz#b9f1afe5006d0bdf29260181833a070978bc6947" + dependencies: + fstream "^1.0.10" + tar "^2.2.1" + node-pre-gyp@0.6.23: version "0.6.23" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.23.tgz#155bf3683abcfcde008aedab1248891a0773db95" @@ -2069,9 +2321,9 @@ node-pre-gyp@0.6.23: tar "~2.2.0" tar-pack "~3.1.0" -node-pre-gyp@0.6.32: - version "0.6.32" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5" +node-pre-gyp@0.6.33: + version "0.6.33" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.33.tgz#640ac55198f6a925972e0c16c4ac26a034d5ecc9" dependencies: mkdirp "~0.5.1" nopt "~3.0.6" @@ -2083,7 +2335,7 @@ node-pre-gyp@0.6.32: tar "~2.2.1" tar-pack "~3.3.0" -node-pre-gyp@0.6.34, node-pre-gyp@~0.6.28: +node-pre-gyp@0.6.34, node-pre-gyp@^0.6.34, node-pre-gyp@~0.6.28: version "0.6.34" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" dependencies: @@ -2252,10 +2504,6 @@ osenv@^0.1.4: version "0.0.5" resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" -parallelshell@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parallelshell/-/parallelshell-2.0.0.tgz#c94af5d6348526a26da9020faeb5fc724a80600c" - parseurl@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" @@ -2312,6 +2560,13 @@ progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" +proxy-addr@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.0.10.tgz#0d40a82f801fc355567d2ecb65efe3f077f121c5" + dependencies: + forwarded "~0.1.0" + ipaddr.js "1.0.5" + proxy-addr@~1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3" @@ -2347,6 +2602,14 @@ q@1.5.0, q@^1.0.1: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" +qs@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" + +qs@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.1.0.tgz#ec1d1626b24278d99f0fdf4549e524e24eceeb26" + qs@6.4.0, qs@^6.1.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -2367,10 +2630,22 @@ ramda@^0.22.1: version "0.22.1" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.22.1.tgz#031da0c3df417c5b33c96234757eb37033f36a0e" +range-parser@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" + range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" +raw-body@~2.1.6: + version "2.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" + dependencies: + bytes "2.4.0" + iconv-lite "0.4.13" + unpipe "1.0.0" + raw-body@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96" @@ -2407,14 +2682,14 @@ readable-stream@1.1.x: string_decoder "~0.10.x" readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2: - version "2.2.9" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" + version "2.2.11" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.11.tgz#0796b31f8d7688007ff0b93a8088d34aa17c0f72" dependencies: - buffer-shims "~1.0.0" core-util-is "~1.0.0" inherits "~2.0.1" isarray "~1.0.0" process-nextick-args "~1.0.6" + safe-buffer "~5.0.1" string_decoder "~1.0.0" util-deprecate "~1.0.1" @@ -2461,8 +2736,8 @@ rechoir@^0.6.2: resolve "^1.1.6" remove-trailing-separator@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" + version "1.0.2" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" repeat-string@^1.5.2: version "1.6.1" @@ -2576,7 +2851,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: +rimraf@2, rimraf@2.6.1, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -2613,6 +2888,10 @@ rx@^4.1.0: resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" safe-buffer@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223" + +safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" @@ -2628,6 +2907,10 @@ scryptb@6.0.4: nan "2.2.0" node-pre-gyp "0.6.23" +seedrandom@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc" + semver@^5.3.0, semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -2636,6 +2919,40 @@ semver@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19" +send@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.13.1.tgz#a30d5f4c82c8a9bae9ad00a1d9b1bdbe6f199ed7" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.3.1" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.0.3" + statuses "~1.2.1" + +send@0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.3.1" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.0.3" + statuses "~1.2.1" + send@0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/send/-/send-0.15.1.tgz#8a02354c26e6f5cca700065f5f0cdeba90ec7b5f" @@ -2663,6 +2980,14 @@ serve-static@1.12.1: parseurl "~1.3.1" send "0.15.1" +serve-static@~1.10.2: + version "1.10.3" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" + dependencies: + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.13.2" + set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -2683,8 +3008,8 @@ sha1@: crypt ">= 0.0.1" shelljs@^0.7.5: - version "0.7.7" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -2805,8 +3130,8 @@ sqlite3@3.1.4: node-pre-gyp "~0.6.28" sshpk@^1.7.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c" + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -2815,7 +3140,6 @@ sshpk@^1.7.0: optionalDependencies: bcrypt-pbkdf "^1.0.0" ecc-jsbn "~0.1.1" - jodid25519 "^1.0.0" jsbn "~0.1.0" tweetnacl "~0.14.0" @@ -2823,10 +3147,14 @@ stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" -"statuses@>= 1.3.1 < 2", statuses@~1.3.1: +statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2", statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +statuses@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" + stealthy-require@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -2865,10 +3193,10 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" string_decoder@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" + version "1.0.2" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.2.tgz#b29e1f4e1125fa97a10382b8a533737b7491e179" dependencies: - buffer-shims "~1.0.0" + safe-buffer "~5.0.1" stringstream@~0.0.4: version "0.0.5" @@ -2946,8 +3274,8 @@ table@^3.7.8: string-width "^2.0.0" tail@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/tail/-/tail-1.2.1.tgz#c998a0cd9f8bf6dce780a6bc7339e66371e0db3f" + version "1.2.2" + resolved "https://registry.yarnpkg.com/tail/-/tail-1.2.2.tgz#3c40a47d53e137c541a14cc133532ecb2a75cc51" tar-pack@^3.4.0: version "3.4.0" @@ -3023,7 +3351,7 @@ tmp@0.0.29: dependencies: os-tmpdir "~1.0.1" -tmp@^0.0.31: +tmp@0.0.31, tmp@^0.0.31: version "0.0.31" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" dependencies: @@ -3057,11 +3385,11 @@ tweetnacl-util@0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz#4576c1cee5e2d63d207fee52f1ba02819480bc75" -tweetnacl@0.14.3, tweetnacl@^0.14.3, tweetnacl@~0.14.0: +tweetnacl@0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.3.tgz#3da382f670f25ded78d7b3d1792119bca0b7132d" -tweetnacl@0.14.5: +tweetnacl@0.14.5, tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -3071,7 +3399,7 @@ type-check@~0.3.1, type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-is@~1.6.14: +type-is@~1.6.12, type-is@~1.6.14, type-is@~1.6.6: version "1.6.15" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" dependencies: @@ -3083,8 +3411,8 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" uglify-js@^2.6: - version "2.8.26" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.26.tgz#3a1db8ae0a0aba7f92e1ddadadbd0293d549f90e" + version "2.8.28" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.28.tgz#e335032df9bb20dcb918f164589d5af47f38834a" dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -3119,6 +3447,10 @@ underscore@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" +universalify@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.0.tgz#9eb1c4651debcc670cc94f1a75762332bb967778" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3175,6 +3507,10 @@ vary@^1, vary@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" +vary@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" + verror@1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" @@ -3228,7 +3564,7 @@ wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" -wotb@^0.5.9: +wotb@0.5.x: version "0.5.9" resolved "https://registry.yarnpkg.com/wotb/-/wotb-0.5.9.tgz#5918ee30ca746ec1ba2e8ccc9e1421e709995be2" dependencies: