示例#1
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="privkey">privkey(wif or hex)</param>
 public Privkey(string privkey)
 {
     if (privkey is null)
     {
         throw new ArgumentNullException(nameof(privkey));
     }
     if (string.IsNullOrEmpty(privkey))
     {
         this.privkey = "";
         privkeyWif   = "";
         isCompressed = true;
     }
     else if (privkey.Length == Size * 2)
     {
         // hex
         this.privkey = privkey;
         networkType  = CfdNetworkType.Mainnet;
         privkeyWif   = "";
         isCompressed = true;
     }
     else
     {
         // wif
         privkeyWif = privkey;
         using (var handle = new ErrorHandle())
         {
             CfdErrorCode ret;
             ret = NativeMethods.CfdParsePrivkeyWif(
                 handle.GetHandle(), privkeyWif,
                 out IntPtr tempPrivkeyHex,
                 out int tempNetworkType,
                 out isCompressed);
             if (ret != CfdErrorCode.Success)
             {
                 handle.ThrowError(ret);
             }
             this.privkey = CCommon.ConvertToString(tempPrivkeyHex);
             networkType  = (CfdNetworkType)tempNetworkType;
         }
     }
 }
示例#2
0
        internal void GetAllData(ErrorHandle handle, TreeHandle treeHandle)
        {
            var tree  = GetBranchData(handle, treeHandle);
            var count = tree.branches.Length;

            TapBranch[]   branchList = new TapBranch[count];
            ByteData256[] nodeList   = new ByteData256[count];
            for (var index = 0; index < count; ++index)
            {
                var ret = NativeMethods.CfdGetTapBranchHandle(
                    handle.GetHandle(), treeHandle.GetHandle(), (byte)index,
                    out IntPtr branchHash, out IntPtr branchTreeHandle);
                if (ret != CfdErrorCode.Success)
                {
                    handle.ThrowError(ret);
                }
                CCommon.ConvertToString(branchHash);
                using (var branchHandle = new TreeHandle(handle, branchTreeHandle))
                {
                    TapBranch branch = new TapBranch();
                    branch.GetAllData(handle, branchHandle);
                    branchList[index] = branch;
                }
            }
            if (count != 0)
            {
                branches = branchList;
            }
            topHash    = tree.topHash;
            treeString = tree.treeString;
            if (!tree.tapscript.IsEmpty())
            {
                tapscript   = tree.tapscript;
                leafVersion = tree.leafVersion;
                for (var index = 0; index < count; ++index)
                {
                    nodeList[index] = branchList[index].topHash;
                }
                targetNodes = nodeList;
            }
        }
示例#3
0
 /// <summary>
 /// get pubkey.
 /// </summary>
 /// <returns>pubkey</returns>
 public Pubkey GetPubkey()
 {
     if (privkeyWif.Length == 0)
     {
         return(GetPubkey(true));
     }
     else
     {
         using (var handle = new ErrorHandle())
         {
             var ret = NativeMethods.CfdGetPubkeyFromPrivkey(
                 handle.GetHandle(), privkey, privkeyWif, isCompressed,
                 out IntPtr pubkeyHex);
             if (ret != CfdErrorCode.Success)
             {
                 handle.ThrowError(ret);
             }
             return(new Pubkey(CCommon.ConvertToString(pubkeyHex)));
         }
     }
 }
示例#4
0
 /// <summary>
 /// Get address from locking script.
 /// </summary>
 /// <param name="inputLockingScript">locking script</param>
 /// <param name="network">network type</param>
 /// <returns>address object</returns>
 public static Address GetAddressByLockingScript(Script inputLockingScript, CfdNetworkType network)
 {
     if (inputLockingScript is null)
     {
         throw new ArgumentNullException(nameof(inputLockingScript));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdGetAddressFromLockingScript(
             handle.GetHandle(),
             inputLockingScript.ToHexString(),
             (int)network,
             out IntPtr outputAddress);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         string tempAddress = CCommon.ConvertToString(outputAddress);
         return(new Address(tempAddress));
     }
 }
 static string[] Verify(string signature)
 {
     using (var handle = new ErrorHandle())
     {
         if (signature.Length == AddedSigHashTypeSize * 2)
         {
             signature = signature.Substring(0, (int)(Size * 2));
         }
         var ret = NativeMethods.CfdSplitSchnorrSignature(
             handle.GetHandle(), signature,
             out IntPtr schnorrNonce,
             out IntPtr privkey);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         string nonceStr = CCommon.ConvertToString(schnorrNonce);
         string keyStr   = CCommon.ConvertToString(privkey);
         return(new string[] { nonceStr, keyStr });
     }
 }
        /// <summary>
        /// Get tweaked privkey from internal privkey.
        /// </summary>
        /// <param name="privkey">internal privkey.</param>
        /// <returns>tweaked privkey.</returns>
        public Privkey GetTweakedPrivkey(Privkey privkey)
        {
            if (privkey is null)
            {
                throw new ArgumentNullException(nameof(privkey));
            }
            using (var handle = new ErrorHandle())
                using (var treeHandle = new TreeHandle(handle))
                {
                    Load(handle, treeHandle);
                    var ret = NativeMethods.CfdGetTaprootTweakedPrivkey(
                        handle.GetHandle(), treeHandle.GetHandle(), privkey.ToHexString(),
                        out IntPtr tweakedPrivkey);
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }
                    var tweakedPrivkeyStr = CCommon.ConvertToString(tweakedPrivkey);

                    return(new Privkey(tweakedPrivkeyStr));
                }
        }
示例#7
0
 /// <summary>
 /// Add branches.
 /// </summary>
 /// <param name="treeStringList">tree string list</param>
 public void AddBranches(string[] treeStringList)
 {
     if (treeStringList is null)
     {
         throw new ArgumentNullException(nameof(treeStringList));
     }
     using (var handle = new ErrorHandle())
         using (var treeHandle = new TreeHandle(handle))
         {
             Load(handle, treeHandle);
             foreach (var treeStr in treeStringList)
             {
                 var ret = NativeMethods.CfdAddTapBranchByScriptTreeString(
                     handle.GetHandle(), treeHandle.GetHandle(), treeStr);
                 if (ret != CfdErrorCode.Success)
                 {
                     handle.ThrowError(ret);
                 }
             }
             UpdateAllData(handle, treeHandle);
         }
 }
示例#8
0
 /// <summary>
 /// Exist txid in block.
 /// </summary>
 /// <param name="txid">txid</param>
 /// <returns>true is exist txid.</returns>
 public bool ExistTxid(Txid txid)
 {
     if (txid is null)
     {
         throw new ArgumentNullException(nameof(txid));
     }
     using (var handle = new ErrorHandle())
         using (var txHandle = new BlockHandle(handle, defaultNetType, hex))
         {
             var ret = NativeMethods.CfdExistTxidInBlock(
                 handle.GetHandle(), txHandle.GetHandle(), txid.ToHexString());
             if (ret == CfdErrorCode.Success)
             {
                 return(true);
             }
             else if (ret != CfdErrorCode.NotFound)
             {
                 handle.ThrowError(ret);
             }
             return(false);
         }
 }
示例#9
0
        private void Initialize(ErrorHandle handle, string addressString, out CfdNetworkType outputNetwork,
                                out CfdWitnessVersion outputWitnessVersion, out string outputLockingScript, out string outputHash)
        {
            var ret = NativeMethods.CfdGetAddressInfo(
                handle.GetHandle(),
                addressString,
                out int networkType,
                out int hashType,
                out int segwitVersion,
                out IntPtr lockingScript,
                out IntPtr hashString);

            if (ret != CfdErrorCode.Success)
            {
                handle.ThrowError(ret);
            }
            outputNetwork        = (CfdNetworkType)networkType;
            addressType          = (CfdAddressType)hashType;
            outputWitnessVersion = (CfdWitnessVersion)segwitVersion;
            outputLockingScript  = CCommon.ConvertToString(lockingScript);
            outputHash           = CCommon.ConvertToString(hashString);
        }
示例#10
0
 /// <summary>
 /// constructor.
 /// </summary>
 /// <param name="seed">seed bytes</param>
 /// <param name="networkType">network type</param>
 public ExtPrivkey(ByteData seed, CfdNetworkType networkType)
 {
     if (seed is null)
     {
         throw new ArgumentNullException(nameof(seed));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdCreateExtkeyFromSeed(
             handle.GetHandle(), seed.ToHexString(), (int)networkType,
             (int)CfdExtKeyType.Privkey, out IntPtr tempExtkey);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         extkey = CCommon.ConvertToString(tempExtkey);
         GetExtkeyInformation(handle, extkey,
                              out version, out fingerprint,
                              out chainCode, out depth, out childNumber, out _);
         privkey          = GetPrivkeyFromExtKey(handle, extkey, networkType);
         this.networkType = networkType;
     }
 }
示例#11
0
 /// <summary>
 /// Calculate ec-signature.
 /// </summary>
 /// <param name="sighash">signature hash.</param>
 /// <param name="hasGrindR">use grind-R.</param>
 /// <returns></returns>
 public SignParameter CalculateEcSignature(ByteData sighash, bool hasGrindR)
 {
     if (sighash is null)
     {
         throw new ArgumentNullException(nameof(sighash));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdCalculateEcSignature(
             handle.GetHandle(), sighash.ToHexString(),
             privkey, privkeyWif, (int)networkType, hasGrindR,
             out IntPtr signatureHex);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         SignParameter     signature   = new SignParameter(CCommon.ConvertToString(signatureHex));
         SignatureHashType sighashType = new SignatureHashType(CfdSighashType.All, false);
         signature.SetDerEncode(sighashType);
         signature.SetRelatedPubkey(GetPubkey());
         return(signature);
     }
 }
示例#12
0
        private static void GetExtkeyInformation(ErrorHandle handle, string extkey,
                                                 out ByteData version, out ByteData fingerprint, out ByteData chainCode,
                                                 out uint depth, out uint childNumber, out CfdNetworkType networkType)
        {
            var ret = NativeMethods.CfdGetExtkeyInformation(
                handle.GetHandle(), extkey,
                out IntPtr tempVersion,
                out IntPtr tempFingerprint,
                out IntPtr tempChainCode,
                out depth,
                out childNumber);

            if (ret != CfdErrorCode.Success)
            {
                handle.ThrowError(ret);
            }
            string workVersion     = CCommon.ConvertToString(tempVersion);
            string workFingerprint = CCommon.ConvertToString(tempFingerprint);
            string workChainCode   = CCommon.ConvertToString(tempChainCode);

            version     = new ByteData(workVersion);
            fingerprint = new ByteData(workFingerprint);
            chainCode   = new ByteData(workChainCode);
            if (VersionMainnet == version.ToHexString())
            {
                networkType = CfdNetworkType.Mainnet;
            }
            else
            {
                networkType = CfdNetworkType.Testnet;
                if (VersionTestnet != version.ToHexString())
                {
                    CfdCommon.ThrowError(CfdErrorCode.IllegalArgumentError,
                                         "Failed to version format.");
                }
            }
        }
示例#13
0
 /// <summary>
 /// decode from DER.
 /// </summary>
 /// <param name="derSignature">DER encoded data</param>
 /// <returns>signature (SignParameter object)</returns>
 public static SignParameter DecodeFromDer(ByteData derSignature)
 {
     if (derSignature is null)
     {
         throw new ArgumentNullException(nameof(derSignature));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdDecodeSignatureFromDer(
             handle.GetHandle(), derSignature.ToHexString(),
             out IntPtr signature,
             out int signatureHashType,
             out bool _);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         string            signatureStr = CCommon.ConvertToString(signature);
         SignatureHashType sighashType  = new SignatureHashType(signatureHashType);
         SignParameter     signParam    = new SignParameter(signatureStr);
         signParam.SetDerEncode(sighashType);
         return(signParam);
     }
 }
示例#14
0
 /// <summary>
 /// constructor.
 /// </summary>
 /// <param name="address">address</param>
 /// <param name="confidentialKey">confidential key</param>
 public ConfidentialAddress(Address address, Pubkey confidentialKey)
 {
     if (address is null)
     {
         throw new ArgumentNullException(nameof(address));
     }
     if (confidentialKey is null)
     {
         throw new ArgumentNullException(nameof(confidentialKey));
     }
     unconfidenialAddress = address;
     key = confidentialKey;
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdCreateConfidentialAddress(
             handle.GetHandle(), address.ToAddressString(), confidentialKey.ToHexString(),
             out IntPtr outputConfidentialAddr);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         confidentialAddress = CCommon.ConvertToString(outputConfidentialAddr);
     }
 }
示例#15
0
        /// <summary>
        /// create script from asm string list.
        /// </summary>
        /// <param name="asmList">asm string list</param>
        /// <returns>script object</returns>
        public static Script CreateFromAsm(string[] asmList)
        {
            if (asmList is null)
            {
                throw new ArgumentNullException(nameof(asmList));
            }
            using (var handle = new ErrorHandle())
            {
                StringBuilder builder = new StringBuilder();
                foreach (string asm in asmList)
                {
#pragma warning disable IDE0059 // Unnecessary value assignment
                    IntPtr hexString = IntPtr.Zero;
#pragma warning restore IDE0059 // Unnecessary value assignment
                    var ret = NativeMethods.CfdConvertScriptAsmToHex(handle.GetHandle(), asm, out hexString);
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }
                    builder.Append(CCommon.ConvertToString(hexString));
                }
                return(new Script(builder.ToString()));
            }
        }
 /// <summary>
 /// Adapt ECDSA-adaptor signature.
 /// </summary>
 /// <param name="adaptorSignature">adaptor signature</param>
 /// <param name="adaptorSecret">adaptor secret key</param>
 /// <returns>ecdsa signature in compact format</returns>
 public static ByteData Adapt(ByteData adaptorSignature, Privkey adaptorSecret)
 {
     if (adaptorSignature is null)
     {
         throw new ArgumentNullException(nameof(adaptorSignature));
     }
     if (adaptorSecret is null)
     {
         throw new ArgumentNullException(nameof(adaptorSecret));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdAdaptEcdsaAdaptor(
             handle.GetHandle(), adaptorSignature.ToHexString(),
             adaptorSecret.ToHexString(),
             out IntPtr signature);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         string sig = CCommon.ConvertToString(signature);
         return(new ByteData(sig));
     }
 }
示例#17
0
 /// <summary>
 /// convert entropy to mnemonic.
 /// </summary>
 /// <param name="entropy">entropy</param>
 /// <param name="language">language</param>
 /// <returns>mnemonic words</returns>
 public static string[] ConvertEntropyToMnemonic(
     ByteData entropy, string language)
 {
     if (entropy is null)
     {
         throw new ArgumentNullException(nameof(entropy));
     }
     if (language is null)
     {
         throw new ArgumentNullException(nameof(language));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdConvertEntropyToMnemonic(handle.GetHandle(),
                                                             entropy.ToHexString(),
                                                             language, out IntPtr tempMnemonic);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         string mnemonic = CCommon.ConvertToString(tempMnemonic);
         return(mnemonic.Split(' '));
     }
 }
示例#18
0
 public ExtPubkey(CfdNetworkType networkType, ByteData fingerprint,
                  Pubkey pubkey, ByteData chainCode, uint depth, uint childNumber)
 {
     if (fingerprint is null)
     {
         throw new ArgumentNullException(nameof(fingerprint));
     }
     if (pubkey is null)
     {
         throw new ArgumentNullException(nameof(pubkey));
     }
     if (chainCode is null)
     {
         throw new ArgumentNullException(nameof(chainCode));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdCreateExtkey(
             handle.GetHandle(), (int)networkType, (int)CfdExtKeyType.Pubkey, "",
             fingerprint.ToHexString(), pubkey.ToHexString(), chainCode.ToHexString(),
             (byte)depth, childNumber, out IntPtr tempExtkey);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         extkey           = CCommon.ConvertToString(tempExtkey);
         this.networkType = networkType;
         this.fingerprint = fingerprint;
         this.pubkey      = pubkey;
         this.chainCode   = chainCode;
         this.depth       = depth;
         this.childNumber = childNumber;
         GetExtkeyInformation(handle, extkey, out version, out _,
                              out _, out _, out _, out _);
     }
 }
示例#19
0
        /// <summary>
        /// Select coins.
        /// </summary>
        /// <param name="utxoList">utxo list</param>
        /// <param name="txFeeAmount">transaction fee</param>
        /// <param name="targetAmount">target amount of asset. Amount more than the specified amount is set in txout. default is 0 (disable).</param>
        /// <param name="effectiveFeeRate">fee rate</param>
        /// <param name="longTermFeeRate">long-term fee rate</param>
        /// <param name="dustFeeRate">dust fee rate</param>
        /// <param name="knapsackMinChange">knapsack min change value. knapsack logic's threshold. Recommended value is 1.</param>
        /// <returns>select utxo list.</returns>
        public UtxoData[] SelectCoins(UtxoData[] utxoList, long txFeeAmount, long targetAmount,
                                      double effectiveFeeRate, double longTermFeeRate, double dustFeeRate, long knapsackMinChange)
        {
            if (utxoList is null)
            {
                throw new ArgumentNullException(nameof(utxoList));
            }
            if (utxoList.Length <= 0)
            {
                throw new InvalidOperationException("utxoList is empty.");
            }
            using (var handle = new ErrorHandle())
            {
                var ret = NativeMethods.CfdInitializeCoinSelection(
                    handle.GetHandle(), (uint)utxoList.Length, 1, "", txFeeAmount,
                    effectiveFeeRate, longTermFeeRate, dustFeeRate, knapsackMinChange,
                    out IntPtr coinSelectHandle);
                if (ret != CfdErrorCode.Success)
                {
                    handle.ThrowError(ret);
                }
                try
                {
                    for (uint index = 0; index < utxoList.Length; ++index)
                    {
                        string desc = (utxoList[index].GetDescriptor() is null) ?
                                      "" : utxoList[index].GetDescriptor().ToString();
                        ret = NativeMethods.CfdAddCoinSelectionUtxoTemplate(
                            handle.GetHandle(), coinSelectHandle, index,
                            utxoList[index].GetOutPoint().GetTxid().ToHexString(),
                            utxoList[index].GetOutPoint().GetVout(),
                            utxoList[index].GetAmount(), "",
                            desc, utxoList[index].GetScriptSigTemplate().ToHexString());
                        if (ret != CfdErrorCode.Success)
                        {
                            handle.ThrowError(ret);
                        }
                    }
                    ret = NativeMethods.CfdAddCoinSelectionAmount(
                        handle.GetHandle(), coinSelectHandle, 0, targetAmount, "");
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }

                    ret = NativeMethods.CfdFinalizeCoinSelection(
                        handle.GetHandle(), coinSelectHandle, out long utxoFeeAmount);
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }

                    uint[] collectIndexes = new uint[utxoList.Length];
                    uint   collectCount   = 0;
                    if ((utxoFeeAmount > 0) || (targetAmount > 0))
                    {
                        for (uint index = 0; index < utxoList.Length; ++index)
                        {
                            ret = NativeMethods.CfdGetSelectedCoinIndex(
                                handle.GetHandle(), coinSelectHandle,
                                index, out int utxoIndex);
                            if (ret != CfdErrorCode.Success)
                            {
                                handle.ThrowError(ret);
                            }
                            if (utxoIndex < 0)
                            {
                                break;
                            }
                            if (utxoList.Length <= utxoIndex)
                            {
                                throw new InvalidProgramException("utxoIndex maximum over.");
                            }
                            ++collectCount;
                            collectIndexes[index] = (uint)utxoIndex;
                        }
                    }

                    /*
                     * ret = NativeMethods.CfdGetSelectedCoinAssetAmount(
                     * handle.GetHandle(), coinSelectHandle, 0, out long collectAmount);
                     * if (ret != CfdErrorCode.Success)
                     * {
                     * handle.ThrowError(ret);
                     * }
                     */

                    UtxoData[] selectedUtxoList = new UtxoData[collectCount];
                    for (uint index = 0; index < collectCount; ++index)
                    {
                        selectedUtxoList[index] = utxoList[collectIndexes[index]];
                    }
                    lastSelectedUtxoFee = utxoFeeAmount;
                    return(selectedUtxoList);
                }
                finally
                {
                    NativeMethods.CfdFreeCoinSelectionHandle(handle.GetHandle(), coinSelectHandle);
                }
            }
        }
示例#20
0
        /// <summary>
        /// Select coins for elements.
        /// </summary>
        /// <param name="utxoList">utxo list</param>
        /// <param name="targetAssetAmountMap">target amount of asset. Amount more than the specified amount is set in txout. default is 0 (disable).</param>
        /// <param name="feeAsset">asset by fee</param>
        /// <param name="txFeeAmount">transaction fee</param>
        /// <param name="effectiveFeeRate">fee rate</param>
        /// <param name="exponent">blinding exponent</param>
        /// <param name="minimumBits">blinding minimum bits</param>
        /// <param name="longTermFeeRate">long-term fee rate</param>
        /// <param name="dustFeeRate">dust fee rate</param>
        /// <param name="knapsackMinChange">knapsack min change value. knapsack logic's threshold. Recommended value is 1.</param>
        /// <returns>select utxo list.</returns>
        public ElementsUtxoData[] SelectCoinsForElements(
            ElementsUtxoData[] utxoList,
            IDictionary <ConfidentialAsset, long> targetAssetAmountMap,
            ConfidentialAsset feeAsset, long txFeeAmount,
            double effectiveFeeRate, int exponent, int minimumBits,
            double longTermFeeRate,
            double dustFeeRate, long knapsackMinChange)
        {
            if (utxoList is null)
            {
                throw new ArgumentNullException(nameof(utxoList));
            }
            if (utxoList.Length <= 0)
            {
                throw new InvalidOperationException("utxoList is empty.");
            }
            if (targetAssetAmountMap is null)
            {
                throw new ArgumentNullException(nameof(targetAssetAmountMap));
            }
            if (targetAssetAmountMap.Count <= 0)
            {
                throw new InvalidOperationException("targetAssetAmountMap is empty.");
            }
            if (feeAsset is null)
            {
                throw new ArgumentNullException(nameof(feeAsset));
            }
            if (feeAsset.HasBlinding())
            {
                throw new InvalidOperationException(
                          "fee asset has blinding. fee asset is unblind only.");
            }
            using (var handle = new ErrorHandle())
            {
                var ret = NativeMethods.CfdInitializeCoinSelection(
                    handle.GetHandle(), (uint)utxoList.Length, (uint)targetAssetAmountMap.Count,
                    feeAsset.ToHexString(), txFeeAmount,
                    effectiveFeeRate, longTermFeeRate, dustFeeRate, knapsackMinChange,
                    out IntPtr coinSelectHandle);
                if (ret != CfdErrorCode.Success)
                {
                    handle.ThrowError(ret);
                }
                try
                {
                    for (uint index = 0; index < utxoList.Length; ++index)
                    {
                        string desc = (utxoList[index].GetDescriptor() is null) ?
                                      "" : utxoList[index].GetDescriptor().ToString();
                        ret = NativeMethods.CfdAddCoinSelectionUtxoTemplate(
                            handle.GetHandle(), coinSelectHandle, index,
                            utxoList[index].GetOutPoint().GetTxid().ToHexString(),
                            utxoList[index].GetOutPoint().GetVout(),
                            utxoList[index].GetAmount(),
                            utxoList[index].GetAsset(),
                            desc, utxoList[index].GetScriptSigTemplate().ToHexString());
                        if (ret != CfdErrorCode.Success)
                        {
                            handle.ThrowError(ret);
                        }
                    }
                    long targetAmountAll = 0;
                    uint assetIndex      = 0;
                    foreach (var key in targetAssetAmountMap.Keys)
                    {
                        ret = NativeMethods.CfdAddCoinSelectionAmount(
                            handle.GetHandle(), coinSelectHandle, assetIndex,
                            targetAssetAmountMap[key], key.ToHexString());
                        if (ret != CfdErrorCode.Success)
                        {
                            handle.ThrowError(ret);
                        }
                        ++assetIndex;
                        targetAmountAll += targetAssetAmountMap[key];
                    }

                    if (exponent >= -1)
                    {
                        ret = NativeMethods.CfdSetOptionCoinSelection(handle.GetHandle(), coinSelectHandle,
                                                                      Exponent, exponent, 0, false);
                        if (ret != CfdErrorCode.Success)
                        {
                            handle.ThrowError(ret);
                        }
                    }
                    if (minimumBits >= 0)
                    {
                        ret = NativeMethods.CfdSetOptionCoinSelection(handle.GetHandle(), coinSelectHandle,
                                                                      MinimumBits, minimumBits, 0, false);
                        if (ret != CfdErrorCode.Success)
                        {
                            handle.ThrowError(ret);
                        }
                    }

                    ret = NativeMethods.CfdFinalizeCoinSelection(
                        handle.GetHandle(), coinSelectHandle, out long utxoFeeAmount);
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }

                    uint[] collectIndexes = new uint[utxoList.Length];
                    uint   collectCount   = 0;
                    if ((utxoFeeAmount > 0) || (targetAmountAll > 0))
                    {
                        for (uint index = 0; index < utxoList.Length; ++index)
                        {
                            ret = NativeMethods.CfdGetSelectedCoinIndex(
                                handle.GetHandle(), coinSelectHandle,
                                index, out int utxoIndex);
                            if (ret != CfdErrorCode.Success)
                            {
                                handle.ThrowError(ret);
                            }
                            if (utxoIndex < 0)
                            {
                                break;
                            }
                            if (utxoList.Length <= utxoIndex)
                            {
                                throw new InvalidProgramException("utxoIndex maximum over.");
                            }
                            ++collectCount;
                            collectIndexes[index] = (uint)utxoIndex;
                        }
                    }

                    /*
                     * assetIndex = 0;
                     * collectAmountList = new Dictionary<ConfidentialAsset, long>();
                     * foreach (var key in targetAssetAmountMap.Keys)
                     * {
                     * ret = NativeMethods.CfdGetSelectedCoinAssetAmount(
                     *  handle.GetHandle(), coinSelectHandle, assetIndex,
                     *  out long collectAmount);
                     * if (ret != CfdErrorCode.Success)
                     * {
                     *  handle.ThrowError(ret);
                     * }
                     ++assetIndex;
                     * collectAmountList.Add(key, collectAmount);
                     * }
                     */

                    ElementsUtxoData[] selectedUtxoList = new ElementsUtxoData[collectCount];
                    for (uint index = 0; index < collectCount; ++index)
                    {
                        selectedUtxoList[index] = utxoList[collectIndexes[index]];
                    }
                    lastSelectedUtxoFee = utxoFeeAmount;
                    return(selectedUtxoList);
                }
                finally
                {
                    NativeMethods.CfdFreeCoinSelectionHandle(handle.GetHandle(), coinSelectHandle);
                }
            }
        }
示例#21
0
        private static CfdDescriptorScriptData[] ParseDescriptor(
            ErrorHandle handle, string descriptorString,
            string derivePath, CfdNetworkType network, out CfdDescriptorScriptData rootData)
        {
            var ret = NativeMethods.CfdParseDescriptor(
                handle.GetHandle(), descriptorString, (int)network, derivePath,
                out IntPtr descriptorHandle, out uint maxIndex);

            if (ret != CfdErrorCode.Success)
            {
                handle.ThrowError(ret);
            }
            try
            {
                bool isMultisig = false;
                uint maxKeyNum  = 0;
                uint requireNum = 0;
                {
                    ret = NativeMethods.CfdGetDescriptorRootData(
                        handle.GetHandle(), descriptorHandle,
                        out int scriptType, out IntPtr lockingScript, out IntPtr address,
                        out int hashType, out IntPtr redeemScript,
                        out int keyType, out IntPtr pubkey, out IntPtr extPubkey,
                        out IntPtr extPrivkey, out IntPtr schnorrPubkey, out IntPtr treeString,
                        out isMultisig, out maxKeyNum, out requireNum);
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }
                    CCommon.ConvertToString(lockingScript);
                    string tempAddress        = CCommon.ConvertToString(address);
                    string tempRedeemScript   = CCommon.ConvertToString(redeemScript);
                    string tempPubkey         = CCommon.ConvertToString(pubkey);
                    string tempExtPubkey      = CCommon.ConvertToString(extPubkey);
                    string tempExtPrivkey     = CCommon.ConvertToString(extPrivkey);
                    string tempSchnorr        = CCommon.ConvertToString(schnorrPubkey);
                    string tempTreeStr        = CCommon.ConvertToString(treeString);
                    CfdDescriptorKeyType type = (CfdDescriptorKeyType)keyType;
                    CfdKeyData           keyData;
                    TapBranch            scriptTree = new TapBranch();
                    if (type == CfdDescriptorKeyType.Bip32)
                    {
                        keyData = new CfdKeyData(new ExtPubkey(tempExtPubkey));
                    }
                    else if (type == CfdDescriptorKeyType.Bip32Priv)
                    {
                        keyData = new CfdKeyData(new ExtPrivkey(tempExtPrivkey));
                    }
                    else if (type == CfdDescriptorKeyType.SchnorrPubkey)
                    {
                        keyData = new CfdKeyData(new SchnorrPubkey(tempSchnorr));
                    }
                    else if (type == CfdDescriptorKeyType.Public)
                    {
                        keyData = new CfdKeyData(new Pubkey(tempPubkey));
                    }
                    else
                    {
                        keyData = new CfdKeyData();
                    }
                    Address addr = new Address();
                    if (tempAddress.Length > 0)
                    {
                        addr = new Address(tempAddress);
                    }
                    if (tempTreeStr.Length > 0)
                    {
                        scriptTree = new TapBranch(tempTreeStr);
                    }
                    rootData = new CfdDescriptorScriptData((CfdDescriptorScriptType)scriptType, 0,
                                                           (CfdHashType)hashType, addr, new Script(tempRedeemScript),
                                                           scriptTree, keyData, Array.Empty <CfdKeyData>(), 0);
                }
                CfdDescriptorScriptData[] list = new CfdDescriptorScriptData[maxIndex + 1];
                for (uint index = 0; index <= maxIndex; ++index)
                {
                    // force initialized because guard illegal memory access.
                    IntPtr lockingScript = IntPtr.Zero;
                    IntPtr redeemScript  = IntPtr.Zero;
                    IntPtr address       = IntPtr.Zero;
                    IntPtr pubkey        = IntPtr.Zero;
                    IntPtr extPubkey     = IntPtr.Zero;
                    IntPtr extPrivkey    = IntPtr.Zero;
                    ret = NativeMethods.CfdGetDescriptorData(
                        handle.GetHandle(), descriptorHandle, index, out _, out uint depth,
                        out int scriptType, out lockingScript, out address,
                        out int hashType, out redeemScript,
                        out int keyType, out pubkey, out extPubkey, out extPrivkey,
                        out isMultisig, out maxKeyNum, out requireNum);
                    if (ret != CfdErrorCode.Success)
                    {
                        handle.ThrowError(ret);
                    }
                    CCommon.ConvertToString(lockingScript);
                    string tempAddress      = CCommon.ConvertToString(address);
                    string tempRedeemScript = CCommon.ConvertToString(redeemScript);
                    string tempPubkey       = CCommon.ConvertToString(pubkey);
                    string tempExtPubkey    = CCommon.ConvertToString(extPubkey);
                    string tempExtPrivkey   = CCommon.ConvertToString(extPrivkey);
                    CfdDescriptorScriptData data;
                    CfdKeyData           keyData;
                    CfdDescriptorKeyType type;
                    switch ((CfdDescriptorScriptType)scriptType)
                    {
                    case CfdDescriptorScriptType.Combo:
                    case CfdDescriptorScriptType.Pk:
                    case CfdDescriptorScriptType.Pkh:
                    case CfdDescriptorScriptType.Wpkh:
                    case CfdDescriptorScriptType.Taproot:
                        type = (CfdDescriptorKeyType)keyType;
                        if (type == CfdDescriptorKeyType.Bip32)
                        {
                            keyData = new CfdKeyData(new ExtPubkey(tempExtPubkey));
                        }
                        else if (type == CfdDescriptorKeyType.Bip32Priv)
                        {
                            keyData = new CfdKeyData(new ExtPrivkey(tempExtPrivkey));
                        }
                        else if (type == CfdDescriptorKeyType.SchnorrPubkey)
                        {
                            keyData = new CfdKeyData(new SchnorrPubkey(tempPubkey));
                        }
                        else
                        {
                            keyData = new CfdKeyData(new Pubkey(tempPubkey));
                        }
                        data = new CfdDescriptorScriptData(
                            (CfdDescriptorScriptType)scriptType,
                            depth, (CfdHashType)hashType, new Address(tempAddress), keyData);
                        break;

                    case CfdDescriptorScriptType.Sh:
                    case CfdDescriptorScriptType.Wsh:
                    case CfdDescriptorScriptType.Multi:
                    case CfdDescriptorScriptType.SortedMulti:
                        if (isMultisig)
                        {
                            CfdKeyData[] keyList = new CfdKeyData[maxKeyNum];
                            for (uint multisigIndex = 0; multisigIndex < maxKeyNum; ++multisigIndex)
                            {
                                IntPtr multisigPubkey     = IntPtr.Zero;
                                IntPtr multisigExtPubkey  = IntPtr.Zero;
                                IntPtr multisigExtPrivkey = IntPtr.Zero;
                                ret = NativeMethods.CfdGetDescriptorMultisigKey(handle.GetHandle(), descriptorHandle,
                                                                                multisigIndex, out int multisigKeyType, out multisigPubkey,
                                                                                out multisigExtPubkey, out multisigExtPrivkey);
                                if (ret != CfdErrorCode.Success)
                                {
                                    handle.ThrowError(ret);
                                }
                                tempPubkey     = CCommon.ConvertToString(multisigPubkey);
                                tempExtPubkey  = CCommon.ConvertToString(multisigExtPubkey);
                                tempExtPrivkey = CCommon.ConvertToString(multisigExtPrivkey);
                                type           = (CfdDescriptorKeyType)multisigKeyType;
                                if (type == CfdDescriptorKeyType.Bip32)
                                {
                                    keyList[multisigIndex] = new CfdKeyData(new ExtPubkey(tempExtPubkey));
                                }
                                else if (type == CfdDescriptorKeyType.Bip32Priv)
                                {
                                    keyList[multisigIndex] = new CfdKeyData(new ExtPrivkey(tempExtPrivkey));
                                }
                                else
                                {
                                    keyList[multisigIndex] = new CfdKeyData(new Pubkey(tempPubkey));
                                }
                            }
                            data = new CfdDescriptorScriptData(
                                (CfdDescriptorScriptType)scriptType,
                                depth, (CfdHashType)hashType, new Address(tempAddress),
                                new Script(tempRedeemScript), keyList, requireNum);
                            rootData = new CfdDescriptorScriptData(rootData.ScriptType, 0,
                                                                   rootData.HashType, rootData.Address, rootData.RedeemScript,
                                                                   rootData.KeyData, keyList, requireNum);
                        }
                        else
                        {
                            data = new CfdDescriptorScriptData(
                                (CfdDescriptorScriptType)scriptType,
                                depth, (CfdHashType)hashType, new Address(tempAddress),
                                new Script(tempRedeemScript));
                        }
                        break;

                    case CfdDescriptorScriptType.Raw:
                        data = new CfdDescriptorScriptData(
                            (CfdDescriptorScriptType)scriptType,
                            depth, new Script(tempRedeemScript));
                        break;

                    case CfdDescriptorScriptType.Addr:
                        data = new CfdDescriptorScriptData(
                            (CfdDescriptorScriptType)scriptType,
                            depth, (CfdHashType)hashType, new Address(tempAddress));
                        break;

                    default:
                        data = new CfdDescriptorScriptData();
                        break;
                    }
                    list[index] = data;

                    if (scriptType == (int)CfdDescriptorScriptType.Combo)
                    {
                        // TODO: combo data is top only.
                        CfdDescriptorScriptData[] newList = { list[0] };
                        list = newList;
                        break;
                    }
                }
                return(list);
            }
            finally
            {
                NativeMethods.CfdFreeDescriptorHandle(
                    handle.GetHandle(), descriptorHandle);
            }
        }