basic parsing
This commit is contained in:
parent
05d7a0143f
commit
bcc9ce484c
|
@ -1,16 +1,124 @@
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
#include "mem.h"
|
||||||
#include "bitcoin/psbt.h"
|
#include "bitcoin/psbt.h"
|
||||||
|
|
||||||
void core_btc_tx_elem_handler(psbt_elem_t* rec) {
|
#define BTC_MAX_INPUTS 10
|
||||||
|
#define BTC_MAX_OUTPUTS 10
|
||||||
|
|
||||||
|
enum btc_input_type {
|
||||||
|
BTC_INPUT_TYPE_LEGACY,
|
||||||
|
BTC_INPUT_TYPE_SEGWIT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum btc_sighash_flag {
|
||||||
|
SIGHASH_DEFAULT = 0x00,
|
||||||
|
SIGHASH_ALL = 0x01,
|
||||||
|
SIGHASH_NONE = 0x02,
|
||||||
|
SIGHASH_SINGLE = 0x03,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* pubkey_hash;
|
||||||
|
uint8_t* amount;
|
||||||
|
uint8_t* bip32_path;
|
||||||
|
uint32_t bip32_path_len;
|
||||||
|
uint32_t master_fingerprint;
|
||||||
|
uint32_t sighash_flag;
|
||||||
|
enum btc_input_type input_type;
|
||||||
|
} psbt_input_data_t;
|
||||||
|
|
||||||
|
struct btc_tx_ctx {
|
||||||
|
psbt_tx_t tx;
|
||||||
|
psbt_txin_t inputs[BTC_MAX_INPUTS];
|
||||||
|
psbt_txout_t outputs[BTC_MAX_OUTPUTS];
|
||||||
|
psbt_input_data_t input_data[BTC_MAX_INPUTS];
|
||||||
|
size_t input_count;
|
||||||
|
size_t output_count;
|
||||||
|
app_err_t error;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void core_btc_psbt_rec_handler(struct btc_tx_ctx* tx_data, size_t index, psbt_record_t* rec) {
|
||||||
|
if (rec->scope != PSBT_SCOPE_INPUTS) {
|
||||||
|
return;
|
||||||
|
} else if (index >= tx_data->input_count) {
|
||||||
|
tx_data->error = ERR_DATA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rec->type) {
|
||||||
|
case PSBT_IN_NON_WITNESS_UTXO:
|
||||||
|
case PSBT_IN_REDEEM_SCRIPT:
|
||||||
|
case PSBT_IN_WITNESS_SCRIPT:
|
||||||
|
//TODO: implement
|
||||||
|
tx_data->error = ERR_DECODE;
|
||||||
|
break;
|
||||||
|
case PSBT_IN_WITNESS_UTXO:
|
||||||
|
if ((rec->val[8] != 22) || (rec->val[9] != 0x00) || (rec->val[10] != 20)) {
|
||||||
|
tx_data->error = ERR_DECODE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_data->input_data[index].input_type = BTC_INPUT_TYPE_SEGWIT;
|
||||||
|
tx_data->input_data[index].amount = rec->val;
|
||||||
|
tx_data->input_data[index].pubkey_hash = &rec->val[11];
|
||||||
|
break;
|
||||||
|
case PSBT_IN_BIP32_DERIVATION:
|
||||||
|
memcpy(&tx_data->input_data[index].master_fingerprint, rec->val, sizeof(uint32_t));
|
||||||
|
tx_data->input_data[index].bip32_path = &rec->val[4];
|
||||||
|
tx_data->input_data[index].bip32_path_len = rec->val_size - 4;
|
||||||
|
break;
|
||||||
|
case PSBT_IN_SIGHASH_TYPE:
|
||||||
|
memcpy(&tx_data->input_data[index].sighash_flag, rec->val, sizeof(uint32_t));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void core_btc_txelem_handler(struct btc_tx_ctx* tx_data, psbt_txelem_t* elem) {
|
||||||
|
switch (elem->elem_type) {
|
||||||
|
case PSBT_TXELEM_TX:
|
||||||
|
memcpy(&tx_data->tx, elem->elem.tx, sizeof(psbt_tx_t));
|
||||||
|
break;
|
||||||
|
case PSBT_TXELEM_TXIN:
|
||||||
|
if (tx_data->input_count < BTC_MAX_INPUTS) {
|
||||||
|
memcpy(&tx_data->inputs[tx_data->input_count++], elem->elem.txin, sizeof(psbt_txin_t));
|
||||||
|
} else {
|
||||||
|
tx_data->error = ERR_FULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PSBT_TXELEM_TXOUT:
|
||||||
|
if (tx_data->output_count < BTC_MAX_OUTPUTS) {
|
||||||
|
memcpy(&tx_data->outputs[tx_data->output_count++], elem->elem.txout, sizeof(psbt_txout_t));
|
||||||
|
} else {
|
||||||
|
tx_data->error = ERR_FULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void core_btc_parser_cb(psbt_elem_t* rec) {
|
||||||
|
struct btc_tx_ctx* tx_data = (struct btc_tx_ctx*) rec->user_data;
|
||||||
|
|
||||||
if (rec->type == PSBT_ELEM_RECORD) {
|
if (rec->type == PSBT_ELEM_RECORD) {
|
||||||
|
core_btc_psbt_rec_handler(tx_data, rec->index, rec->elem.rec);
|
||||||
} else if (rec->type == PSBT_ELEM_TXELEM) {
|
} else if (rec->type == PSBT_ELEM_TXELEM) {
|
||||||
|
core_btc_txelem_handler(tx_data, rec->elem.txelem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_btc_psbt_run(struct zcbor_string* qr_request) {
|
void core_btc_psbt_run(struct zcbor_string* qr_request) {
|
||||||
|
struct btc_tx_ctx* tx_ctx = (struct btc_tx_ctx*) &qr_request->value[(qr_request->len + 3) & ~0x3];
|
||||||
|
memset(tx_ctx, 0, sizeof(struct btc_tx_ctx));
|
||||||
|
|
||||||
psbt_t psbt;
|
psbt_t psbt;
|
||||||
psbt_init(&psbt, (uint8_t*) qr_request->value, qr_request->len);
|
psbt_init(&psbt, (uint8_t*) qr_request->value, qr_request->len);
|
||||||
psbt_read(qr_request->value, qr_request->len, &psbt, core_btc_tx_elem_handler, NULL);
|
psbt_read(qr_request->value, qr_request->len, &psbt, core_btc_parser_cb, tx_ctx);
|
||||||
|
|
||||||
|
if (!tx_ctx->error != ERR_OK) {
|
||||||
|
//TODO: add error message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue