Doppelte TX-IDs

Gibt es eine schnelle und schmutzige Möglichkeit, alle Transaktionen zu erkennen tx-id, die seit dem Genesis-Block in mehr als einer Transaktion zu finden sind?

Ich würde auch gerne mutierte Transaktionen sehen, obwohl ich nicht sicher bin, ob die Blockchain die mutierten Transaktionen historisch verfolgt.

Fragen Sie nach doppelten Transaktionen, also 2 Transaktionen mit derselben ID? Wenn ja, gibt es keine.
@ike wie bist du zu diesem Schluss gekommen? Tx-IDs sollen nicht eindeutig sein bitcointalk.org/index.php?topic=28387.0
Es sind sha-256-Hashes, und es würde mehr Rechenleistung erfordern, als es auf der Welt gibt, um einen absichtlich zu erstellen. Sie möchten nach einem unwahrscheinlichen Szenario suchen, um sicherzustellen, dass es nicht passiert ist? Ich bin sicher, es gibt Leute, die gesucht und nichts gefunden haben; wenn es einen gäbe, würden wir davon hören.
Genauso wie ich Ihren privaten Schlüssel nicht einfach auf meinem Computer generiert habe.
@ike Ich verstehe, dass die Wahrscheinlichkeit, dass dies geschieht, nahe bei Null liegt, aber nicht bei Null, und dass die 55 Millionen TXs, die seitdem genesisinsgesamt stattgefunden haben, nicht einmal annähernd dem entsprechen, was normalerweise erforderlich wäre, um den sha256-Algo brutal zu erzwingen, alles ich Ich frage mich, ob es eine praktische Möglichkeit gibt, das Bitcoin-Netzwerk nach solchen Szenarien abzufragen.
Ok, der Weg wäre, eine Kopie der Blockchain zu haben, alle txids aufzulisten und nach Dups zu scannen. Ich werde die Befehle nachschlagen und das als Antwort geben.
Es sieht kompliziert aus, ich müsste ein paar Skripte schreiben. Dies kann Ihnen jedoch helfen, wenn Sie ein wenig Bash kennen. bitcoin.stackexchange.com/questions/4601/…

Antworten (3)

Gibt es eine schnelle und schmutzige Möglichkeit, alle Transaktionen zu erkennen, deren TX-ID seit dem Genesis-Block in mehr als einer Transaktion gefunden werden kann?

Es gibt mehrere Möglichkeiten, Ihre Frage zu lesen.

Gibt es Fälle, in denen dieselbe Transaktion mehrmals in die Blockchain aufgenommen wurde?

Ja . Es gibt eine aufgezeichnete Instanz derselben Coinbase, die zweimal erscheint. Das Problem dabei ist, dass nur einer davon eingelöst werden kann. Es ermöglicht auch, eine vollständig bestätigte Transaktion auf eine Bestätigung zu reduzieren, obwohl ich die Details nicht verstehe. BIP34 hat dies behoben.

Gibt es Fälle, in denen derselbe Eingabe-Hash in mehreren Transaktionen erscheint?

Ja. Es passiert ständig. Beispielsweise hat die Transaktion 9fa3... zwei Ausgaben. Diese beiden Ausgaben wurden von zwei verschiedenen Transaktionen ausgegeben. Jede Transaktion musste denselben Eingabe-Hash enthalten (obwohl das vout-Feld anders war).

Gibt es bekannte Kollisionen in SHA256?

Nein.

Ich würde auch gerne mutierte Transaktionen sehen, obwohl ich nicht sicher bin, ob die Blockchain die mutierten Transaktionen historisch verfolgt.

Das tut es nicht.

Danke Nick. "Es gibt mehrere Möglichkeiten, Ihre Frage zu lesen." Was ich brauche, ist eine schnelle Möglichkeit, die Blockchain abzufragen: SELECT TxId, COUNT(*) c FROM blockchain GROUP BY TxId HAVING c > 1;
@DougPeters Unterscheidet sich das von der ersten Interpretation Ihrer Frage?
Nicht wirklich, ich habe mich nur gefragt, ob Sie eine nette Möglichkeit kennen, dies zu erreichen, ohne sie auf blockchain.info oder einem anderen Drittanbieterdienst nachschlagen zu müssen.

Die Coinbase-Transaktionen e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468 und d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d8 existieren in zwei Blöcken9.

Dieses Problem wurde in BIP30 behoben , so dass dies nicht noch einmal passieren kann.

BIP30 schreibt auch vor, dass es die neueste Version dieser Transaktionen ist, die ausgegeben werden kann.

Ich habe ein NodeJS-Skript geschrieben, das die REST-API von Bitcoin Core verwendet, um bis zu Block 227835 zu scannen, was der letzte Block der Version 1 ist . Die Ausführung dauert etwa eine halbe Stunde und zeigt die vollständige Liste der doppelten Coinbase-Transaktionen wie folgt an:

454279874213763724535987336644243549a273058910332236515429488599 91812 91842
5356640744203756384561725255950751537320676481287559742658862468 91722 91880

Das Skript (manchmal, wenn eine Zeitüberschreitung für Anfragen auftritt, meldet es die Anfrage, für die der Block fehlgeschlagen ist, damit Sie den Fortschritt sehen können):

const { performance } = require("perf_hooks");
const fetch = require("node-fetch");

const LAST_V1_BLOCK = 227835;
var hashes = [];
var hashes_len = 0;
var block_heights = [];

async function getBlockHash(height) {
  return (await fetch("http://127.0.0.1:8332/rest/blockhashbyheight/" + height + ".json")
    .then((response) => {
      return response.json();
    }).catch((err) => {
      console.log("Retrying " + height);
      return getBlockHash(height);
    }))
}

async function getCoinbaseHash(hash) {
  return (await fetch("http://127.0.0.1:8332/rest/block/" + hash + ".json")
    .then((response) => {
      return response.json();
    }).catch((err) => {
      console.log("Retrying " + hash);
      return getCoinbaseHash(hash);
    }))
}

async function getCoinbaseHashByHeight(height) {
  return (await getCoinbaseHash((await getBlockHash(height)).blockhash)).tx[0].txid
}

const hex_alphabet = Uint32Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15]);
const hex_encode = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];

// I'm forcing big endian, even though order doesn't matter in this code
// It means you can use this code to find the block with the lowest hash
function eightTo32(a) {
  var out = new Uint32Array(8);
  for (var i = 0; i < 8; i++)
    out[i] = a[4 * i] << 24 | a[4 * i + 1] << 16 | a[4 * i + 2] << 8 | a[4 * i + 3];
  return out;
}

function thirty2To8(a) {
  var out = new Uint8Array(32);
  for (var i = 0; i < 8; i++) {
    out[4 * i] = (a[i] >> 24) & 255;
    out[4 * i + 1] = (a[i] >> 16) & 255;
    out[4 * i + 2] = (a[i] >> 8) & 255;
    out[4 * i + 3] = (a[i]) & 255;
  }
  return out;
}

function decodeHex(str) {
  var out = new Uint8Array(32);
  var scratch = new Uint32Array(64);
  for (var i = 0; i < 64; i++)
    scratch[i] = str.charCodeAt(i);
  for (var i = 0; i < 64; i++)
    scratch[i] -= 48;
  for (var i = 0; i < 32; i++)
    out[i] = scratch[i << 1];
  for (var i = 0; i < 32; i++)
    out[i] <<= 4;
  for (var i = 0; i < 64; i += 2)
    out[i >>> 1] += scratch[i + 1];
  return eightTo32(out);
}

function encodeHex(arr) {
  var x = thirty2To8(arr)
  var s = "";
  for (var i = 0; i < 32; i++)
    s += hex_encode[x[i] >>> 4] + hex_encode[x[i] & 15];
  return s;
}

function compareHashes(a, b) {
  for (var i = 0; i < 8; i++)
    if (a[i] < b[i])
      return -1;
    else if (a[i] > b[i])
      return 1;
  return 0;
}

// We need a binary tree
// Taken from https://stackoverflow.com/q/1344500
// Start = 0
// End = length
function locationOf(element, start, end) {
  const pivot = start + ((end - start) >>> 1);
  const arrPiv = hashes[pivot];
  const com = compareHashes(arrPiv, element)
  if (!com) return pivot;
  if (end - start <= 1) {
    if (com == 1)
      return pivot - 1;
    return pivot;
  }
  if (com == -1)
    return locationOf(element, pivot, end);
  return locationOf(element, start, pivot);
}

// Taken from https://stackoverflow.com/q/1344500
function insert(element, height) {
  var l = locationOf(element, 0, hashes_len);
  hashes.splice(l + 1, 0, element);
  block_heights.splice(l + 1, 0, height);
  hashes_len++;
  return 0;
}

async function run() {
  var t0 = performance.now();

  // Process the genesis block out of the loop
  hashes.push(decodeHex(await getCoinbaseHashByHeight(0)));
  block_heights.push(0);
  hashes_len++;

  var pre_hashes = [];
  // Batches of 5 for await
  for (var i = 0, r = (LAST_V1_BLOCK / 5 | 0) * 5; i < r; i += 5) {
    for (var x = 0; x < 5; x++)
      pre_hashes[i + x] = getCoinbaseHashByHeight(i + x + 1);
    for (var x = 0; x < 5; x++)
      pre_hashes[i + x] = await pre_hashes[i + x];
  }
  for (; i < LAST_V1_BLOCK; i++) pre_hashes[i] = await getCoinbaseHashByHeight(i + 1);

  console.log("Done acquiring");

  for (var i = 0; i < LAST_V1_BLOCK; i++)
    pre_hashes[i] = decodeHex(pre_hashes[i]);
  for (var i = 0; i < LAST_V1_BLOCK; i++)
    insert(pre_hashes[i], i + 1);

  console.log("Sorting done")

  for (var i = 1; i < hashes_len; i++)
    if (!compareHashes(hashes[i - 1], hashes[i]))
      console.log(encodeHex(hashes[i]) + " " + block_heights[i - 1] + " " + block_heights[i]);
  console.log("Duplicate check done")
  var t1 = performance.now();
  console.log("Took " + (t1 - t0) + " ms.");
}

run()