Remuniter, mes nœuds et d’autres refusent le bloc 191946-000002F1
et sont en fork :
https://moul.re/zerobin/?cf2a12f6d04da0d9#JOXdFJ0ZyDv5tE1H36CQ4J+CKBdvNrZLQu4ZKf2hFRE=
En particulier :
2019-01-30T10:51:28+01:00 - info: Fork resolution: suite 1/1 REFUSED block#191946: Cannot read property 'match' of undefined
2019-01-30T10:51:28+01:00 - info: Fork resolution: suite 1/1 reached HEAD + 19. Now rolling back.
2019-01-30T10:51:42+01:00 - error: TypeError: Cannot read property 'match' of undefined
at txSourceUnlock (/opt/duniter/app/lib/indexer.js:1835:27)
at Promise.all.underscore_1.Underscore.where.map (/opt/duniter/app/lib/indexer.js:759:31)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:160:7)
Bloc invalidé par certains nœuds du réseau :
curl g1.duniter.org/blockchain/block/191946
{
"version": 11,
"nonce": 120100000140395,
"number": 191946,
"powMin": 87,
"time": 1548819621,
"medianTime": 1548811053,
"membersCount": 1592,
"monetaryMass": 529305715,
"unitbase": 0,
"issuersCount": 29,
"issuersFrame": 146,
"issuersFrameVar": 0,
"currency": "g1",
"issuer": "HqSgtznEg3MEyhq81aX95XuFwRMGmuZ3Rzs7UxgvBH1f",
"signature": "TiMas5TyvFiKnJpwEvbyGYkWZDg8mYP3qate01YxO/AaYOdHvKc1Fp4iCuaZkFdzJBDSIVRA+vcpRo2EFFElAw==",
"hash": "000002F1B31E67D021F440360DC1B370AB31C1BF4B49DAE56BDB0981AC137C23",
"parameters": "",
"previousHash": "000000A9F4D910FE4977DFC628ED1B24929CA2C2ACE169921F7FEFEE5BBFAA2E",
"previousIssuer": "D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH",
"inner_hash": "FCA00AD3E2EDD63E5A4218630A6673D7A4A008C8E525D896204E6345878F7A21",
"dividend": null,
"identities": [],
"joiners": [],
"actives": [],
"leavers": [],
"revoked": [],
"excluded": [],
"certifications": [],
"transactions": [
{
"version": 10,
"currency": "g1",
"locktime": 0,
"hash": "32EEB19446A77052C42C7E7B4F0DA4E7AA9405FCD7AC7D56426031A000C0A0B2",
"blockstamp": "191943-000004DDB40CC456F319BDEE9CE603561DF9AC6B9ACD21E0AFC682F326435BE7",
"blockstampTime": 0,
"issuers": [
"DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg"
],
"inputs": [
"1000:0:T:94FD41FA2A256A20F2689B2AF2BB8BB370C7896F0F4E7E6A0F9A622DD6969A35:1",
"6000:0:T:0D3A680DBAC4CA50036EBD336CC16197B9952E25BDE1E53160A60ACA48A2FEF5:0"
],
"outputs": [
"1255:0:SIG(6vjF4vk9UiGWk7b12yPx2NXWQ4QaVDDesZXdpactihMR)",
"5745:0:SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)"
],
"unlocks": [
"0:SIG(0)",
"1:SIG(0)"
],
"signatures": [
"fl07WGoRpmKlKBmVEI9ah/77I/Vd2nVplwnBHbPeVNV78R+EbjNoeCV8jggmLAm2+gGlEMsrzTPFEIyL5QxVBQ=="
],
"comment": "GU2POM"
}
],
"raw": "Version: 11\nType: Block\nCurrency: g1\nNumber: 191946\nPoWMin: 87\nTime: 1548819621\nMedianTime: 1548811053\nUnitBase: 0\nIssuer: HqSgtznEg3MEyhq81aX95XuFwRMGmuZ3Rzs7UxgvBH1f\nIssuersFrame: 146\nIssuersFrameVar: 0\nDifferentIssuersCount: 29\nPreviousHash: 000000A9F4D910FE4977DFC628ED1B24929CA2C2ACE169921F7FEFEE5BBFAA2E\nPreviousIssuer: D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH\nMembersCount: 1592\nIdentities:\nJoiners:\nActives:\nLeavers:\nRevoked:\nExcluded:\nCertifications:\nTransactions:\nTX:10:1:2:2:2:1:0\n191943-000004DDB40CC456F319BDEE9CE603561DF9AC6B9ACD21E0AFC682F326435BE7\nDQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg\n1000:0:T:94FD41FA2A256A20F2689B2AF2BB8BB370C7896F0F4E7E6A0F9A622DD6969A35:1\n6000:0:T:0D3A680DBAC4CA50036EBD336CC16197B9952E25BDE1E53160A60ACA48A2FEF5:0\n0:SIG(0)\n1:SIG(0)\n1255:0:SIG(6vjF4vk9UiGWk7b12yPx2NXWQ4QaVDDesZXdpactihMR)\n5745:0:SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)\nGU2POM\nfl07WGoRpmKlKBmVEI9ah/77I/Vd2nVplwnBHbPeVNV78R+EbjNoeCV8jggmLAm2+gGlEMsrzTPFEIyL5QxVBQ==\nInnerHash: FCA00AD3E2EDD63E5A4218630A6673D7A4A008C8E525D896204E6345878F7A21\nNonce: 120100000140395\n"
}⏎
Car il ne respecte pas la règle BR_G47 :
####### BR_G47 - ENTRY.isLocked
INPUT_ENTRIES = LOCAL_SINDEX[op='CREATE',identifier=ENTRY.identifier,pos=ENTRY.pos,amount=ENTRY.amount,base=ENTRY.base]
If COUNT(INPUT_ENTRIES) == 0 Then
INPUT_ENTRIES = GLOBAL_SINDEX[identifier=ENTRY.identifier,pos=ENTRY.pos,amount=ENTRY.amount,base=ENTRY.base]
EndIf
INPUT = REDUCE(INPUT_ENTRIES)
ENTRY.isLocked = TX_SOURCE_UNLOCK(INPUT.conditions, ENTRY)
Le code incriminé :
// BR_G47
await Promise.all(underscore_1.Underscore.where(sindex, { op: constants.IDX_UPDATE }).map(async (ENTRY) => {
const source = await getInputLocalFirstOrFallbackGlobally(sindex, ENTRY);
ENTRY.conditions = source.conditions;
ENTRY.isLocked = !txSourceUnlock(ENTRY, source, HEAD);
}));
Les sources utilisées par cette transaction ne sont pas disponibles avant ou n’existaient pas (nœud bloqué avant ce bloc) :
curl duniter.moul.re/tx/sources/DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg
{
"currency": "g1",
"pubkey": "DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg",
"sources": [
{
"type": "T",
"noffset": 1,
"identifier": "2D9679448680654A4694B52F855F44E57A2E99D86A2FA3BD48028E99B98D1F42",
"amount": 5400,
"base": 0,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)"
},
{
"type": "T",
"noffset": 1,
"identifier": "8D28C0AEB4B651B584312737AE25D79FAD1455FA149CDFD23C4B1B9A176E7E03",
"amount": 2000,
"base": 0,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)"
}
]
}
Ni après (nœud qui a accepté ce bloc) :
curl g1.duniter.org/tx/sources/DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg
{
"currency": "g1",
"pubkey": "DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg",
"sources": [
{
"type": "T",
"noffset": 0,
"identifier": "90FF03A666B9EF6C6E9A5981193FBD2E614C306098E6728DCD8D330420616D23",
"amount": 1000,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)",
"base": 0
},
{
"type": "T",
"noffset": 1,
"identifier": "2D9679448680654A4694B52F855F44E57A2E99D86A2FA3BD48028E99B98D1F42",
"amount": 5400,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)",
"base": 0
},
{
"type": "T",
"noffset": 1,
"identifier": "8D28C0AEB4B651B584312737AE25D79FAD1455FA149CDFD23C4B1B9A176E7E03",
"amount": 2000,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)",
"base": 0
},
{
"type": "T",
"noffset": 1,
"identifier": "32EEB19446A77052C42C7E7B4F0DA4E7AA9405FCD7AC7D56426031A000C0A0B2",
"amount": 5745,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)",
"base": 0
},
{
"type": "T",
"noffset": 1,
"identifier": "92467116650E0FA4DBCB5E66B779D4BB42E89373087459F428693A107096B2F1",
"amount": 19150,
"conditions": "SIG(DQh2YyvsGbfehrDmYta3XZXwqNpQXx7yeRMK7Ak59JMg)",
"base": 0
}
]
}
Bon, je suis allé mettre un point d’arrêt en ligne de commande grâce à cette doc.
Ajouter debugger;
autour de /opt/duniter/app/lib/indexer.js:759
, lancer :
cd /opt/duniter/
./node/bin/node inspect bin/duniter direct_start
continue # still you reach your `debugg;` breakpoint
repl # To display variables content
Ce que je semble conclure, c’est qu’il manque la source pour que la transaction puisse avoir lieu :
> source
{ }
> ENTRY
{ index: 'SINDEX',
op: 'UPDATE',
srcType: 'T',
tx: '32EEB19446A77052C42C7E7B4F0DA4E7AA9405FCD7AC7D56426031A000C0A0B2',
identifier: '94FD41FA2A256A20F2689B2AF2BB8BB370C7896F0F4E7E6A0F9A622DD6969A35',
... }
C’est bien ça, la source est vide, j’ai comparé sur ğ1-test où la source existait dans un nouveau bloc ajouté.
Du coup, le client a dû faire une erreur en envoyant cette transaction avec ces fausses sources.
Mais, l’important est que l’implémentation des nœuds ne devraient pas accepter dans leurs bacs à sable des transactions avec des sources inexistantes et encore moins permettre que ça entre dans la chaîne.