int serialize_tx(struct buff *buf, const btc_msg_tx *tx) { uint64 i; int res; res = serialize_uint32(buf, tx->version); res |= serialize_varint(buf, tx->in_count); for (i = 0; i < tx->in_count; i++) { res |= serialize_uint256(buf, &tx->tx_in[i].prevTxHash); res |= serialize_uint32(buf, tx->tx_in[i].prevTxOutIdx); res |= serialize_varint(buf, tx->tx_in[i].scriptLength); res |= serialize_bytes(buf, tx->tx_in[i].scriptSig, tx->tx_in[i].scriptLength); res |= serialize_uint32(buf, tx->tx_in[i].sequence); } res |= serialize_varint(buf, tx->out_count); for (i = 0; i < tx->out_count; i++) { res |= serialize_uint64(buf, tx->tx_out[i].value); res |= serialize_varint(buf, tx->tx_out[i].scriptLength); res |= serialize_bytes(buf, tx->tx_out[i].scriptPubKey, tx->tx_out[i].scriptLength); } res |= serialize_uint32(buf, tx->lock_time); return res; }
/* Serialize a block into a flat array (for hashing or writing to a file). */ static void block_serialize(const struct block *b, unsigned char buf[SERIALIZED_BLOCK_LEN]) { unsigned char *p, *endp; unsigned char uint32_buf[4]; p = buf; endp = buf + SERIALIZED_BLOCK_LEN; serialize(&p, endp, b->prev_block_hash, sizeof(b->prev_block_hash)); serialize_uint32(uint32_buf, b->height); serialize(&p, endp, uint32_buf, sizeof(uint32_buf)); serialize_uint32(uint32_buf, b->nonce); serialize(&p, endp, uint32_buf, sizeof(uint32_buf)); serialize_uint32(uint32_buf, b->reward_tx.height); serialize(&p, endp, uint32_buf, sizeof(uint32_buf)); serialize(&p, endp, b->reward_tx.prev_transaction_hash, sizeof(b->reward_tx.prev_transaction_hash)); serialize(&p, endp, b->reward_tx.dest_pubkey.x, sizeof(b->reward_tx.dest_pubkey.x)); serialize(&p, endp, b->reward_tx.dest_pubkey.y, sizeof(b->reward_tx.dest_pubkey.y)); serialize(&p, endp, b->reward_tx.src_signature.r, sizeof(b->reward_tx.src_signature.r)); serialize(&p, endp, b->reward_tx.src_signature.s, sizeof(b->reward_tx.src_signature.s)); serialize_uint32(uint32_buf, b->normal_tx.height); serialize(&p, endp, uint32_buf, sizeof(uint32_buf)); serialize(&p, endp, b->normal_tx.prev_transaction_hash, sizeof(b->normal_tx.prev_transaction_hash)); serialize(&p, endp, b->normal_tx.dest_pubkey.x, sizeof(b->normal_tx.dest_pubkey.x)); serialize(&p, endp, b->normal_tx.dest_pubkey.y, sizeof(b->normal_tx.dest_pubkey.y)); serialize(&p, endp, b->normal_tx.src_signature.r, sizeof(b->normal_tx.src_signature.r)); serialize(&p, endp, b->normal_tx.src_signature.s, sizeof(b->normal_tx.src_signature.s)); if (p != endp) abort(); }
int serialize_msgheader(struct buff *buf, const btc_msg_header *h) { int res; res = serialize_uint32(buf, h->magic); res |= serialize_bytes(buf, h->message, ARRAYSIZE(h->message)); res |= serialize_uint32(buf, h->payloadLength); res |= serialize_bytes(buf, h->checksum, ARRAYSIZE(h->checksum)); ASSERT_NOT_TESTED(res == 0); return res; }
bool serialize_data(char *&r_stream, uint32_t &r_stream_size, uint32_t &r_offset, const void *p_data, uint32_t p_data_size) { if (serialize_uint32(r_stream, r_stream_size, r_offset, p_data_size) && serialize_bytes(r_stream, r_stream_size, r_offset, p_data, p_data_size)) return true; return false; }
int serialize_version(struct buff *buf, const btc_msg_version *v) { int res; res = serialize_uint32(buf, v->version); res |= serialize_uint64(buf, v->services); res |= serialize_uint64(buf, v->time); res |= serialize_addr(buf, &v->addrTo); res |= serialize_addr(buf, &v->addrFrom); res |= serialize_uint64(buf, v->nonce); res |= serialize_str(buf, v->strVersion); res |= serialize_uint32(buf, v->startingHeight); return res; }
int serialize_varint(struct buff *buf, const uint64 val) { int res; uint8 c; if (val < 253) { c = val; return serialize_uint8(buf, c); } else if (val < 0x10000) { uint16 len16 = val; c = 253; res = serialize_uint8(buf, c); if (res) { return res; } return serialize_uint16(buf, len16); } else { uint32 len32 = val; c = 254; res = serialize_uint8(buf, c); if (res) { return res; } return serialize_uint32(buf, len32); } }
int serialize_inv(struct buff *buf, const btc_msg_inv *inv) { int res; res = serialize_uint32(buf, inv->type); res |= serialize_bytes(buf, &inv->hash, sizeof inv->hash); return res; }
int serialize_blocklocator(struct buff *buf, const btc_block_locator *bl) { int res; int i; res = serialize_uint32(buf, bl->protversion); res |= serialize_varint(buf, bl->numHashes); for (i = 0; i < bl->numHashes; i++) { res |= serialize_uint256(buf, &bl->hashArray[i]); } res |= serialize_uint256(buf, &bl->hashStop); return res; }
/* Sign this transaction using the given private key. Returns 1 for success; 0 * for error. */ int transaction_sign(struct transaction *tx, EC_KEY *key) { unsigned char uint32_buf[4]; SHA256_CTX sha; ECDSA_SIG *sig; BIGNUM *x, *y; hash_output h; sig = NULL; x = NULL; y = NULL; /* Signing this transaction, we ignore the src_signature field * itself. */ SHA256_Init(&sha); serialize_uint32(uint32_buf, tx->height); SHA256_Update(&sha, uint32_buf, sizeof(uint32_buf)); SHA256_Update(&sha, tx->prev_transaction_hash, sizeof(tx->prev_transaction_hash)); SHA256_Update(&sha, tx->dest_pubkey.x, sizeof(tx->dest_pubkey.x)); SHA256_Update(&sha, tx->dest_pubkey.y, sizeof(tx->dest_pubkey.y)); SHA256_Final(h, &sha); sig = ECDSA_do_sign(h, sizeof(h), key); if (sig == NULL) goto err; /* Copy the signature into the transaction's byte arrays. */ memset(tx->src_signature.r, 0, sizeof(tx->src_signature.r)); memset(tx->src_signature.s, 0, sizeof(tx->src_signature.s)); if (bn2bin(sig->r, tx->src_signature.r, sizeof(tx->src_signature.r)) != 1) goto err; if (bn2bin(sig->s, tx->src_signature.s, sizeof(tx->src_signature.s)) != 1) goto err; ECDSA_SIG_free(sig); BN_free(x); BN_free(y); return 1; err: if (sig != NULL) ECDSA_SIG_free(sig); if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); return 0; }
static void script_tx_sighash(struct wallet *wallet, uint256 *hash, const struct buff *scriptPubKey, const struct btc_msg_tx *tx, uint32 idx, enum script_hash_type hashType) { struct btc_msg_tx *tx2; struct buff *buf; int i; ASSERT(idx < tx->in_count); memset(hash, 0, sizeof *hash); tx2 = btc_msg_tx_dup(tx); Log(LGPFX " Computing sighash for txi-%u/%llu\n", idx, tx2->in_count); /* * Zero-out all the inputs' signatures. */ for (i = 0; i < tx2->in_count; i++) { tx2->tx_in[i].scriptLength = 0; } size_t len = buff_maxlen(scriptPubKey); ASSERT(len > 0); ASSERT(tx2->tx_in[idx].scriptSig == NULL); ASSERT(tx2->tx_in[idx].scriptLength == 0); tx2->tx_in[idx].scriptLength = len; tx2->tx_in[idx].scriptSig = safe_malloc(len); memcpy(tx2->tx_in[idx].scriptSig, buff_base(scriptPubKey), len); ASSERT((hashType & 0x1f) == SIGHASH_ALL); /* * Final step: * * Serialize tx + hashType (as a uint32) and compute hash. */ buf = buff_alloc(); serialize_tx(buf, tx2); serialize_uint32(buf, hashType); hash256_calc(buff_base(buf), buff_curlen(buf), hash); buff_free(buf); btc_msg_tx_free(tx2); free(tx2); }
/* Compute the hash value of this transaction. */ void transaction_hash(const struct transaction *tx, hash_output h) { unsigned char uint32_buf[4]; SHA256_CTX sha; SHA256_Init(&sha); serialize_uint32(uint32_buf, tx->height); SHA256_Update(&sha, uint32_buf, sizeof(uint32_buf)); SHA256_Update(&sha, tx->prev_transaction_hash, sizeof(tx->prev_transaction_hash)); SHA256_Update(&sha, tx->dest_pubkey.x, sizeof(tx->dest_pubkey.x)); SHA256_Update(&sha, tx->dest_pubkey.y, sizeof(tx->dest_pubkey.y)); SHA256_Update(&sha, tx->src_signature.r, sizeof(tx->src_signature.r)); SHA256_Update(&sha, tx->src_signature.s, sizeof(tx->src_signature.s)); SHA256_Final(h, &sha); }
static void script_push_data(struct buff *buf, const void *data, size_t len) { ASSERT(buf->grow); Log("%s: len=%zu / %#zx\n", __FUNCTION__, len, len); if (len < OP_PUSHDATA1) { serialize_uint8(buf, len); } else if (len <= 0xff) { serialize_uint8(buf, OP_PUSHDATA1); serialize_uint8(buf, len); } else if (len <= 0xffff) { serialize_uint8(buf, OP_PUSHDATA2); serialize_uint16(buf, len); } else { serialize_uint8(buf, OP_PUSHDATA4); serialize_uint32(buf, len); } serialize_bytes(buf, data, len); }
void serialize_header(pokeheader *header, char **outstream) { char buff8; char buff8b; char *buff32 = ( char *) malloc(4*sizeof( char)); buff32 = serialize_uint32(buff32, header->type); buff8 = serialize_uint8(buff8, header->id); buff8b = serialize_uint8(buff8b, header->data_size); char *instream = ( char *) malloc(7* sizeof( char)); for(int i = 0; i< 4; i++){ instream[i] = buff32[i]; } instream[4] = buff8; instream[5] = buff8b; memcpy(*outstream, instream, 7 ); free(buff32); free(instream); }
/* Verify the signature on this transaction using the public key * prev_tx->dest_pubkey. The return value is: * 1 for successful verification; * 0 for failed verification; * -1 for any runtime error. */ int transaction_verify(struct transaction *tx, const struct transaction *prev_tx) { unsigned char uint32_buf[4]; SHA256_CTX sha; hash_output h; EC_KEY *pubkey; ECDSA_SIG *sig; BIGNUM *x, *y; int v, rc; pubkey = NULL; sig = NULL; x = NULL; y = NULL; SHA256_Init(&sha); serialize_uint32(uint32_buf, tx->height); SHA256_Update(&sha, uint32_buf, sizeof(uint32_buf)); SHA256_Update(&sha, tx->prev_transaction_hash, sizeof(tx->prev_transaction_hash)); SHA256_Update(&sha, tx->dest_pubkey.x, sizeof(tx->dest_pubkey.x)); SHA256_Update(&sha, tx->dest_pubkey.y, sizeof(tx->dest_pubkey.y)); SHA256_Final(h, &sha); x = BN_bin2bn(prev_tx->dest_pubkey.x, sizeof(prev_tx->dest_pubkey.x), NULL); if (x == NULL) goto err; y = BN_bin2bn(prev_tx->dest_pubkey.y, sizeof(prev_tx->dest_pubkey.y), NULL); if (y == NULL) goto err; pubkey = EC_KEY_new_by_curve_name(EC_GROUP_NID); if (pubkey == NULL) goto err; rc = EC_KEY_set_public_key_affine_coordinates(pubkey, x, y); if (rc != 1) { EC_KEY_free(pubkey); BN_free(x); BN_free(y); return 0; } BN_free(x); x = NULL; BN_free(y); y = NULL; sig = ECDSA_SIG_new(); if (sig == NULL) goto err; sig->r = BN_bin2bn(tx->src_signature.r, sizeof(tx->src_signature.r), sig->r); if (sig->r == NULL) goto err; sig->s = BN_bin2bn(tx->src_signature.s, sizeof(tx->src_signature.s), sig->s); if (sig->s == NULL) goto err; v = ECDSA_do_verify(h, sizeof(h), sig, pubkey); EC_KEY_free(pubkey); ECDSA_SIG_free(sig); return v; err: if (pubkey != NULL) EC_KEY_free(pubkey); if (sig != NULL) ECDSA_SIG_free(sig); if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); return -1; }