From 812d32c8f783ccf933a6d7b187c58c3b8ae8f0ae Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Sat, 14 Jul 2018 16:29:16 +0200
Subject: [PATCH] [fix] on start DB cleanup could cause a crash of Duniter

---
 app/lib/blockchain/DuniterBlockchain.ts  | 14 ++++----------
 app/lib/computation/BlockchainContext.ts | 17 +++++++++++++++--
 app/service/BlockchainService.ts         |  4 ++++
 server.ts                                |  6 +++++-
 4 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/app/lib/blockchain/DuniterBlockchain.ts b/app/lib/blockchain/DuniterBlockchain.ts
index fd683b19e..074af4420 100644
--- a/app/lib/blockchain/DuniterBlockchain.ts
+++ b/app/lib/blockchain/DuniterBlockchain.ts
@@ -33,7 +33,6 @@ import {MembershipDTO} from "../dto/MembershipDTO"
 import {TransactionDTO} from "../dto/TransactionDTO"
 import {CommonConstants} from "../common-libs/constants"
 import {FileDAL} from "../dal/fileDAL"
-import {DataErrors} from "../common-libs/errors"
 import {NewLogger} from "../logger"
 import {DBTx} from "../db/DBTx"
 import {Underscore} from "../common-libs/underscore"
@@ -372,14 +371,9 @@ export class DuniterBlockchain {
     }
   }
 
-  static async revertBlock(number:number, hash:string, dal:FileDAL) {
+  static async revertBlock(number:number, hash:string, dal:FileDAL, block?: DBBlock) {
 
     const blockstamp = [number, hash].join('-');
-    const block = await dal.getAbsoluteValidBlockInForkWindow(number, hash)
-
-    if (!block) {
-      throw DataErrors[DataErrors.BLOCK_TO_REVERT_NOT_FOUND]
-    }
 
     // Revert links
     const writtenOn = await dal.cindexDAL.getWrittenOn(blockstamp);
@@ -421,9 +415,9 @@ export class DuniterBlockchain {
     await this.updateWallets(sindexOfBlock, [], dal, REVERSE_BALANCE)
 
     // Restore block's transaction as incoming transactions
-    await this.undoDeleteTransactions(block, dal)
-
-    return block
+    if (block) {
+      await this.undoDeleteTransactions(block, dal)
+    }
   }
 
   static async undoMembersUpdate(blockstamp:string, dal:FileDAL) {
diff --git a/app/lib/computation/BlockchainContext.ts b/app/lib/computation/BlockchainContext.ts
index 9705c2eed..daf505a3a 100644
--- a/app/lib/computation/BlockchainContext.ts
+++ b/app/lib/computation/BlockchainContext.ts
@@ -18,6 +18,7 @@ import {DBHead} from "../db/DBHead"
 import {FileDAL} from "../dal/fileDAL"
 import {DBBlock} from "../db/DBBlock"
 import {Underscore} from "../common-libs/underscore"
+import {DataErrors} from "../common-libs/errors"
 
 const indexer         = require('../indexer').Indexer
 const constants       = require('../constants');
@@ -131,10 +132,22 @@ export class BlockchainContext {
   async revertCurrentBlock(): Promise<DBBlock> {
     const head_1 = await this.dal.bindexDAL.head(1);
     this.logger.debug('Reverting block #%s...', head_1.number);
-    const res = await DuniterBlockchain.revertBlock(head_1.number, head_1.hash, this.dal)
+    const block = await this.dal.getAbsoluteValidBlockInForkWindow(head_1.number, head_1.hash)
+    if (!block) {
+      throw DataErrors[DataErrors.BLOCK_TO_REVERT_NOT_FOUND]
+    }
+    await DuniterBlockchain.revertBlock(head_1.number, head_1.hash, this.dal, block)
+    // Invalidates the head, since it has changed.
+    await this.refreshHead();
+    return block
+  }
+
+  async revertCurrentHead() {
+    const head_1 = await this.dal.bindexDAL.head(1);
+    this.logger.debug('Reverting HEAD~1... (b#%s)', head_1.number);
+    await DuniterBlockchain.revertBlock(head_1.number, head_1.hash, this.dal)
     // Invalidates the head, since it has changed.
     await this.refreshHead();
-    return res;
   }
 
   async applyNextAvailableFork(): Promise<any> {
diff --git a/app/service/BlockchainService.ts b/app/service/BlockchainService.ts
index 5efc339d0..27eb39a7f 100644
--- a/app/service/BlockchainService.ts
+++ b/app/service/BlockchainService.ts
@@ -282,6 +282,10 @@ export class BlockchainService extends FIFOService {
   revertCurrentBlock() {
     return this.pushFIFO("revertCurrentBlock", () => this.mainContext.revertCurrentBlock())
   }
+
+  revertCurrentHead() {
+    return this.pushFIFO("revertCurrentHead", () => this.mainContext.revertCurrentHead())
+  }
   
 
   applyNextAvailableFork() {
diff --git a/server.ts b/server.ts
index 69cd309e7..1ddb6257a 100644
--- a/server.ts
+++ b/server.ts
@@ -340,7 +340,7 @@ export class Server extends stream.Duplex implements HookableServer {
       const current = await this.dal.blockDAL.getCurrent();
       const nbBlocksToRevert = (head_1.number - (current as DBBlock).number);
       for (let i = 0; i < nbBlocksToRevert; i++) {
-        await this.revert();
+        await this.revertHead();
       }
     }
     // Database trimming
@@ -502,6 +502,10 @@ export class Server extends stream.Duplex implements HookableServer {
     return this.BlockchainService.revertCurrentBlock()
   }
 
+  revertHead() {
+    return this.BlockchainService.revertCurrentHead()
+  }
+
   async revertTo(number:number) {
     const current = await this.BlockchainService.current();
     if (!current) {
-- 
GitLab