美文网首页
比特币源码研读(17)-交易(3)交易流程分析

比特币源码研读(17)-交易(3)交易流程分析

作者: electroman | 来源:发表于2018-02-21 16:14 被阅读446次

在上一篇文章中,我们知道了,在交易以前要先判断entry是否有效。验证是否有效需要判断以下几个参数:

 1)检查地址是否有效

2)交易额是否有效

3)交易额是否小于0

4)拒绝小额交易

今天,我们在来看看拒绝小额交易的代码

   // Reject dust outputs:

   if (retval && GUIUtil::isDust(ui->payTo->text(),ui->payAmount->value())) {

       ui->payAmount->setValid(false);

       retval = false;

    }

其中的函数GUIUtil::isDust()是判断该交易是否为dust,该函数定义在guiutil.cpp文件中。函数如下:

bool isDust(const QString& address,const CAmount& amount)

{

   CTxDestination dest = DecodeDestination(address.toStdString());  //编译地址

   CScript script = GetScriptForDestination(dest);                              //获取脚本

    CTxOuttxOut(amount, script);

   return IsDust(txOut, ::dustRelayFee);

}

1 DecodeDestination()

DecodeDestination()函数是用于编译地址,该函数定义在base58.cpp中,定义如下:

CTxDestination DecodeDestination(conststd::string& str)

{

   return CBitcoinAddress(str).Get();

}

CBitcoinAddress类定义如下:

/** base58-encoded Bitcoin addresses.

 *Public-key-hash-addresses have version 0 (or 111 testnet).

 *The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is theserialized public key.

 *Script-hash-addresses have version 5 (or 196 testnet).

 *The data vector contains RIPEMD160(SHA256(cscript)), where cscript is theserialized redemption script.

 */

class CBitcoinAddress : public CBase58Data{

public:

   bool Set(const CKeyID &id);

   bool Set(const CScriptID &id);

   bool Set(const CTxDestination &dest);

   bool IsValid() const;

   bool IsValid(const CChainParams ¶ms) const;

   CBitcoinAddress() {}

   CBitcoinAddress(const CTxDestination &dest) { Set(dest); }

   CBitcoinAddress(const std::string& strAddress) {SetString(strAddress); }

    CBitcoinAddress(const char* pszAddress) {SetString(pszAddress); }

   CTxDestination Get() const;

};

从注释可以看出:该类用于base58编码,版本5以前用公钥地址,版本5以后用脚本公钥

Get()函数定义如下;

CTxDestination CBitcoinAddress::Get() const

{

   if (!IsValid())

       return CNoDestination();

   uint160 id;

    memcpy(&id,vchData.data(), 20);

   if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))//公钥地址编译

       return CKeyID(id);

   else if (vchVersion ==Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))//脚本地址编译

       return CScriptID(id);

   else

        return CNoDestination();

}

2 GetScriptForDestination

GetScriptForDestination()函数,获取脚本,函数定义如下:

CScript GetScriptForDestination(constCTxDestination& dest)

{

   CScript script;

   boost::apply_visitor(CScriptVisitor(&script), dest);

   return script;

}

3 IsDust()

IsDust()函数为判断是否为dust的函数,定义在policy.cpp中,定义如下:

bool IsDust(const CTxOut& txout, constCFeeRate& dustRelayFeeIn)

{

   return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));

}

其中函数GetDustThreshold()是检测设定的dust值,定义在policy.cpp中。

CAmount GetDustThreshold(const CTxOut&txout, const CFeeRate& dustRelayFeeIn)

{

//"Dust" is defined in terms of dustRelayFee,

// which hasunits satoshis-per-kilobyte.  

   // If you'd pay more in fees than the value of the output

   // to spend something, then we consider it dust.

   // A typical spendable non-segwit txout is 34 bytes big, and will

   // need a CTxIn of at least 148 bytes to spend:

   // so dust is a spendable txout less than

   // 182*dustRelayFee/1000 (in satoshis).

   // 546 satoshis at the default rate of 3000 sat/kB

   // A typical spendablesegwit txout is 31 bytesbig, and will  

   // need a CTxIn of at least 67 bytes to spend:

   // so dust is a spendable txout less than

   // 98*dustRelayFee/1000 (in satoshis).

// 294 satoshisat the default rate of 3000 sat/kB.

   if (txout.scriptPubKey.IsUnspendable())      //判断脚本格式是否支持

       return 0;

   size_t nSize = GetSerializeSize(txout, SER_DISK, 0);

   int witnessversion = 0;

   std::vector witnessprogram;

       //判断是否支持隔离见证

   if (txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)){

       // sum the sizes of the parts of a transaction input

       // with 75% segwit discount applied to the script size.

       nSize += (32 + 4 + 1 + (107 /WITNESS_SCALE_FACTOR)+ 4);

    }else {

       nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above

    }

   return dustRelayFeeIn.GetFee(nSize);

}

由注释可以看出,交易费用是否为dust与下面几个因素有关

1)设定的dustRelayFee,dustRelayFee设置的越大,则dust越大

2)如果没用隔离见证,则dust较大:dust = 182*dustRelayFee/1000,当交易费用为3000 sat/kB.,是dust= 546sat。

3)如果有隔离见证,则dust较小。Dust=98*dustRelayFee/1000,当交易费用为3000 sat/kB.,是dust= 294sat。

本文由【区块链研习社】优质内容计划支持,更多关于区块链的深度好文,请点击[区块链研习社](http://www.jianshu.com/c/b17f09dc2831)

区块链研习社比特币源码研读班  electroman

以下是广告:

我们区块链研习社已创建“区块链研习社币圈交流”小密圈”,在小密圈中,我们将带领大家一起学习区块链的原理与投资,还将提供区块链基本原理解答、交易所注册与交易操作、ICO交易与操作、投资分析、风险分析等内容。

相关文章

网友评论

      本文标题:比特币源码研读(17)-交易(3)交易流程分析

      本文链接:https://www.haomeiwen.com/subject/hmkotftx.html