From f97e182e15ee7805182a75ca5d864b1e4c6444bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Moreau?= <cem.moreau@gmail.com>
Date: Sat, 17 Feb 2018 16:58:22 +0100
Subject: [PATCH] [fix] #1277 Correctly forge blocks including chained txs

---
 app/lib/rules/global_rules.ts            | 16 +++++++++++-----
 app/modules/prover/lib/blockGenerator.ts | 17 +++++++++--------
 app/service/TransactionsService.ts       |  3 +--
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/app/lib/rules/global_rules.ts b/app/lib/rules/global_rules.ts
index 761dcf3dc..4fa145004 100644
--- a/app/lib/rules/global_rules.ts
+++ b/app/lib/rules/global_rules.ts
@@ -9,6 +9,7 @@ import {CommonConstants} from "../common-libs/constants"
 import {IdentityDTO} from "../dto/IdentityDTO"
 import {hashf} from "../common"
 import {Indexer} from "../indexer"
+import {DBTx} from "../dal/sqliteDAL/TxsDAL"
 
 const _ = require('underscore')
 
@@ -80,7 +81,7 @@ export const GLOBAL_RULES_FUNCTIONS = {
     return true;
   },
 
-  checkSourcesAvailability: async (block:{ transactions:TransactionDTO[], medianTime: number }, conf:ConfDTO, dal:FileDAL, alsoCheckPendingTransactions:boolean) => {
+  checkSourcesAvailability: async (block:{ transactions:TransactionDTO[], medianTime: number }, conf:ConfDTO, dal:FileDAL, findSourceTx:(txHash:string) => Promise<DBTx|null>) => {
     const txs = block.transactions
     const current = await dal.getCurrentBlockOrNull();
     for (const tx of txs) {
@@ -98,12 +99,12 @@ export const GLOBAL_RULES_FUNCTIONS = {
         let src = inputs[k];
         let dbSrc = await 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) {
+        if (!dbSrc) {
           // 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 = await (async () => {
             let hypotheticSrc:any = null;
-            let targetTX = await dal.getTxByHash(src.identifier);
+            let targetTX = await findSourceTx(src.identifier);
             if (targetTX) {
               let outputStr = targetTX.outputs[src.pos];
               if (outputStr) {
@@ -193,10 +194,15 @@ export const GLOBAL_RULES_HELPERS = {
 
   checkExistsPubkey: (pub:string, dal:FileDAL) => dal.getWrittenIdtyByPubkey(pub),
 
-  checkSingleTransaction: (tx:TransactionDTO, block:{ medianTime: number }, conf:ConfDTO, dal:FileDAL, alsoCheckPendingTransactions:boolean = false) => GLOBAL_RULES_FUNCTIONS.checkSourcesAvailability({
+  checkSingleTransaction: (
+    tx:TransactionDTO,
+    block:{ medianTime: number },
+    conf:ConfDTO,
+    dal:FileDAL,
+    findSourceTx:(txHash:string) => Promise<DBTx|null>) => GLOBAL_RULES_FUNCTIONS.checkSourcesAvailability({
     transactions: [tx],
     medianTime: block.medianTime
-  }, conf, dal, alsoCheckPendingTransactions),
+  }, conf, dal, findSourceTx),
 
   checkTxBlockStamp: async (tx:TransactionDTO, dal:FileDAL) => {
     const number = parseInt(tx.blockstamp.split('-')[0])
diff --git a/app/modules/prover/lib/blockGenerator.ts b/app/modules/prover/lib/blockGenerator.ts
index 39d9cb45a..938bc3788 100644
--- a/app/modules/prover/lib/blockGenerator.ts
+++ b/app/modules/prover/lib/blockGenerator.ts
@@ -105,7 +105,6 @@ export class BlockGenerator {
   }
 
   private async findTransactions(current:DBBlock, options:{ dontCareAboutChaining?:boolean }) {
-    const ALSO_CHECK_PENDING_TXS = true
     const versionMin = current ? Math.min(CommonConstants.LAST_VERSION_FOR_TX, current.version) : CommonConstants.DOCUMENTS_VERSION;
     const txs = await this.dal.getTransactionsPending(versionMin);
     const transactions = [];
@@ -116,7 +115,9 @@ export class BlockGenerator {
       try {
         await LOCAL_RULES_HELPERS.checkBunchOfTransactions(passingTxs.concat(tx), this.conf, options)
         const nextBlockWithFakeTimeVariation = { medianTime: current.medianTime + 1 };
-        await GLOBAL_RULES_HELPERS.checkSingleTransaction(tx, nextBlockWithFakeTimeVariation, this.conf, this.dal, ALSO_CHECK_PENDING_TXS);
+        await GLOBAL_RULES_HELPERS.checkSingleTransaction(tx, nextBlockWithFakeTimeVariation, this.conf, this.dal, async (txHash:string) => {
+          return _.findWhere(passingTxs, { hash: txHash }) || null
+        });
         await GLOBAL_RULES_HELPERS.checkTxBlockStamp(tx, this.dal);
         transactions.push(tx);
         passingTxs.push(tx);
@@ -779,12 +780,12 @@ class ManualRootGenerator implements BlockGeneratorInterface {
 
     if (newcomers.length > 0) {
       const answers = await inquirer.prompt([{
-          type: "checkbox",
-          name: "uids",
-          message: "Newcomers to add",
-          choices: uids,
-          default: uids[0]
-        }]);
+        type: "checkbox",
+        name: "uids",
+        message: "Newcomers to add",
+        choices: uids,
+        default: uids[0]
+      }]);
       newcomers.forEach((newcomer:string) => {
         if (~answers.uids.indexOf(preJoinData[newcomer].ms.userid))
           filtered[newcomer] = preJoinData[newcomer];
diff --git a/app/service/TransactionsService.ts b/app/service/TransactionsService.ts
index 3068c1b71..a36dd89f0 100644
--- a/app/service/TransactionsService.ts
+++ b/app/service/TransactionsService.ts
@@ -9,7 +9,6 @@ import {FIFOService} from "./FIFOService";
 import {GlobalFifoPromise} from "./GlobalFifoPromise";
 
 const constants       = require('../lib/constants');
-const CHECK_PENDING_TRANSACTIONS = true
 
 export class TransactionService extends FIFOService {
 
@@ -43,7 +42,7 @@ export class TransactionService extends FIFOService {
         const dto = TransactionDTO.fromJSONObject(tx)
         await LOCAL_RULES_HELPERS.checkSingleTransactionLocally(dto, this.conf)
         await GLOBAL_RULES_HELPERS.checkTxBlockStamp(tx, this.dal);
-        await GLOBAL_RULES_HELPERS.checkSingleTransaction(dto, nextBlockWithFakeTimeVariation, this.conf, this.dal, CHECK_PENDING_TRANSACTIONS);
+        await GLOBAL_RULES_HELPERS.checkSingleTransaction(dto, nextBlockWithFakeTimeVariation, this.conf, this.dal, this.dal.getTxByHash.bind(this.dal));
         const server_pubkey = this.conf.pair && this.conf.pair.pub;
         if (!(await this.dal.txsDAL.sandbox.acceptNewSandBoxEntry({
             issuers: tx.issuers,
-- 
GitLab