示例#1
0
void bp_tx_sigserializer(cstring *s, const cstring *scriptCode,
			const struct bp_tx *txTo, unsigned int nIn,
			int nHashType)
{
    const bool fAnyoneCanPay = (!!(nHashType & SIGHASH_ANYONECANPAY));
    const bool fHashSingle = ((nHashType & 0x1f) == SIGHASH_SINGLE);
    const bool fHashNone = ((nHashType & 0x1f) == SIGHASH_NONE);

    /** Serialize txTo */
    // Serialize nVersion
    ser_u32(s, txTo->nVersion);

    // Serialize vin
    unsigned int nInputs = fAnyoneCanPay ? 1 : txTo->vin->len;
    ser_varlen(s, nInputs);

	unsigned int nInput;
	for (nInput = 0; nInput < nInputs; nInput++) {
	    /** Serialize an input of txTo */
	    // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
		if (fAnyoneCanPay)
			nInput = nIn;

	    struct bp_txin *txin = parr_idx(txTo->vin, nInput);

	    // Serialize the prevout
	    ser_bp_outpt(s, &txin->prevout);

		// Serialize the script
		if (nInput != nIn)
			// Blank out other inputs' signatures
			ser_varlen(s, (int)0);
		else if (scriptCode == NULL)
		    cstr_append_c(s, 0);
		else {
			/** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
			struct const_buffer it = { scriptCode->str, scriptCode->len };
			struct const_buffer itBegin = it;
			struct bscript_op op;
			unsigned int nCodeSeparators = 0;

			struct bscript_parser bp;
			bsp_start(&bp, &it);

			while (bsp_getop(&op, &bp)) {
				if (op.op == OP_CODESEPARATOR)
				    nCodeSeparators++;
			}
			ser_varlen(s, scriptCode->len - nCodeSeparators);

			it = itBegin;
			bsp_start(&bp, &it);

			while (bsp_getop(&op, &bp)) {
			    if (op.op == OP_CODESEPARATOR) {
					ser_bytes(s, itBegin.p, it.p - itBegin.p - 1);
					itBegin  = it;
			    }
			}

			if (itBegin.p != scriptCode->str + scriptCode->len)
			    ser_bytes(s, itBegin.p, it.p - itBegin.p);
		}

		// Serialize the nSequence
		if ((nInput != nIn) && (fHashSingle || fHashNone))
			// let the others update at will
			ser_u32(s, (int)0);
		else
			ser_u32(s, txin->nSequence);
	}

    // Serialize vout
    unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? (nIn + 1) : txTo->vout->len);
    ser_varlen(s, nOutputs);

	unsigned int nOutput;
    for (nOutput = 0; nOutput < nOutputs; nOutput++) {
		struct bp_txout *txout = parr_idx(txTo->vout, nOutput);
		if (fHashSingle && (nOutput != nIn))
			// Do not lock-in the txout payee at other indices as txin;
			bp_txout_set_null(txout);

		ser_bp_txout(s, txout);
    }
    // Serialize nLockTime
    ser_u32(s, txTo->nLockTime);
}
示例#2
0
void bp_tx_sighash(bu256_t *hash, const GString *scriptCode,
		   const struct bp_tx *txTo, unsigned int nIn,
		   int nHashType)
{
	if (nIn >= txTo->vin->len) {
		bu256_set_u64(hash, 1);
		goto out;
	}
	
	struct bp_tx txTmp;
	bp_tx_init(&txTmp);
	bp_tx_copy(&txTmp, txTo);

	/* TODO: find-and-delete OP_CODESEPARATOR from scriptCode */

	/* Blank out other inputs' signatures */
	unsigned int i;
	struct bp_txin *txin;
	for (i = 0; i < txTmp.vin->len; i++) {
		txin = g_ptr_array_index(txTmp.vin, i);
		g_string_set_size(txin->scriptSig, 0);

		if (i == nIn)
			g_string_append_len(txin->scriptSig,
					    scriptCode->str, scriptCode->len);
	}

	/* Blank out some of the outputs */
	if ((nHashType & 0x1f) == SIGHASH_NONE) {
		/* Wildcard payee */
		bp_tx_free_vout(&txTmp);
		txTmp.vout = g_ptr_array_new_full(1, g_free);

		/* Let the others update at will */
		for (i = 0; i < txTmp.vin->len; i++) {
			txin = g_ptr_array_index(txTmp.vin, i);
			if (i != nIn)
				txin->nSequence = 0;
		}
	}

	else if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
		/* Only lock-in the txout payee at same index as txin */
		unsigned int nOut = nIn;
		if (nOut >= txTmp.vout->len) {
			bu256_set_u64(hash, 1);
			goto out;
		}

		g_ptr_array_set_size(txTmp.vout, nOut + 1);

		for (i = 0; i < nOut; i++) {
			struct bp_txout *txout;

			txout = g_ptr_array_index(txTmp.vout, i);
			bp_txout_set_null(txout);
		}

		/* Let the others update at will */
		for (i = 0; i < txTmp.vin->len; i++) {
			txin = g_ptr_array_index(txTmp.vin, i);
			if (i != nIn)
				txin->nSequence = 0;
		}
	}

	/* Blank out other inputs completely;
	   not recommended for open transactions */
	if (nHashType & SIGHASH_ANYONECANPAY) {
		if (nIn > 0)
			g_ptr_array_remove_range(txTmp.vin, 0, nIn);
		g_ptr_array_set_size(txTmp.vin, 1);
	}

	/* Serialize and hash */
	bp_tx_calc_sighash(hash, &txTmp, nHashType);

out:
	bp_tx_free(&txTmp);
}