Author

Topic: ㅤ (Read 196 times)

hero member
Activity: 520
Merit: 11957
August 18, 2020, 11:41:30 AM
#2
Часть 3

Если вы выполнили первую и вторую части, у вас будет полностью настроенная regtest среда. Теперь у вас есть все, что угодно, чтобы экспериментировать с любой безумной идеей, которая вам придет в голову.


Вперед за програмным материалом

Я собираюсь упростить задачу, создав простой скрипт python3, который создает необработанную транзакцию, подписывает транзакцию и, наконец, отправляет все это из программы Python:

Code:
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
import sys

rpc_connection = AuthServiceProxy("http://%s:%[email protected]:18444"%("bitcoin", "talk"),timeout = 120)

def addreses_to_spent_from():
  lstSpendableAddresses = []
  allAddresses = rpc_connection.listaddressgroupings()
  
  for i in range(0, len(allAddresses)):
    availableBTC = float(allAddresses[i][0][1])
    if availableBTC > 1:
      print('Suitable address found: %s' % allAddresses[i][0][0])
      lstSpendableAddresses.append(allAddresses[i][0][0])

  return lstSpendableAddresses

def make_transaction(txid, idx, address, amount):
  raw = rpc_connection.createrawtransaction(
            [{"txid": txid,
              "vout": idx}],
            {address:amount} )

  signed = rpc_connection.signrawtransactionwithwallet(raw)
  send_result = rpc_connection.sendrawtransaction(signed['hex'])
  
  return send_result

#=============
txid = None
for address in addreses_to_spent_from():
  unspents = rpc_connection.listunspent(1, 99999999, [address])
  num_unspents = len(unspents)
  for spendable_input in unspents:
    txid = spendable_input['txid']
    idx  = spendable_input['vout']
    amount =  float(spendable_input['amount'])
    if amount > 1:
      break;

if txid == None:
  sys.exit('No suitable input could be found for a transaction!')

trans_amount = float(amount) - (0.00000100)
trans_amount = "{:.8f}".format(trans_amount)

non_wallet_address = 'mpXwg4jMtRhuSpVq4xS3HFHmCmWp9NyGKt'
success_txid = make_transaction(txid, idx, non_wallet_address, trans_amount)
print('Transaction-id: %s' % success_txid)


Программа ищет подходящий адрес кошелька, в котором есть как минимум 1 неизрасходованный BTC. Первый найденный используется для получения входных данных для нашей транзакции. Весь ввод тратится за вычетом комиссий (в данном примере установлено фиксированное значение 0.00000100)). Функция "make_transaction" заботится о подписании и отправке транзакции и возвращает txid в случае успеха). Повторюсь еще раз: речь идет о примере того, как можно самостоятельно использовать regtest среду для программного эксперимента/тестирования. Я уверен, что вы можете придумать много вещей, которые содержат ошибки в моем примере кода, это нормально Smiley. Все дело в концепции regtest, а не в моих слабых навыках программирования!

При запуске кода вы должны получить что-то вроде этого:

Code:
Suitable address found: bcrt1qkcvk53y8qfckuwemp7w9hahszk6j5eeqjae9t4
Transaction-id: c784407fed108736c9a71d9ab2eb22ce1bf46c1ec9006d75e8a28671af86d1ae

И вот ты только что перевел 50 BTC (минус комиссия) на адрес, который не твой и не в твоем кошельке. И если ты пожалеешь о своем поступке, просто начни все заново.

До тех пор, пока ты не наберешь еще один блок, транзакция, которую ты только что совершил, останется в мемпуле. Так что не забудьте смайнить хотя бы 1 дополнительный блок, чтобы получить подтверждение и в своей цепочке.


Конец третьей части

На этом мы завершаем третью часть, в которой мы рассматривали вопрос о программном выполнении транзакции. Сама программа не была сложной, но теперь, когда вы знаете что делать, флаг вам в руки! Может быть, вы хотите создать свой собственный простой бумажник для экспериментов? Вперед! Всегда хотел попробовать, как установить более высокую комиссию за транзакцию с использованием RBF? Теперь ты можешь это выяснить! Ну что ж, если вы уловили ход мысли, что regtest может быть лучшей средой для начала погони за ней!


Часть 4

Некоторая дополнительная помощь.

Погружение во внутренности regtest блокчейна

Одна большая разница между regtest и тестовой\главной сетью в том, что у вас нет причудливого блок эксплорера. Но это не значит, что иногда нужно проверять или подтверждать что-то в regtest блокчейне. Поэтому для этого я использую еще одну программу python3, чтобы получить базовую информацию regtest блокчейне и транзакциях.


Вот программа python3, которую я использовал для создания транзакции (удобно называемая "info.py"):

Code:
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
import sys, simplejson
rpc_connection = AuthServiceProxy("http://%s:%[email protected]:18444"%("bitcoin", "talk"),timeout = 120)

def get_blockchain_size():
  iBlockSize = rpc_connection.getblockcount()
  return iBlockSize

def get_block_hash(height):
    blockhash = rpc_connection.getblockhash(height)
    return blockhash

def get_transactions_in_block(blockhash):
    return rpc_connection.getblock(blockhash)['tx']

def get_mempool_transactions():
    mempoolTransactions = rpc_connection.getrawmempool()
    return mempoolTransactions

def lookup_transaction(txid):
    blockfound = -1
    regTestChainSize = get_blockchain_size()
    for i in range(0, regTestChainSize+1):
        blockhash = get_block_hash(i)
        for transaction in get_transactions_in_block(blockhash):
            if transaction == txid:
                blockfound = i
    
    return blockfound

def lookup_mempool_transaction(txid):
    found = 0
    mempoolTransactions = get_mempool_transactions()
    if len(mempoolTransactions) > 0:
        for transaction in get_mempool_transactions():
            if transaction == txid:
                found = 1
    return found

def getraw_transaction(txid):
    return rpc_connection.getrawtransaction(txid)

def decode_transaction(raw):
    parsed = rpc_connection.decoderawtransaction(raw)
    formatted_json = simplejson.dumps(parsed, indent=4)
    #print(json.loads(parsed, indent=4, sort_keys=False))    
    return formatted_json

#=============
if __name__ == "__main__":
    if len(sys.argv) == 1:
        operation = 'chain'
    else:
        operation = sys.argv[1]

    #Show info on the entire chain and mempool. This is the default operation if none is specified.
    if operation.lower() == 'chain':
        regTestChainSize = get_blockchain_size()
        print('The network currently consists out of %s blocks.' % regTestChainSize)
        if regTestChainSize < 100:
            print('Warning: No transactions can be performed on this chain yet since there are no mature blocks!')

        for i in range(0, regTestChainSize+1):
            print('---------------------------------')
            print('Block height: %s' %i)
            blockhash = get_block_hash(i)
            print('Block hash  : %s' % blockhash)
            print('Transactions:')
            for transaction in get_transactions_in_block(blockhash):
                print(transaction)
            print('---------------------------------')
        
        print('')
        print('Mempool transactions')
        print('---------------------------------')
        mempoolTransactions = get_mempool_transactions()
        if len(mempoolTransactions) > 0:
            for transaction in get_mempool_transactions():
                print(transaction)
        else:
            print('Mempool is empty')

    #Show info on blocks containing at least one transaction other than coinbase reward
    if operation.lower() == 'blocktrans':
        regTestChainSize = get_blockchain_size()
        print('Scanning for blocks with at least one transaction other than coinbase reward:')
        for i in range(0, regTestChainSize+1):
            blockhash = get_block_hash(i)
            transInBlock = get_transactions_in_block(blockhash)
            if len(transInBlock) > 1:
                print('---------------------------------')
                print('Block height: %s' %i)
                print('Block hash  : %s' % blockhash)
                print('Transactions:')
                for transaction in transInBlock:
                    print(transaction)
                print('---------------------------------')

    #Show info on blocks containing at least one transaction other than coinbase reward
    if operation.lower() == 'mempool':
        print('')
        print('Mempool transactions:')
        mempoolTransactions = get_mempool_transactions()
        if len(mempoolTransactions) > 0:
            for transaction in get_mempool_transactions():
                print(transaction)
        else:
            print('Mempool is empty')

    #Show info on blocks containing at least one transaction other than coinbase reward
    if operation.lower() == 'trans':
        try:
            txid = sys.argv[2]
        except:
            sys.exit('Provide txid as search value')
        
        print('Looking up transaction %s'  % txid)

        mempoolfound = lookup_mempool_transaction(txid)
        if mempoolfound == 1:
            print('')
            print('------------------')
            print('Transaction is in the mempool (so unconfirmed)')
            print('------------------')            
        else:
            blockfound = lookup_transaction(txid)
            if blockfound > -1:
                print('')
                print('------------------')
                print('Transaction is included in block with height %s' % blockfound)
                print('------------------')
            else:
                sys.exit('Transaction was not found in any block or mempool.')
        
        raw_transaction = getraw_transaction(txid)
        print('------------------')
        print('Raw transaction:')
        print(raw_transaction)
        print('------------------')
        
        decoded_json = decode_transaction(raw_transaction)
        print('')
        print('------------------')
        print('Decoded transaction:')
        print(decoded_json)
        print('------------------')

Это первая программа, которую можно запустить с помощью параметра запуска для выполнения различных задач. Я представлю их одну за другой:


Получаем информацию о блоках в цепочке и мемпуле.

Code:
python3 info.py chain

The network currently consists out of 175 blocks.
---------------------------------
Block height: 1
Block hash  : 20e3935462a04eefca66b965d9ff6c3fc75388be010ca890ddb426110160a94d
Transactions:
36d07cbb236db866aaecc768bf514a90bf2c8ae2d3f5ec852cc72f757b741f8d
---------------------------------




---------------------------------
Block height: 175
Block hash  : 07c82a7e5ae630408d2f4f99af3dbcaacc2328d50bbea3beb6a8f7cdf55eb8bd
Transactions:
17a4fd218d864633207deedfbb2c943cefd78f96d4df5838fc731e76a4bdb16b
b5b3646b2452775964fde010c0e20282d9cb00e5d8fb3d1a75121f8725edc844
---------------------------------

Mempool transactions
---------------------------------
817e8bfc4797657d4a0e77389d168aa1018dd087a3c93195525fe0414b65956d
6cf0d8eefbc01340d81b6704907c47da13ebeb79251b1a7a155dc57124429804

Запуск информации с аргументом цепочки (или так как по умолчанию без какого-либо параметра) даст вам общую информацию о regtest блокчейне, включая все идентификаторы транзакций в блоке и транзакций в mempool (если таковые имеются).
Подсказка: Если вам нужна эта информация в текстовом файле, вы можете просто перенаправить ее, так что что-то вроде: python3 info.py chain > mychain.text


Список блоков, сгенерированных пользователем

Code:
python3 info.py blocktrans

Scanning for blocks with at lease one transaction other than coinbase reward:
---------------------------------
Block height: 151
Block hash  : 189c05ca108ff2091cf049483ea5c52e950dc789b45c51c1feaa1db0b8d0115d
Transactions:
68a10da9c0cf52aab47a6a2eb13c9404b42aff6206834e302eb5e3e1eba2fa1a
545cbb46c3a266f7ba2d0f159b5b91d4d28e140f12ab25a7fb6607940ccd511c
c52ca060fa3ac2cbb41b8708f5664a8418518b4c9b10224ee7e60f8e9783a960
002c700a5803ed49e52b3c58494b8a13a2b6d3fbab7be3c67aac2e57e02f0f71
88386302f926dd77e7aff370ddf440321daba1892c5e470de7460668eea645bd
372c3b5dffb323c850677ab852c90308b09b25a6895ee0825fc6fa20ce1dc6cf
---------------------------------
---------------------------------
Block height: 152
Block hash  : 6886d26823dab1c57f2aa1c5de27d50648a0da961e8ac5f155500ebe1ea95cb9
Transactions:
2e6f32adedc779c1eb948d77cb870f52a010e7dae703093f65db79cde1c98efa
85479cb7cfd788e94bb4b3007871857051b5282a07a1acfc458a57f9e785d35a
44c76adea68b6dd2785b61a0e48325ffd9cca95fb3e6a24585ee617e150ed99b
c784407fed108736c9a71d9ab2eb22ce1bf46c1ec9006d75e8a28671af86d1ae
---------------------------------
---------------------------------
Block height: 153
Block hash  : 71dfd97a6aca1e4183b1579fe3333aadc21670c2cf2cef88ff3281b3b8b6e111
Transactions:
dbb52d7049c9339a81b66e90509238b51d73571ff5b296d1a62d8beafb071389
499b9284eede4f80e4e19e8f1f2db289447cf85ff90bb2b536f1c8bc66ba9a99
---------------------------------
---------------------------------
Block height: 166
Block hash  : 5ab0a67ca9d6457193f57059cd37982b6620f6da016176177822f8519351f04a
Transactions:
1523e59493e6a64981256a546060ca41c40a2d51c7985c6637704918a00fcf2f
d88cf4d784d475cda43f72262573ef4c89fdf418e0a3afff2013ed917471209f
---------------------------------
---------------------------------
Block height: 170
Block hash  : 1484a88ee17b4dbc610969af1e9f6624fabd3871ccc911f0363e3a3c113757c7
Transactions:
12a00e59825ed735c7d7f9e6429bd78f4b445fe0898118b5676e7190a6475508
9e664ee1f641212df8ee6078f3f6f68bfeb2e920902d8362c2471c9081366f73
---------------------------------
---------------------------------
Block height: 175
Block hash  : 07c82a7e5ae630408d2f4f99af3dbcaacc2328d50bbea3beb6a8f7cdf55eb8bd
Transactions:
17a4fd218d864633207deedfbb2c943cefd78f96d4df5838fc731e76a4bdb16b
b5b3646b2452775964fde010c0e20282d9cb00e5d8fb3d1a75121f8725edc844

Особенно, когда вы экспериментируете с транзакциями, вы можете потерять те блоки, которые содержат ваши собственные генерируемые транзакции, а не только coinbase транзакции. Таким образом, при использовании параметра "blocktrans" вы можете получить список всех блоков, содержащих более 1 транзакции.


Список всех транзакций в мемпуле

Code:
python3 info.py mempool

Mempool transactions:
817e8bfc4797657d4a0e77389d168aa1018dd087a3c93195525fe0414b65956d
6cf0d8eefbc01340d81b6704907c47da13ebeb79251b1a7a155dc57124429804

Довольно просто, когда вы используете аргумент mempool, вы получите все txid (если таковые имеются) в данный момент в мемпуле.


Получение подробной информации о транзакции

Code:
python3 info.py trans 817e8bfc4797657d4a0e77389d168aa1018dd087a3c93195525fe0414b65956d

Looking up transaction 817e8bfc4797657d4a0e77389d168aa1018dd087a3c93195525fe0414b65956d

------------------
Transaction is in the mempool (so unconfirmed)
------------------
------------------
Raw transaction:
020000000001011431a62376437bf7228db991c2fdcdf4757750eb8fcbf8e47665841082aaac750000000000ffffffff014094052a010000001976a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac0247304402204d645f8fc2193fee73f835e1987f694e2761f60a6e692b88e340bdcc2c5c4962022058fedeca7be2d22028a6dbac41589bb61e70518a407b48685ec30cf2dbb52c77012102d836add3dce8aeaa481aa2843e6c317654b6cebe36c22f72641ea44a506e245700000000
------------------

------------------
Decoded transaction:
{
    "txid": "817e8bfc4797657d4a0e77389d168aa1018dd087a3c93195525fe0414b65956d",
    "hash": "22ea77afe16191bc6bba5b02e62de164a2d1c70c0eda65d8e7c055c3f38c8870",
    "version": 2,
    "size": 194,
    "vsize": 113,
    "weight": 449,
    "locktime": 0,
    "vin": [
        {
            "txid": "75acaa8210846576e4f8cb8feb507775f4cdfdc291b98d22f77b437623a63114",
            "vout": 0,
            "scriptSig": {
                "asm": "",
                "hex": ""
            },
            "txinwitness": [
                "304402204d645f8fc2193fee73f835e1987f694e2761f60a6e692b88e340bdcc2c5c4962022058fedeca7be2d22028a6dbac41589bb61e70518a407b48685ec30cf2dbb52c7701",
                "02d836add3dce8aeaa481aa2843e6c317654b6cebe36c22f72641ea44a506e2457"
            ],
            "sequence": 4294967295
        }
    ],
    "vout": [
        {
            "value": 49.99976000,
            "n": 0,
            "scriptPubKey": {
                "asm": "OP_DUP OP_HASH160 62e907b15cbf27d5425399ebf6f0fb50ebb88f18 OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac",
                "reqSigs": 1,
                "type": "pubkeyhash",
                "addresses": [
                    "mpXwg4jMtRhuSpVq4xS3HFHmCmWp9NyGKt"
                ]
            }
        }
    ]
}
------------------

Если вам нужна подробная информация о транзакции, включенная в блок или в мемпуле, вы можете использовать аргумент транзакции вместе с txid. Если транзакция найдена, то будет показана подробная информация.


Заключительные слова
Я надеюсь, что этот гайд дал вам хорошее представление о том, что такое regtest и почему он может пригодиться. Особенно, когда вы хотите поэкспериментировать с транзакциями, скриптами, это может быть лучшим местом, чем тестнет!
hero member
Activity: 520
Merit: 11957
August 18, 2020, 11:39:00 AM
#1
Jump to: