C# BC,成功創建和簽署原始交易
第一次在stackexchange上尋求幫助,如果我犯了錯誤,對不起(英語不是我的母語)。
我嘗試使用 bouncycastle 在 C# 上創建一個有效的原始事務,但我似乎卡住了,無法找到我的錯誤在哪裡。我在 testnet 網路上進行了測試,並使用了許多資源來幫助自己,主要是這個。首先,我有下一個地址和私鑰
Address: mjhcWg5SvS96kk85R8G1wp7mru55UCNGY5 Public Key Hex: 0482052EF9560585ED62F046EE45C1B5F85448BCF1BD5CE36A7D35EB00C8A146C14BF99223907F9A8688E6F84B54FD747A637BB82F02E296203E735E7A6B40059F Wif: 93U5P1qHPXAhXhiw1T15z3f1cBqFw9fWrd3Yzz1nDk8b2aRbrrM Private Key Hex: F7DBD21285F621F1C7A47AE7F63D06C276FE49839F4842DDEF805477936812A5
我想使用上一個(testnet)交易中的 6.49689241 btc
912a2c3d84c8572b39c173b2bcde950cfe4ae07756bac189ace98f198d5ccb7d
並將一些(作為測試)發送回水龍頭 mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
首先,為了建構未簽名的原始交易,我添加了這些字節:
01000000 (version number) 01 (number of inputs) 7dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91 (reversed previous tx hash) 01000000 (output index) 1976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac (previous tx script with its length at start) ffffffff (sequence) 02 (number of outputs) 496ff50200000000 (first output little endian amount. The faucet) 1976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac (first output script with its length at start) 0046c32300000000 (second output little endian amount. My address, for change) 1976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac (second script with its length at start) 00000000 (locktime) 01000000 (hash code type)
結果是
01000000017dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91010000001976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88acffffffff02496ff502000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac0046c323000000001976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac0000000001000000
然後我通過將原始交易推送到返回給我的雙 SHA256 函式中來檢索交易雜湊
f64b6480a2888596636d4995153e990ce95582a1308c9c568d2698e6dc1f7893
然後,我使用私鑰十六進制 (prvkeyHex) 使用此函式對交易雜湊 (txHash) 進行簽名:
X9ECParameters curve = SecNamedCurves.GetByName("secp256k1"); ECDomainParameters dom = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H) ECKeyParameters params = new ECPrivateKeyParameters(new BigInteger(1, prvkeyHex), dom); ECDsaSigner signer = new ECDsaSigner(); signer.Init(true, params); BigInteger[] sig = signer.GenerateSignature(txHash); MemoryStream ms = new MemoryStream(72); DerSequenceGenerator seq = new DerSequenceGenerator(ms); seq.AddObject(new DerInteger(sig[0])); seq.AddObject(new DerInteger(sig[1])); seq.Close(); byte[] signature = ms.ToArray();
它返回我一個最大 72 字節長度的字節數組,從 30 開始。在我的最後一個測試中:
3045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d23
然後,我使用公鑰十六進制及其長度構造我的最終 scriptSig,結果為
483045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d2301410482052ef9560585ed62f046ee45c1b5f85448bcf1bd5ce36a7d35eb00c8a146c14bf99223907f9a8688e6f84b54fd747a637bb82f02e296203e735e7a6b40059f
我終於建立了我簽名的原始交易:
01000000 (version number) 01 (number of inputs) 7dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91 (reversed previous tx hash) 01000000 (output index) 8b (scriptSig length) 483045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d2301410482052ef9560585ed62f046ee45c1b5f85448bcf1bd5ce36a7d35eb00c8a146c14bf99223907f9a8688e6f84b54fd747a637bb82f02e296203e735e7a6b40059f (scriptSig) ffffffff (sequence) 02 (number of outputs) 496ff50200000000 (first output little endian amount. The faucet) 1976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac (first output script with its length at start) 0046c32300000000 (second output little endian amount. My address, for change) 1976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac (second script with its length at start) 00000000 (locktime)
最終結果給了我簽署的原始交易
01000000017dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91010000008b483045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d2301410482052ef9560585ed62f046ee45c1b5f85448bcf1bd5ce36a7d35eb00c8a146c14bf99223907f9a8688e6f84b54fd747a637bb82f02e296203e735e7a6b40059fffffffff02496ff502000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac0046c323000000001976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac00000000
但是現在,當我嘗試通過 Web 服務在 testnet 網路上發送簽名的原始交易時,每次都會出錯。sandbox.smartbit.com.au/txs/pushtx 回复我
"PUSH TRANSACTION ERROR: 16: MANDATORY-SCRIPT-VERIFY-FLAG-FAILED (SCRIPT EVALUATED WITHOUT ERROR BUT FINISHED WITH A FALSE/EMPTY TOP STACK ELEMENT)"
live.blockcypher.com/btc-testnet/pushtx/ 還給我
"Error sending transaction: Error running script for input 0 referencing 912a2c3d84c8572b39c173b2bcde950cfe4ae07756bac189ace98f198d5ccb7d at 1: Script was NOT verified successfully.."
與 tbtc.blockr.io/tx/push 相同
我遠未掌握比特幣或 c#,我正在學習(並且想了解它是如何工作的)。有人看到我的錯誤在哪裡嗎?謝謝
您生成的簽名是正確的,但是對於錯誤的“消息”,這是我能找到的唯一錯誤。這是你簽署的:
f64b6480a2888596636d4995153e990ce95582a1308c9c568d2698e6dc1f7893
這是錯誤的(因為您反轉了 has 結果)。相反,您應該對從您
SHA256(SHA256(<bytes>))
的簽名函式獲得的實際結果進行簽名,這意味著:93781fdce698268d569c8c30a18255e90c993e1595496d63968588a280644bf6
有幾個地方我們反轉雜湊結果,這不是其中之一。在這裡,您只是對序列化交易進行雜湊處理,以將其大小從任意長度轉換為固定的 32 字節大小,以便您可以使用 ECDSA 方案對其進行簽名。
直接使用 BouncyCastle 或任何為密碼學設計的類似庫通常不是為比特幣設計的,還有一個可能的問題,它們返回的簽名可能具有大於 curve的
s
值(簽名中的第二個) 。在這種情況下,您必須通過計算將其更改為。BigInteger``N/2``s'``s' = N - s
為什麼不使用NBitcoin庫創建原始交易並將其發佈到 blockr.io 或您正在使用的任何 API 提供商?NBitcoin 是 C# 加密貨幣開發人員的絕佳庫。