diff --git a/.gitignore b/.gitignore
index 9b656c46522606b19e13f3c4310831863ca3426b..1a8aef2074a1563edf3994813d403786f81879ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,7 @@ test/integration/documents-currency.d.ts
 test/integration/forwarding.js
 test/integration/branches_switch.js
 test/integration/branches2.js
+test/integration/transactions-chaining.js
 test/fast/modules/crawler/block_pulling.js*
 test/fast/modules/crawler/block_pulling.d.ts
 test/fast/fork*.js*
@@ -72,3 +73,6 @@ test/fast/modules/common/grammar.d.ts
 test/fast/prover/pow-1-cluster.d.ts
 test/fast/prover/pow-1-cluster.js
 test/fast/prover/pow-1-cluster.js.map
+test/fast/protocol-local-rule-chained-tx-depth.js
+test/fast/protocol-local-rule-chained-tx-depth.js.map
+test/fast/protocol-local-rule-chained-tx-depth.d.ts
diff --git a/app/lib/common-libs/constants.ts b/app/lib/common-libs/constants.ts
index b34cb6278407c8679b19c508cc6b86ce7f5473f2..e1be3f6661f221523d06aad8460cb82d3c36f6a4 100644
--- a/app/lib/common-libs/constants.ts
+++ b/app/lib/common-libs/constants.ts
@@ -285,6 +285,8 @@ export const CommonConstants = {
     BLOCK: find("Block: (" + INTEGER + "-" + FINGERPRINT + ")"),
     SPECIAL_BLOCK
   },
+
+  BLOCK_MAX_TX_CHAINING_DEPTH: 5
 }
 
 function exact (regexpContent:string) {
diff --git a/app/lib/rules/index.ts b/app/lib/rules/index.ts
index 44ca3d2535efb9cd8d8733317a255ad80f74cf5e..28d13899b467bb69fe4a8c9be2e9c0bcd021bcac 100644
--- a/app/lib/rules/index.ts
+++ b/app/lib/rules/index.ts
@@ -33,6 +33,7 @@ export const ALIAS = {
     await LOCAL_RULES_FUNCTIONS.checkTxRecipients(block);
     await LOCAL_RULES_FUNCTIONS.checkTxAmounts(block);
     await LOCAL_RULES_FUNCTIONS.checkTxSignature(block);
+    await LOCAL_RULES_FUNCTIONS.checkMaxTransactionChainingDepth(block, conf, index);
   },
 
   ALL_LOCAL_BUT_POW_AND_SIGNATURE: async (block:BlockDTO, conf:ConfDTO, index:IndexEntry[]) => {
@@ -60,6 +61,7 @@ export const ALIAS = {
     await LOCAL_RULES_FUNCTIONS.checkTxRecipients(block);
     await LOCAL_RULES_FUNCTIONS.checkTxAmounts(block);
     await LOCAL_RULES_FUNCTIONS.checkTxSignature(block);
+    await LOCAL_RULES_FUNCTIONS.checkMaxTransactionChainingDepth(block, conf, index);
   }
 }
 
diff --git a/app/lib/rules/local_rules.ts b/app/lib/rules/local_rules.ts
index 41d19f163d8b3a377fb2e6832c7be37dae36d2d3..5a608112485b7afc5b732204aecf0d0fcef3374c 100644
--- a/app/lib/rules/local_rules.ts
+++ b/app/lib/rules/local_rules.ts
@@ -379,28 +379,70 @@ export const LOCAL_RULES_FUNCTIONS = {
       }
     }
     return true;
+  },
+
+  checkMaxTransactionChainingDepth: async (block:BlockDTO, conf:ConfDTO, index:IndexEntry[]) => {
+    const sindex = Indexer.sindex(index)
+    const max = getMaxTransactionDepth(sindex)
+    //
+    const allowedMax = block.medianTime > 1517443200 ? CommonConstants.BLOCK_MAX_TX_CHAINING_DEPTH : 1
+    if (max > allowedMax) {
+      throw "The maximum transaction chaining length per block is " + CommonConstants.BLOCK_MAX_TX_CHAINING_DEPTH
+    }
+    return true
+  }
+}
+
+export interface SindexShortEntry {
+  op:string,
+  identifier:string,
+  pos:number,
+  tx:string|null
+}
+
+function getMaxTransactionDepth(sindex:SindexShortEntry[]) {
+  const ids = _.uniq(_.pluck(sindex, 'tx'))
+  let maxTxChainingDepth = 0
+  for (let id of ids) {
+    maxTxChainingDepth = Math.max(maxTxChainingDepth, getTransactionDepth(id, sindex, 0))
   }
+  return maxTxChainingDepth
+}
+
+function getTransactionDepth(txHash:string, sindex:SindexShortEntry[], localDepth = 0) {
+  const inputs = _.filter(sindex, (s:SindexShortEntry) => s.op === 'UPDATE' && s.tx === txHash)
+  let depth = localDepth
+  for (let input of inputs) {
+    const consumedOutput = _.findWhere(sindex, { op: 'CREATE', identifier: input.identifier, pos: input.pos })
+    if (consumedOutput) {
+      if (localDepth < 5) {
+        const subTxDepth = getTransactionDepth(consumedOutput.tx, sindex, localDepth + 1)
+        depth = Math.max(depth, subTxDepth)
+      } else {
+        depth++
+      }
+    }
+  }
+  return depth
 }
 
 function checkSingleMembershipSignature(ms:any) {
   return verify(ms.getRaw(), ms.signature, ms.issuer);
 }
 
-function checkBunchOfTransactions(transactions:TransactionDTO[], done:any = undefined){
-  const block:any = { transactions };
+function checkBunchOfTransactions(transactions:TransactionDTO[], conf:ConfDTO, options?:{ dontCareAboutChaining?:boolean }){
+  const block:any = { transactions, identities: [], joiners: [], actives: [], leavers: [], revoked: [], excluded: [], certifications: [] };
+  const index = Indexer.localIndex(block, conf)
   return (async () => {
-    try {
-      let local_rule = LOCAL_RULES_FUNCTIONS;
-      await local_rule.checkTxLen(block);
-      await local_rule.checkTxIssuers(block);
-      await local_rule.checkTxSources(block);
-      await local_rule.checkTxRecipients(block);
-      await local_rule.checkTxAmounts(block);
-      await local_rule.checkTxSignature(block);
-      done && done();
-    } catch (err) {
-      if (done) return done(err);
-      throw err;
+    let local_rule = LOCAL_RULES_FUNCTIONS;
+    await local_rule.checkTxLen(block);
+    await local_rule.checkTxIssuers(block);
+    await local_rule.checkTxSources(block);
+    await local_rule.checkTxRecipients(block);
+    await local_rule.checkTxAmounts(block);
+    await local_rule.checkTxSignature(block);
+    if (!options || !options.dontCareAboutChaining) {
+      await local_rule.checkMaxTransactionChainingDepth(block, conf, index);
     }
   })()
 }
@@ -411,9 +453,13 @@ export const LOCAL_RULES_HELPERS = {
 
   checkSingleMembershipSignature: checkSingleMembershipSignature,
 
-  checkBunchOfTransactions: checkBunchOfTransactions,
+  checkBunchOfTransactions,
+
+  getTransactionDepth,
+
+  getMaxTransactionDepth,
 
-  checkSingleTransactionLocally: (tx:any, done:any = undefined) => checkBunchOfTransactions([tx], done),
+  checkSingleTransactionLocally: (tx:any, conf:ConfDTO) => checkBunchOfTransactions([tx], conf),
 
   checkTxAmountsValidity: (tx:TransactionDTO) => {
     const inputs = tx.inputsAsObjects()
diff --git a/app/modules/prover/lib/blockGenerator.ts b/app/modules/prover/lib/blockGenerator.ts
index c41dfb24283028cae37c2d7cd09d4fad815a6fdc..39d9cb45aee91ab8d19df5bdd52f9ccee77944d3 100644
--- a/app/modules/prover/lib/blockGenerator.ts
+++ b/app/modules/prover/lib/blockGenerator.ts
@@ -65,7 +65,7 @@ export class BlockGenerator {
     const wereExcludeds = await this.dal.getRevokedPubkeys();
     const newCertsFromWoT = await generator.findNewCertsFromWoT(current);
     const newcomersLeavers = await this.findNewcomersAndLeavers(current, (joinersData:any) => generator.filterJoiners(joinersData));
-    const transactions = await this.findTransactions(current);
+    const transactions = await this.findTransactions(current, manualValues);
     const joinData = newcomersLeavers[2];
     const leaveData = newcomersLeavers[3];
     const newCertsFromNewcomers = newcomersLeavers[4];
@@ -104,7 +104,8 @@ export class BlockGenerator {
     return [cur, newWoTMembers, finalJoinData, leavers, updates];
   }
 
-  private async findTransactions(current:DBBlock) {
+  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 = [];
@@ -113,14 +114,9 @@ export class BlockGenerator {
       obj.currency = this.conf.currency
       const tx = TransactionDTO.fromJSONObject(obj);
       try {
-        await new Promise((resolve, reject) => {
-          LOCAL_RULES_HELPERS.checkBunchOfTransactions(passingTxs.concat(tx), (err:any, res:any) => {
-            if (err) return reject(err)
-            return resolve(res)
-          })
-        })
+        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);
+        await GLOBAL_RULES_HELPERS.checkSingleTransaction(tx, nextBlockWithFakeTimeVariation, this.conf, this.dal, ALSO_CHECK_PENDING_TXS);
         await GLOBAL_RULES_HELPERS.checkTxBlockStamp(tx, this.dal);
         transactions.push(tx);
         passingTxs.push(tx);
diff --git a/app/service/BlockchainService.ts b/app/service/BlockchainService.ts
index ba652048307abf4a5d3bbacc9da9f89edd562bce..e8148d81d2945f241a7f7be44384050b6b75991d 100644
--- a/app/service/BlockchainService.ts
+++ b/app/service/BlockchainService.ts
@@ -217,8 +217,9 @@ export class BlockchainService extends FIFOService {
         } catch (e) {
           this.logger.error(e)
           added = false
+          const theError = e && (e.message || e)
           this.push({
-            blockResolutionError: e && e.message
+            blockResolutionError: theError
           })
         }
         i++
diff --git a/app/service/TransactionsService.ts b/app/service/TransactionsService.ts
index e6ddf1263234920e509ca684438cc19cec1ecb5f..3068c1b71430fb521ad15146ff6fae11fb879965 100644
--- a/app/service/TransactionsService.ts
+++ b/app/service/TransactionsService.ts
@@ -41,7 +41,7 @@ export class TransactionService extends FIFOService {
         // Start checks...
         const nextBlockWithFakeTimeVariation = { medianTime: current.medianTime + 1 };
         const dto = TransactionDTO.fromJSONObject(tx)
-        await LOCAL_RULES_HELPERS.checkSingleTransactionLocally(dto)
+        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);
         const server_pubkey = this.conf.pair && this.conf.pair.pub;
diff --git a/doc/Protocol.md b/doc/Protocol.md
index bc424f2d774934b30086c142123e2380cc3ecf5d..68a5300a4c3744b878f4c44cf058d8c89764e801 100644
--- a/doc/Protocol.md
+++ b/doc/Protocol.md
@@ -1549,6 +1549,40 @@ TRUE
 > Functionally: we cannot create nor lose money through transactions. We can only transfer coins we own.
 > Functionally: also, we cannot convert a superiod unit base into a lower one.
 
+##### Transactions chaining max depth
+
+    FUNCTION `getTransactionDepth(txHash, LOCAL_DEPTH)`:
+
+        INPUTS = LOCAL_SINDEX[op='UPDATE',tx=txHash]
+        DEPTH = LOCAL_DEPTH
+
+        FOR EACH `INPUT` OF `INPUTS`
+            CONSUMED = LOCAL_SINDEX[op='CREATE',identifier=INPUT.identifier,pos=INPUT.pos]
+            IF (CONSUMED != NULL)
+                IF (LOCAL_DEPTH < 5)
+                    DEPTH = MAX(DEPTH, getTransactionDepth(CONSUMED.tx, LOCAL_DEPTH +1)
+                ELSE
+                    DEPTH++
+                END_IF
+            END_IF
+        END_FOR
+
+        RETURN DEPTH
+
+    END_FUNCTION
+
+Then:
+
+    maxTxChainingDepth = 0
+
+For each `TX_HASH` of `UNIQ(PICK(LOCAL_SINDEX, 'tx))`:
+
+    maxTxChainingDepth = MAX(maxTxChainingDepth, getTransactionDepth(TX_HASH, 0))
+
+Rule:
+
+    maxTxChainingDepth <= 5
+
 #### Global
 
 Global validation verifies the coherence of a locally-validated block, in the context of the whole blockchain, including the block.
@@ -1580,6 +1614,7 @@ Function references:
 > If values count is even, the median is computed over the 2 centered values by an arithmetical median on them, *NOT* rounded.
 
 * *UNIQ* returns a list of the unique values in a list of values
+* *PICK* returns a list of the values by picking a particular property on each record
 * *INTEGER_PART* return the integer part of a number
 * *FIRST* return the first element in a list of values matching the given condition
 * *REDUCE* merges a set of elements into a single one, by extending the non-null properties from each record into the resulting record.
diff --git a/test/fast/protocol-local-rule-chained-tx-depth.ts b/test/fast/protocol-local-rule-chained-tx-depth.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a13f0fb3c45bc7d979aa3c98e7c914fe8657a640
--- /dev/null
+++ b/test/fast/protocol-local-rule-chained-tx-depth.ts
@@ -0,0 +1,45 @@
+import {LOCAL_RULES_HELPERS} from "../../app/lib/rules/local_rules"
+
+const _ = require('underscore')
+const assert = require('assert')
+
+describe("Protocol BR_G110 - chained tx depth", () => {
+
+  const sindex = [
+    { tx: 'A', op: 'UPDATE', identifier: 'UD1', pos: 0 },
+    { tx: 'A', op: 'CREATE', identifier: 'TXA', pos: 0 },
+    { tx: 'B', op: 'UPDATE', identifier: 'TXA', pos: 0 },
+    { tx: 'B', op: 'CREATE', identifier: 'TXB', pos: 0 },
+    { tx: 'C', op: 'UPDATE', identifier: 'TXB', pos: 0 },
+    { tx: 'C', op: 'CREATE', identifier: 'TXC', pos: 0 },
+    { tx: 'D', op: 'UPDATE', identifier: 'TXC', pos: 0 },
+    { tx: 'D', op: 'CREATE', identifier: 'TXD', pos: 0 },
+    { tx: 'E', op: 'UPDATE', identifier: 'TXD', pos: 0 },
+    { tx: 'E', op: 'CREATE', identifier: 'TXE', pos: 0 },
+    { tx: 'F', op: 'UPDATE', identifier: 'TXE', pos: 0 },
+    { tx: 'F', op: 'CREATE', identifier: 'TXF', pos: 0 },
+    { tx: 'G', op: 'UPDATE', identifier: 'TXF', pos: 0 },
+    { tx: 'G', op: 'CREATE', identifier: 'TXG', pos: 0 },
+    { tx: 'H', op: 'UPDATE', identifier: 'TXG', pos: 0 },
+    { tx: 'H', op: 'CREATE', identifier: 'TXH', pos: 0 },
+  ]
+
+  it('should detected normal depth', () => {
+    assert.equal(0, LOCAL_RULES_HELPERS.getTransactionDepth('A', sindex))
+    assert.equal(1, LOCAL_RULES_HELPERS.getTransactionDepth('B', sindex))
+    assert.equal(2, LOCAL_RULES_HELPERS.getTransactionDepth('C', sindex))
+    assert.equal(3, LOCAL_RULES_HELPERS.getTransactionDepth('D', sindex))
+    assert.equal(4, LOCAL_RULES_HELPERS.getTransactionDepth('E', sindex))
+    assert.equal(5, LOCAL_RULES_HELPERS.getTransactionDepth('F', sindex))
+    assert.equal(6, LOCAL_RULES_HELPERS.getTransactionDepth('G', sindex))
+  })
+
+  it('should detected max the depth to 6', () => {
+    assert.equal(6, LOCAL_RULES_HELPERS.getTransactionDepth('H', sindex))
+  })
+
+  it('should find the max depth globally', () => {
+    assert.equal(6, LOCAL_RULES_HELPERS.getMaxTransactionDepth(sindex))
+  })
+})
+
diff --git a/test/integration/transactions-chaining.js b/test/integration/transactions-chaining.js
deleted file mode 100644
index 66a02c1ca402f6046a8ece5faaa057bbd26efba0..0000000000000000000000000000000000000000
--- a/test/integration/transactions-chaining.js
+++ /dev/null
@@ -1,92 +0,0 @@
-"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('../../app/modules/bma').BmaDependency.duniter.methods.bma;
-const CommonConstants = require('../../app/lib/common-libs/constants').CommonConstants
-const toolbox   = require('./tools/toolbox');
-const node   = require('./tools/node');
-const TestUser = require('./tools/TestUser').TestUser
-const unit   = require('./tools/unit');
-const http   = require('./tools/http');
-
-describe("Transaction chaining", function() {
-
-  const now = 1456644632;
-
-  let s1, tic, toc
-
-  before(() => co(function*() {
-
-    s1 = toolbox.server({
-      pair: {
-        pub: 'DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV',
-        sec: '468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7'
-      },
-      dt: 3600,
-      udTime0: now + 3600,
-      ud0: 1200,
-      c: 0.1
-    });
-
-    tic = new TestUser('tic', { pub: 'DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV', sec: '468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7'}, { server: s1 });
-    toc = new TestUser('toc', { pub: 'DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo', sec: '64EYRvdPpTfLGGmaX5nijLXRqWXaVz8r1Z1GtaahXwVSJGQRn7tqkxLb288zwSYzELMEG5ZhXSBYSxsTsz1m9y8F'}, { server: s1 });
-
-    yield s1.initDalBmaConnections();
-    yield tic.createIdentity();
-    yield toc.createIdentity();
-    yield tic.cert(toc);
-    yield toc.cert(tic);
-    yield tic.join();
-    yield toc.join();
-    yield s1.commit({ time: now });
-    yield s1.commit({ time: now + 7210 });
-    yield s1.commit({ time: now + 7210 });
-  }));
-
-  after(() => {
-    return Promise.all([
-      s1.closeCluster()
-    ])
-  })
-
-  describe("Sources", function(){
-
-    it('it should exist block#2 with UD of 1200', () => s1.expect('/blockchain/block/2', (block) => {
-      should.exists(block);
-      assert.equal(block.number, 2);
-      assert.equal(block.dividend, 1200);
-    }));
-  });
-
-  describe("Chaining", function(){
-
-    it('with SIG and XHX', () => co(function *() {
-      // Current state
-      let current = yield s1.get('/blockchain/current');
-      (yield s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(1);
-      let tx1 = yield toc.prepareITX(1040, tic); // Rest = 1200 - 1040 = 160
-      let tx2 = yield toc.prepareUTX(tx1, ['SIG(0)'], [{ qty: 160, base: 0, lock: 'SIG(' + tic.pub + ')' }], {
-        comment: 'also take the remaining 160 units',
-        blockstamp: [current.number, current.hash].join('-'),
-        theseOutputsStart: 1
-      });
-      const tmp = CommonConstants.TRANSACTION_MAX_TRIES;
-      CommonConstants.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);
-      (yield s1.get('/tx/sources/DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV')).should.have.property('sources').length(1);
-      yield s1.commit({ time: now + 7210 }); // TX1 commited
-      (yield s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(1); // The 160 remaining units
-      (yield s1.get('/tx/sources/DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV')).should.have.property('sources').length(2); // The UD + 1040 units sent by toc
-      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
-      CommonConstants.TRANSACTION_MAX_TRIES = tmp;
-    }));
-  });
-});
diff --git a/test/integration/transactions-chaining.ts b/test/integration/transactions-chaining.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cbcbddf8fad80dcdbefe0440839365cde84efa9d
--- /dev/null
+++ b/test/integration/transactions-chaining.ts
@@ -0,0 +1,109 @@
+import {CommonConstants} from "../../app/lib/common-libs/constants"
+import {TestUser} from "./tools/TestUser"
+import {TestingServer} from "./tools/toolbox"
+import {NewLogger} from "../../app/lib/logger"
+
+const should = require('should');
+const assert = require('assert');
+const toolbox   = require('./tools/toolbox');
+const unit   = require('./tools/unit');
+
+describe("Transaction chaining", () => {
+
+  const now = 1456644632;
+
+  let s1:TestingServer, tic:TestUser, toc:TestUser
+
+  before(async () => {
+
+    s1 = toolbox.server({
+      pair: {
+        pub: 'DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV',
+        sec: '468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7'
+      },
+      dt: 3600,
+      udTime0: now + 3600,
+      ud0: 1200,
+      c: 0.1
+    });
+
+    tic = new TestUser('tic', { pub: 'DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV', sec: '468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iAfZACm7'}, { server: s1 });
+    toc = new TestUser('toc', { pub: 'DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo', sec: '64EYRvdPpTfLGGmaX5nijLXRqWXaVz8r1Z1GtaahXwVSJGQRn7tqkxLb288zwSYzELMEG5ZhXSBYSxsTsz1m9y8F'}, { server: s1 });
+
+    await s1.initDalBmaConnections();
+    await tic.createIdentity();
+    await toc.createIdentity();
+    await tic.cert(toc);
+    await toc.cert(tic);
+    await tic.join();
+    await toc.join();
+    await s1.commit({ time: now });
+    await s1.commit({ time: now + 7210 });
+    await s1.commit({ time: now + 7210 });
+  })
+
+  after(() => {
+    return s1.closeCluster()
+  })
+
+  describe("Sources", () => {
+
+    it('it should exist block#2 with UD of 1200', () => s1.expect('/blockchain/block/2', (block: { number:number, dividend:number }) => {
+      should.exists(block);
+      assert.equal(block.number, 2);
+      assert.equal(block.dividend, 1200);
+    }))
+  })
+
+  describe("Chaining", () => {
+
+    it('with SIG and XHX', async () => {
+      // Current state
+      let current = await s1.get('/blockchain/current');
+      (await s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(1);
+      let tx1 = await toc.prepareITX(1040, tic); // Rest = 1200 - 1040 = 160
+      let tx2 = await toc.prepareUTX(tx1, ['SIG(0)'], [{ qty: 160, base: 0, lock: 'SIG(' + tic.pub + ')' }], {
+        comment: 'also take the remaining 160 units',
+        blockstamp: [current.number, current.hash].join('-'),
+        theseOutputsStart: 1
+      });
+      const tmp = CommonConstants.TRANSACTION_MAX_TRIES;
+      CommonConstants.TRANSACTION_MAX_TRIES = 2;
+      await unit.shouldNotFail(toc.sendTX(tx1));
+      await unit.shouldNotFail(toc.sendTX(tx2));
+      (await s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(1);
+      (await s1.get('/tx/sources/DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV')).should.have.property('sources').length(1);
+      await s1.commit({ time: now + 7210 }); // TX1 + TX2 commited
+      (await s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(0);
+      (await s1.get('/tx/sources/DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV')).should.have.property('sources').length(3); // The UD + 1040 + 160 units sent by toc
+      CommonConstants.TRANSACTION_MAX_TRIES = tmp;
+    })
+
+    it('should refuse a block with more than 5 chained tx in it', async () => {
+      // Current state
+      let current = await s1.get('/blockchain/current');
+      const blockstamp = [current.number, current.hash].join('-');
+      (await s1.get('/tx/sources/DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo')).should.have.property('sources').length(0);
+      (await s1.get('/tx/sources/DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV')).should.have.property('sources').length(3);
+      // Ping-pong of 1200 units
+      let tx1 = await tic.prepareITX(1200, toc, "PING-PONG TX1");
+      let tx2 = await toc.prepareUTX(tx1, ['SIG(0)'], [{ qty: 1200, base: 0, lock: 'SIG(' + tic.pub + ')' }], { blockstamp, comment: "PING-PONG TX2" });
+      let tx3 = await tic.prepareUTX(tx2, ['SIG(0)'], [{ qty: 1200, base: 0, lock: 'SIG(' + toc.pub + ')' }], { blockstamp, comment: "PING-PONG TX3" });
+      let tx4 = await toc.prepareUTX(tx3, ['SIG(0)'], [{ qty: 1200, base: 0, lock: 'SIG(' + tic.pub + ')' }], { blockstamp, comment: "PING-PONG TX4" });
+      let tx5 = await tic.prepareUTX(tx4, ['SIG(0)'], [{ qty: 1200, base: 0, lock: 'SIG(' + toc.pub + ')' }], { blockstamp, comment: "PING-PONG TX5" });
+      let tx6 = await toc.prepareUTX(tx5, ['SIG(0)'], [{ qty: 1200, base: 0, lock: 'SIG(' + tic.pub + ')' }], { blockstamp, comment: "PING-PONG TX6" });
+      let tx7 = await tic.prepareUTX(tx6, ['SIG(0)'], [{ qty: 1200, base: 0, lock: 'SIG(' + toc.pub + ')' }], { blockstamp, comment: "PING-PONG TX7" });
+      const tmp = CommonConstants.TRANSACTION_MAX_TRIES;
+      CommonConstants.TRANSACTION_MAX_TRIES = 2;
+      await unit.shouldNotFail(toc.sendTX(tx1));
+      await unit.shouldNotFail(toc.sendTX(tx2));
+      await unit.shouldNotFail(toc.sendTX(tx3));
+      await unit.shouldNotFail(toc.sendTX(tx4));
+      await unit.shouldNotFail(toc.sendTX(tx5));
+      await unit.shouldNotFail(toc.sendTX(tx6));
+      await unit.shouldNotFail(toc.sendTX(tx7));
+      await s1.commitWaitError({ dontCareAboutChaining: true }, 'The maximum transaction chaining length per block is 5')
+      CommonConstants.TRANSACTION_MAX_TRIES = tmp;
+    })
+  });
+});