您的位置:首页 > 其它

【比特币】交易

2014-07-22 18:42 881 查看
做实验之前使用-txindex=1(索引所有交易)和-reindex(重新索引block)来启动Daemon程序bitcoind

./bitcoind -datadir=/root/harrywu/temp/bitcoin-v0.9.1/ -gen -daemon -reindex -txindex=1


标准交易实验部分:

1)创建交易

createrawtransaction [{\"txid\":\"94ab03c82d036454c0b733094b306997eebee297af1684f905b3a74a4092efbc\",\"vout\":0}] {\"PN3h88Az7oyt4oRkGQov6KgHhT2U4BQbgH\":50}
0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab940000000000ffffffff0100f2052a010000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000


2)签名交易

signrawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab940000000000ffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
{
"hex" : "0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006b4830450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba80121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000",
"complete" : true
}
decoderawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006b4830450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba80121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
{
    "txid" : "cd488764b6a87e9aacbec021ba678ea262890dfed400594931aa3856bcaa59e2",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
        {
            "txid" : "94ab03c82d036454c0b733094b306997eebee297af1684f905b3a74a4092efbc",
            "vout" : 0,
            "scriptSig" : {
                "asm" : "30450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba801 032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f",
                "hex" : "4830450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba80121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f"
            },
            "sequence" : 4294967295
        }
    ],
    "vout" : [
        {
            "value" : 100.00000000,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 939d776145ae6e35a9be0592361938683bb57561 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a914939d776145ae6e35a9be0592361938683bb5756188ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "PN3h88Az7oyt4oRkGQov6KgHhT2U4BQbgH"
                ]
            }
        }
    ]
}




玩一下:
修改签名(r,s)中的s部,使得s'=n-s, n是椭圆曲线多项式方程的order,(p,a,b,G,n,h)中n,对于secp256k1的koblitz曲线,

n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141

decoderawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006c4930460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed2215990121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
{
"txid" : "4d391c500dd247eb6c78fc069d876ed0833f92c2581adca5e454406a79535001",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "94ab03c82d036454c0b733094b306997eebee297af1684f905b3a74a4092efbc",
"vout" : 0,
"scriptSig" : {
"asm" : "30460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed22159901 032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f",
"hex" : "4930460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed2215990121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 100.00000000,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 939d776145ae6e35a9be0592361938683bb57561 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a914939d776145ae6e35a9be0592361938683bb5756188ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"PN3h88Az7oyt4oRkGQov6KgHhT2U4BQbgH"
]
}
}
]
}


3)发送交易

sendrawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006c4930460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed2215990121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
4d391c500dd247eb6c78fc069d876ed0833f92c2581adca5e454406a79535001


提示:

1)createrawtransaction 的参数格式要求:转义,无空格

2)需要了解der编码

3)做实验的客户端我修改了部分参数的,地址前缀是P(官方是1),但是不影响实验








Byte-map of Transaction with each type of TxIn and TxOut

《《《《以下内容来自 Wiki》》》》
transaction is a signed section of data that is broadcast to the network and
collected into blocks. It typically references previous transaction(s) and dedicates
a certain number of bitcoins from it to one or more new public key(s) (Bitcoin address). It is not encrypted (nothing in Bitcoin is encrypted).
A block
chain browser is a site where every transaction included within the block chain can be viewed. This is useful for seeing the technical details of transaction in action, and for payment verification purposes.


general format of a Bitcoin transaction (inside a block)

FieldDescriptionSize
Version nocurrently 14 bytes
In-counterpositive integer VI
= VarInt
1 - 9 bytes
list of inputsthe
first input of the first transaction is also called "coinbase" (its content was ignored in earlier versions)
<in-counter>-many inputs
Out-counterpositive integer VI
= VarInt
1 - 9 bytes
list of outputsthe
outputs of the first transaction spend the mined bitcoins for the block
<out-counter>-many outputs
lock_timeif non-zero and sequence numbers are < 0xFFFFFFFF: block height or timestamp when transaction is final4 bytes


Principle example of a Bitcoin transaction with 1 input and 1 output only


Data

Input:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10
90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501

Output:
Value: 5000000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG


Explanation

The input in this transaction imports 50 BTC from output #0 in transaction f5d8... Then the output sends 50 BTC to a Bitcoin address (expressed here in hexadecimal 4043... instead of the
normal base58). When the recipient wants to spend this money, he will reference output #0 of this transaction in an input of his own transaction.

Input

An input is a reference to an output in a different transaction. Multiple inputs are often listed in a transaction. The values of the referenced outputs are added up, and
the total is usable in the outputs of this transaction. Previous tx is a hash of
a previous transaction. Index is the specific output in the referenced transaction. ScriptSig is the first half of a script (discussed
in more detail later).
The script contains two components, a signature and a public key. The public key must match the hash given in the script of the redeemed output. The public key is used to verify the redeemers
signature, which is the second component. More precisely, the second component is an ECDSA signature over a hash of a simplified version of the transaction. It, combined with the public key, proves the transaction was created by the real owner of the address
in question. Various flags define how the transaction is simplified and can be used to create different types of payment.

Output

An output contains instructions for sending bitcoins. Value is the number of Satoshi (1 BTC = 100,000,000 Satoshi) that this output will be worth when claimed. ScriptPubKey is
the second half of a script (discussed later). There can be more than one output, and they share the combined value of the inputs. Because each output from one transaction can only ever be referenced once by an input of a subsequent transaction, the entire
combined input value needs to be sent in an output if you don't want to lose it. If the input is worth 50 BTC but you only want to send 25 BTC, Bitcoin will create two outputs worth 25 BTC: one to the destination, and one back to you (known as "change",
though you send it to yourself). Any input bitcoins not redeemed in an output is considered a transaction
fee; whoever generates the block will get it.








A sends 100 BTC to C and C generates 50 BTC. C sends 101 BTC to D, and he needs to send himself some change. D sends the 101 BTC to someone else, but they haven't redeemed it yet. Only D's output and C's change are capable of being spent in the current state.


Verification

To verify that inputs are authorized to collect the values of referenced outputs, Bitcoin uses a custom Forth-like scripting system.
The input's scriptSig and the referencedoutput's scriptPubKey are evaluated (in that order), with scriptPubKey using the values left on the stack by scriptSig. The input is authorized if scriptPubKey returns true. Through the scripting system, the
sender can create very complex conditions that people have to meet in order to claim the output's value. For example, it's possible to create an output that can be claimed by anyone without any authorization. It's also possible to require that an input be
signed by ten different keys, or be redeemable with a password instead of a key.


Types of Transaction

Bitcoin currently creates two different scriptSig/scriptPubKey pairs. These are described below.
It is possible to design more complex types of transactions, and link them together into cryptographically enforced agreements. These are known as Contracts.


Pay-to-PubkeyHash

scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig: <sig> <pubKey>

A Bitcoin address is only
a hash, so the sender can't provide a full public key in scriptPubKey. When redeeming coins that have been sent to a Bitcoin address, the recipient provides both the signature and the public key. The script verifies that the provided public key does hash to
the hash in scriptPubKey, and then it also checks the signature against the public key.
Checking process:
StackScriptDescription
Empty.<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGscriptSig and scriptPubKey are combined.
<sig> <pubKey>OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGConstants are added to the stack.
<sig> <pubKey> <pubKey>OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGTop stack item is duplicated.
<sig> <pubKey> <pubHashA><pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGTop stack item is hashed.
<sig> <pubKey> <pubHashA> <pubKeyHash>OP_EQUALVERIFY OP_CHECKSIGConstant added.
<sig> <pubKey>OP_CHECKSIGEquality is checked between the top two stack items.
trueEmpty.Signature is checked for top two stack items.


Pay-to-Script-Hash

scriptPubKey: OP_HASH160 <scriptHash> OP_EQUAL
scriptSig: ..signatures... <serialized script>

m-of-n multi-signature transaction:
scriptSig: 0 <sig1> ... <script>
script: OP_m <pubKey1> ... OP_n OP_CHECKMULTISIG


P2SH addresses were created with the motivation of moving "the responsibility for supplying the conditions to redeem a transaction from the sender of the funds to the redeemer. They allow the sender to fund an arbitrary transaction, no matter how complicated,
using a 20-byte hash"1. Pay-to-Pubkey-hash
addresses are similarly a 20-byte hash of the public key.
Pay-to-script-hash provides a means for complicated transactions, unlike the Pay-to-pubkey-hash, which has a specific definition for scriptPubKey, and scriptSig. The specification places
no limitations on the script, and hence absolutely any contract can be funded using these addresses.
The scriptPubKey in the funding transaction is script which ensures that the script supplied in the redeeming transaction hashes to the script used to create the address.
In the scriptSig above, 'signatures' refers to any script which is sufficient to satisfy the following serialized script.
Checking process:
StackScriptDescription
Empty.0 <sig1> <sig2> OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIGOnly the scriptSig is used.
0 <sig1> <sig2> OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3OP_CHECKMULTISIGConstants are added to the stack.
trueEmptySignatures validated in the order of the keys in the script.
See also BIP 0016


Generation

Generations have a single input, and this input has a "coinbase" parameter instead of a scriptSig. The data in "coinbase" can be anything; it isn't used. Bitcoin puts the current compact-format target and
the arbitrary-precision "extraNonce" number there, which increments every time the Nonce field in the block
header overflows. Outputs can be anything, but Bitcoin creates one exactly like an IP address transaction. The extranonce contributes to enlarge the domain for the proof of work function. Miners can easily modify nonce (4byte), timestamp and extranonce
(2 to 100bytes).


general format (inside a block) of each input of a transaction - Txin

FieldDescriptionSize
Previous Transaction hashdoubled SHA256-hashed of
a (previous) to-be-used transaction
32 bytes
Previous Txout-indexnon negative integer indexing an output of the to-be-used transaction4 bytes
Txin-script lengthnon negative integer VI
= VarInt
1 - 9 bytes
Txin-script / scriptSigScript<in-script length>-many bytes
sequence_nonormally 0xFFFFFFFF; irrelevant unless transaction's lock_time is > 04 bytes
The input sufficiently describes where and how to get the bitcoin amout to be redeemed. If it is the (only) input of the first transaction of a block, it is called the generation transaction
input and its content completely ignored. (Historically the Previous Transaction hash is 0 and the Previous Txout-index is -1.)


general format (inside a block) of each output of a transaction - Txout

FieldDescriptionSize
valuenon negative integer giving the number of Satoshis(BTC/10^8) to
be transfered
8 bytes
Txout-script lengthnon negative integer1 - 9 bytes VI
= VarInt
Txout-script / scriptPubKeyScript<out-script length>-many bytes
The output sets the conditions to release this bitcoin amount later. The sum of the output values of the first transaction is the value of the mined bitcoins for the block plus possible transactions
fees of the other transactions in the block.

交易的签名

bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];

// Leave out the signature from the hash, since a signature can't sign itself.
// The checksig op will also drop the signatures from its hash.
uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType);

txnouttype whichType;
if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType))
return false;

if (whichType == TX_SCRIPTHASH)
{
// Solver returns the subscript that need to be evaluated;
// the final scriptSig is the signatures from that
// and then the serialized subscript:
CScript subscript = txin.scriptSig;

// Recompute txn hash using subscript in place of scriptPubKey:
uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType);

txnouttype subType;
bool fSolved =
Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH;
// Append serialized subscript whether or not it is completely signed:
txin.scriptSig << static_cast<valtype>(subscript);
if (!fSolved) return false;
}

// Test solution
return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, 0);
}


获取交易的hash

uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
if (nIn >= txTo.vin.size()) {
LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
return 1;
}

// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nIn);
return 1;
}
}

// Wrapper to serialize only the necessary parts of the transaction being signed
CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);

// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
ss << txTmp << nHashType;
return ss.GetHash();
}


交易的序列化

namespace {
/** Wrapper that serializes like CTransaction, but with the modifications
*  required for the signature hash done in-place
*/
class CTransactionSignatureSerializer {
private:
const CTransaction &txTo;  // reference to the spending transaction (the one being serialized)
const CScript &scriptCode; // output script being consumed
const unsigned int nIn;    // input index of txTo being signed
const bool fAnyoneCanPay;  // whether the hashtype has the SIGHASH_ANYONECANPAY flag set
const bool fHashSingle;    // whether the hashtype is SIGHASH_SINGLE
const bool fHashNone;      // whether the hashtype is SIGHASH_NONE

public:
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}

/** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
template<typename S>
void SerializeScriptCode(S &s, int nType, int nVersion) const {
CScript::const_iterator it = scriptCode.begin();
CScript::const_iterator itBegin = it;
opcodetype opcode;
unsigned int nCodeSeparators = 0;
while (scriptCode.GetOp(it, opcode)) {
if (opcode == OP_CODESEPARATOR)
nCodeSeparators++;
}
::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
it = itBegin;
while (scriptCode.GetOp(it, opcode)) {
if (opcode == OP_CODESEPARATOR) {
s.write((char*)&itBegin[0], it-itBegin-1);
itBegin = it;
}
}
s.write((char*)&itBegin[0], it-itBegin);
}

/** Serialize an input of txTo */
template<typename S>
void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) const {
// In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
if (fAnyoneCanPay)
nInput = nIn;
// Serialize the prevout
::Serialize(s, txTo.vin[nInput].prevout, nType, nVersion);
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
::Serialize(s, CScript(), nType, nVersion);
else
SerializeScriptCode(s, nType, nVersion);
// Serialize the nSequence
if (nInput != nIn && (fHashSingle || fHashNone))
// let the others update at will
::Serialize(s, (int)0, nType, nVersion);
else
::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion);
}

/** Serialize an output of txTo */
template<typename S>
void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const {
if (fHashSingle && nOutput != nIn)
// Do not lock-in the txout payee at other indices as txin
::Serialize(s, CTxOut(), nType, nVersion);
else
::Serialize(s, txTo.vout[nOutput], nType, nVersion);
}

/** Serialize txTo */
template<typename S>
void Serialize(S &s, int nType, int nVersion) const {
// Serialize nVersion
::Serialize(s, txTo.nVersion, nType, nVersion);
// Serialize vin
unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
::WriteCompactSize(s, nInputs);
for (unsigned int nInput = 0; nInput < nInputs; nInput++)
SerializeInput(s, nInput, nType, nVersion);
// Serialize vout
unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
::WriteCompactSize(s, nOutputs);
for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
SerializeOutput(s, nOutput, nType, nVersion);
// Serialie nLockTime
::Serialize(s, txTo.nLockTime, nType, nVersion);
}
};
}

标准签名步骤

//
// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type.
// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
// Returns false if scriptPubKey could not be completely satisfied.
//
bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType,
CScript& scriptSigRet, txnouttype& whichTypeRet)
{
scriptSigRet.clear();

vector<valtype> vSolutions;
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
return false;

CKeyID keyID;
switch (whichTypeRet)
{
case TX_NONSTANDARD:
case TX_NULL_DATA:
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
return Sign1(keyID, keystore, hash, nHashType, scriptSigRet);
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
return false;
else
{
CPubKey vch;
keystore.GetPubKey(keyID, vch);
scriptSigRet << vch;
}
return true;
case TX_SCRIPTHASH:
return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet);

case TX_MULTISIG:
scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet));
}
return false;
}

//
// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
//
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
{
// Templates
static multimap<txnouttype, CScript> mTemplates;
if (mTemplates.empty())
{
// Standard tx, sender provides pubkey, receiver adds signature
mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));

// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));

// Sender provides N pubkeys, receivers provides M signatures
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));

// Empty, provably prunable, data-carrying output
mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));
mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN));
}

// Shortcut for pay-to-script-hash, which are more constrained than the other types:
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if (scriptPubKey.IsPayToScriptHash())
{
typeRet = TX_SCRIPTHASH;
vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
vSolutionsRet.push_back(hashBytes);
return true;
}

// Scan templates
const CScript& script1 = scriptPubKey;
BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
{
const CScript& script2 = tplate.second;
vSolutionsRet.clear();

opcodetype opcode1, opcode2;
vector<unsigned char> vch1, vch2;

// Compare
CScript::const_iterator pc1 = script1.begin();
CScript::const_iterator pc2 = script2.begin();
while (true)
{
if (pc1 == script1.end() && pc2 == script2.end())
{
// Found a match
typeRet = tplate.first;
if (typeRet == TX_MULTISIG)
{
// Additional checks for TX_MULTISIG:
unsigned char m = vSolutionsRet.front()[0];
unsigned char n = vSolutionsRet.back()[0];
if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
return false;
}
return true;
}
if (!script1.GetOp(pc1, opcode1, vch1))
break;
if (!script2.GetOp(pc2, opcode2, vch2))
break;

// Template matching opcodes:
if (opcode2 == OP_PUBKEYS)
{
while (vch1.size() >= 33 && vch1.size() <= 65)
{
vSolutionsRet.push_back(vch1);
if (!script1.GetOp(pc1, opcode1, vch1))
break;
}
if (!script2.GetOp(pc2, opcode2, vch2))
break;
// Normal situation is to fall through
// to other if/else statements
}

if (opcode2 == OP_PUBKEY)
{
if (vch1.size() < 33 || vch1.size() > 65)
break;
vSolutionsRet.push_back(vch1);
}
else if (opcode2 == OP_PUBKEYHASH)
{
if (vch1.size() != sizeof(uint160))
break;
vSolutionsRet.push_back(vch1);
}
else if (opcode2 == OP_SMALLINTEGER)
{   // Single-byte small integer pushed onto vSolutions
if (opcode1 == OP_0 ||
(opcode1 >= OP_1 && opcode1 <= OP_16))
{
char n = (char)CScript::DecodeOP_N(opcode1);
vSolutionsRet.push_back(valtype(1, n));
}
else
break;
}
else if (opcode2 == OP_SMALLDATA)
{
// small pushdata, <= MAX_OP_RETURN_RELAY bytes
if (vch1.size() > MAX_OP_RETURN_RELAY)
break;
}
else if (opcode1 != opcode2 || vch1 != vch2)
{
// Others must match exactly
break;
}
}
}

vSolutionsRet.clear();
typeRet = TX_NONSTANDARD;
return false;
}

bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
{
CKey key;
if (!keystore.GetKey(address, key))
return false;

vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig;

return true;
}

bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
{
int nSigned = 0;
int nRequired = multisigdata.front()[0];
for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
{
const valtype& pubkey = multisigdata[i];
CKeyID keyID = CPubKey(pubkey).GetID();
if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
++nSigned;
}
return nSigned==nRequired;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: