@leofcoin/chain 1.7.132 → 1.7.134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5080,6 +5080,11 @@ class State extends Contract {
5080
5080
  }
5081
5081
  debug$1(`Local block height: ${localIndex}, remote block height: ${remoteIndex}`);
5082
5082
  debug$1(`Local state hash: ${localStateHash}, remote block hash: ${remoteBlockHash}`);
5083
+ // Skip syncing if remote block hash is 0x0 (invalid state)
5084
+ if (remoteBlockHash === '0x0') {
5085
+ debug$1(`Remote block hash is 0x0, skipping sync`);
5086
+ return;
5087
+ }
5083
5088
  // Use state hash comparison: only resolve if remote hash differs from local state hash
5084
5089
  if (localStateHash !== remoteBlockHash) {
5085
5090
  // Remote block hash differs from our local state, need to resolve
@@ -5251,7 +5256,7 @@ class State extends Contract {
5251
5256
  promiseRequests(promises) {
5252
5257
  return new Promise(async (resolve, reject) => {
5253
5258
  const timeout = setTimeout(() => {
5254
- resolve([{ index: 0, hash: '0x0' }]);
5259
+ resolve([]);
5255
5260
  debug$1('sync timed out');
5256
5261
  }, this.requestTimeout);
5257
5262
  promises = await Promise.allSettled(promises);
@@ -5316,7 +5321,7 @@ class State extends Contract {
5316
5321
  return this.syncChain(latest);
5317
5322
  }
5318
5323
  async triggerLoad() {
5319
- if (this.#blocks.length > 0) {
5324
+ if (this.#blocks?.length > 0) {
5320
5325
  this.#machine = await new Machine(this.#blocks);
5321
5326
  }
5322
5327
  }
@@ -5945,8 +5950,30 @@ class Chain extends VersionControl {
5945
5950
  }
5946
5951
  }
5947
5952
  async #addBlock(block) {
5953
+ // Store the original received encoded bytes for validation
5954
+ const receivedEncoded = block instanceof BlockMessage ? block.encoded : block;
5948
5955
  const blockMessage = await new BlockMessage(block);
5949
5956
  const hash = await blockMessage.hash();
5957
+ // Verify data integrity: re-encode should produce the same bytes
5958
+ const canonicalEncoded = blockMessage.encoded;
5959
+ if (receivedEncoded.length === canonicalEncoded.length) {
5960
+ let mismatch = false;
5961
+ for (let i = 0; i < receivedEncoded.length; i++) {
5962
+ if (receivedEncoded[i] !== canonicalEncoded[i]) {
5963
+ mismatch = true;
5964
+ break;
5965
+ }
5966
+ }
5967
+ if (mismatch) {
5968
+ console.warn(`[chain] ⚠️ Block data corrupted in transit: encoded bytes don't match canonical form for block #${blockMessage.decoded.index}`);
5969
+ }
5970
+ else {
5971
+ console.log(`[chain] ✅ Block data integrity verified via codec: ${hash}`);
5972
+ }
5973
+ }
5974
+ else {
5975
+ console.warn(`[chain] ⚠️ Block data size mismatch: received ${receivedEncoded.length} bytes but canonical is ${canonicalEncoded.length} bytes for block #${blockMessage.decoded.index}`);
5976
+ }
5950
5977
  const transactions = await Promise.all(blockMessage.decoded.transactions
5951
5978
  // @ts-ignore
5952
5979
  .map(async (hash) => {
@@ -6163,6 +6190,8 @@ class Chain extends VersionControl {
6163
6190
  await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() });
6164
6191
  await this.updateState(blockMessage);
6165
6192
  debug(`created block: ${hash} @${block.index}`);
6193
+ // Publish canonical encoded form via codec interface
6194
+ console.log(`[chain] 📤 Publishing block #${block.index} | hash: ${hash} | encoded bytes: ${blockMessage.encoded.length}`);
6166
6195
  globalThis.peernet.publish('add-block', blockMessage.encoded);
6167
6196
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
6168
6197
  }
package/exports/chain.js CHANGED
@@ -1207,6 +1207,11 @@ class State extends Contract {
1207
1207
  }
1208
1208
  debug$1(`Local block height: ${localIndex}, remote block height: ${remoteIndex}`);
1209
1209
  debug$1(`Local state hash: ${localStateHash}, remote block hash: ${remoteBlockHash}`);
1210
+ // Skip syncing if remote block hash is 0x0 (invalid state)
1211
+ if (remoteBlockHash === '0x0') {
1212
+ debug$1(`Remote block hash is 0x0, skipping sync`);
1213
+ return;
1214
+ }
1210
1215
  // Use state hash comparison: only resolve if remote hash differs from local state hash
1211
1216
  if (localStateHash !== remoteBlockHash) {
1212
1217
  // Remote block hash differs from our local state, need to resolve
@@ -1378,7 +1383,7 @@ class State extends Contract {
1378
1383
  promiseRequests(promises) {
1379
1384
  return new Promise(async (resolve, reject) => {
1380
1385
  const timeout = setTimeout(() => {
1381
- resolve([{ index: 0, hash: '0x0' }]);
1386
+ resolve([]);
1382
1387
  debug$1('sync timed out');
1383
1388
  }, this.requestTimeout);
1384
1389
  promises = await Promise.allSettled(promises);
@@ -1443,7 +1448,7 @@ class State extends Contract {
1443
1448
  return this.syncChain(latest);
1444
1449
  }
1445
1450
  async triggerLoad() {
1446
- if (this.#blocks.length > 0) {
1451
+ if (this.#blocks?.length > 0) {
1447
1452
  this.#machine = await new Machine(this.#blocks);
1448
1453
  }
1449
1454
  }
@@ -2072,8 +2077,30 @@ class Chain extends VersionControl {
2072
2077
  }
2073
2078
  }
2074
2079
  async #addBlock(block) {
2080
+ // Store the original received encoded bytes for validation
2081
+ const receivedEncoded = block instanceof BlockMessage ? block.encoded : block;
2075
2082
  const blockMessage = await new BlockMessage(block);
2076
2083
  const hash = await blockMessage.hash();
2084
+ // Verify data integrity: re-encode should produce the same bytes
2085
+ const canonicalEncoded = blockMessage.encoded;
2086
+ if (receivedEncoded.length === canonicalEncoded.length) {
2087
+ let mismatch = false;
2088
+ for (let i = 0; i < receivedEncoded.length; i++) {
2089
+ if (receivedEncoded[i] !== canonicalEncoded[i]) {
2090
+ mismatch = true;
2091
+ break;
2092
+ }
2093
+ }
2094
+ if (mismatch) {
2095
+ console.warn(`[chain] ⚠️ Block data corrupted in transit: encoded bytes don't match canonical form for block #${blockMessage.decoded.index}`);
2096
+ }
2097
+ else {
2098
+ console.log(`[chain] ✅ Block data integrity verified via codec: ${hash}`);
2099
+ }
2100
+ }
2101
+ else {
2102
+ console.warn(`[chain] ⚠️ Block data size mismatch: received ${receivedEncoded.length} bytes but canonical is ${canonicalEncoded.length} bytes for block #${blockMessage.decoded.index}`);
2103
+ }
2077
2104
  const transactions = await Promise.all(blockMessage.decoded.transactions
2078
2105
  // @ts-ignore
2079
2106
  .map(async (hash) => {
@@ -2290,6 +2317,8 @@ class Chain extends VersionControl {
2290
2317
  await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() });
2291
2318
  await this.updateState(blockMessage);
2292
2319
  debug(`created block: ${hash} @${block.index}`);
2320
+ // Publish canonical encoded form via codec interface
2321
+ console.log(`[chain] 📤 Publishing block #${block.index} | hash: ${hash} | encoded bytes: ${blockMessage.encoded.length}`);
2293
2322
  globalThis.peernet.publish('add-block', blockMessage.encoded);
2294
2323
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
2295
2324
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/chain",
3
- "version": "1.7.132",
3
+ "version": "1.7.134",
4
4
  "description": "Official javascript implementation",
5
5
  "private": false,
6
6
  "exports": {