Как получить адреса кошелька от и до транзакции?

Учитывая входы и выходы транзакции, я хотел бы иметь возможность извлечь адрес кошелька (или адреса), который отправил транзакцию, а также адрес/адреса, которые получат транзакцию.

  • Какая часть/поле ввода относится к хешу вывода?

  • И какая часть/поле вывода относится к адресу, на который будет получен вывод?

Я использую биткойн. Я пробовал смотреть на scriptSigвходы и scriptPubKeyвыходы, но для меня это не имеет особого смысла.

Например, для исходной транзакции: https://blockchain.info/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b?show_adv=true .

Выходной scriptPubKey равен[04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f] CHECKSIG

Но адрес получателя1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

Как я могу извлечь адрес получателя из этого scriptPubKey?

Ответы (2)

  • Какая часть/поле ввода относится к хешу вывода?

Outpoint содержит txid (32 байта) и vout (4 байта), которые определяют расходуемый вами вывод.

Это не адрес отправки!

Что вы делаете (когда вы не имеете дело с транзакцией coinbase), так это то, что вы просматриваете транзакцию с txid и смотрите на вывод транзакции, соответствующий vout. Так, например, если бы vout было равно 3, вы бы посмотрели на четвертый вывод соответствующей транзакции. Если бы vout был равен 0, вы бы посмотрели на первый вывод. Адрес, который может потратить этот вывод, является адресом отправки исходной транзакции.

Генезисная транзакция — это транзакция coinbase, поэтому txid — это все нули, а vout — это все единицы.

  • И какая часть/поле вывода относится к адресу, на который будет получен вывод?

Это зависит от формата вывода, но вот общие правила:

  • Если это P2PK, как здесь, запустите HASH160 для первого элемента scriptPubKey, а затем закодируйте его как адрес.
  • Если это P2PKH, возьмите третий элемент scriptPubKey и закодируйте pubkeyhash как адрес.
  • Если это P2SH, возьмите второй элемент scriptPubKey и закодируйте его как адрес с помощью Address.fromP2SHHash.

Я более подробно расскажу о возможных типах адресов здесь: Какие формы биткойн-скриптов следует обнаруживать при отслеживании баланса кошелька?

Как я могу извлечь адрес получателя из этого scriptPubKey?

Сделай это:

import org.bitcoinj.core.*;
import org.bitcoinj.params.MainNetParams;

import org.spongycastle.crypto.digests.RIPEMD160Digest;

import java.nio.file.Files;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test {
    public static void main(String[] args) throws Exception {
        byte[] b;
        NetworkParameters np = MainNetParams.get();
        Context.propagate(new Context(np));
        b = Files.readAllBytes(new File("genesis.bin").toPath());
        Transaction tx1 = new Transaction(np, b);
        System.out.println(tx1);
        byte[] pk = tx1.getOutput(0).getScriptPubKey().getPubKey();
        System.out.println(bytesToHex(pk));
        System.out.println(bytesToHex(hash160(pk)));
        Address a = new Address(np, hash160(pk));
        System.out.println(a);
    }
    static byte[] hash160(byte[] in) {
        MessageDigest d1;
        try {
            d1 = MessageDigest.getInstance("SHA-256");
        } catch(NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        d1.update(in);
        byte[] digest = d1.digest();
        RIPEMD160Digest d2 = new RIPEMD160Digest();
        d2.update(digest, 0, 32);
        byte[] ret = new byte[20];
        d2.doFinal(ret, 0);
        return ret;
    }
    final protected static char[] hexArray = "0123456789abcdef".toCharArray();
    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

(Обратите внимание, что в моем текущем рабочем каталоге есть файл с именем genesis.bin, который содержит необработанные байты для транзакции генезиса.)

И вы получаете:

  4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
     == COINBASE TXN (scriptSig PUSHDATA(4)[ffff001d] PUSHDATA(1)[04] PUSHDATA(69)[5468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73])  (scriptPubKey PUSHDATA(65)[04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f] CHECKSIG)

04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
62e907b15cbf27d5425399ebf6f0fb50ebb88f18
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

Это адрес, который мы пытались получить.

Спасибо, очень полезно. Как узнать, является ли вывод P2PK, P2PKH или P2SH? И охватывают ли эти 3 формата все возможные форматы, в которых он может быть? Кроме того, как я узнаю, что это плата за майнинг без адреса? Наконец, чтобы получить txid входных данных с помощью Bitcoinj, должен ли я использовать метод input.getParentTransaction?
Я видел ваш ответ на bitcoin.stackexchange.com/questions/35456/… , который отвечает на мой первый вопрос. Оставшиеся вопросы: 1) Я предполагаю, что адрес отправителя multi-sig txns не может быть получен? 2) Вы случайно не знаете хэши txns, использующие P2PKH и P2SH, чтобы я мог проверить их разбор? 3) Как я могу получить txId и vout входов через Bitcoinj? Если я заработаю, я отправлю это как PR в bitcoinj. Спасибо.
Было бы лучше, если бы я создал новый вопрос для каждого из них?
@ClickUpvote 1) Это возможно. Вы можете иметь в виду «какие адреса владели этим биткойном раньше» или «какие адреса фактически подписали это». На первый можно ответить, посмотрев на предыдущий scriptPubKey, для второго требуется предыдущий scriptPubKey и текущий scriptSig. 2) P2PKH/P2SH 3) tx.getInput(vin).getOutpoint() с последующим getHash или getIndex. пиар) Круто! Было бы неплохо увидеть это в биткойнах. PS) Я бы сделал отдельные вопросы. Комментарий ограничен 600 символами
Относится ли input.getOutput.getHashк идентификатору txn и getIndexк vout вывода этого txn? PS большое спасибо, я несколько дней пытался получить ответы на эти вопросы, вы первый, кто смог на них ответить. :)
Можно ли загрузить двоичные данные этих txns с blockchain.info или другим способом, не просматривая цепочку в поисках?
@ClickUpvote Вы должны иметь возможность запросить веб-страницу https://blockchain.info/tx/<txid here>?format=hex, чтобы получить версию в шестнадцатеричном кодировании. Другие API имеют нечто подобное.
Так, например, blockchain.info/tx/… , который можно сохранить как файл .bin и передать в транзакцию, как в вашем примере кода? Или что-то еще нужно сделать с шестнадцатеричными данными?
@ClickUpvote Его нужно преобразовать из шестнадцатеричного в необработанные байты. stackoverflow.com/questions/8890174/…

scriptPubKey содержит открытый ключ, используемый для синтеза публичного адреса. Вот два педантичных подхода, не использующих биткойн, применяющих команды bx для синтеза интересующего публичного адреса выше.

% echo 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f | bx sha256 | bx ripemd160 | bx base58check-encode

1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

% echo 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f | bx ec-to-address

1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa