static TapBranch GetBranchData(ErrorHandle handle, TreeHandle treeHandle)
        {
            TapBranch branch = new TapBranch();
            var       ret    = NativeMethods.CfdGetTapBranchCount(
                handle.GetHandle(), treeHandle.GetHandle(), out uint count);

            if (ret != CfdErrorCode.Success)
            {
                handle.ThrowError(ret);
            }
            TapBranch[] branchList = new TapBranch[count];
            ret = NativeMethods.CfdGetBaseTapLeaf(handle.GetHandle(),
                                                  treeHandle.GetHandle(), out byte leafVersion,
                                                  out IntPtr tapscript, out IntPtr tapLeafHash);
            if (ret != CfdErrorCode.Success)
            {
                handle.ThrowError(ret);
            }
            string tapscriptStr   = CCommon.ConvertToString(tapscript);
            string tapLeafHashStr = CCommon.ConvertToString(tapLeafHash);

            if (count == 0)
            {
                branch.topHash = new ByteData256(tapLeafHashStr);
            }
            branch.branches = branchList;
            if (tapscriptStr.Length != 0)
            {
                branch.tapscript   = new Script(tapscriptStr);
                branch.leafVersion = leafVersion;
                branch.targetNodes = new ByteData256[count];
            }
            branch.UpdateBranchData(handle, treeHandle);
            return(branch);
        }
 /// <summary>
 /// Add branch.
 /// </summary>
 /// <param name="branch">tapbranch</param>
 public void AddBranch(TapBranch branch)
 {
     if (branch is null)
     {
         throw new ArgumentNullException(nameof(branch));
     }
     AddBranch(branch.treeString);
 }
Exemple #3
0
 public CfdDescriptorScriptData(CfdDescriptorScriptType scriptType, uint depth,
                                CfdHashType hashType, Address address, Script redeemScript)
 {
     ScriptType         = scriptType;
     Depth              = depth;
     HashType           = hashType;
     Address            = address;
     RedeemScript       = redeemScript;
     KeyData            = new CfdKeyData();
     MultisigKeyList    = new ArraySegment <CfdKeyData>();
     MultisigRequireNum = 0;
     ScriptTree         = new TapBranch();
 }
Exemple #4
0
 public CfdDescriptorScriptData(CfdDescriptorScriptType scriptType, uint depth,
                                Script redeemScript)
 {
     ScriptType         = scriptType;
     Depth              = depth;
     HashType           = CfdHashType.P2sh;
     Address            = new Address();
     RedeemScript       = redeemScript;
     KeyData            = new CfdKeyData();
     MultisigKeyList    = new ArraySegment <CfdKeyData>();
     MultisigRequireNum = 0;
     ScriptTree         = new TaprootScriptTree();
 }
Exemple #5
0
 public CfdDescriptorScriptData(CfdDescriptorScriptType scriptType, uint depth,
                                CfdHashType hashType, Address address, Script redeemScript,
                                TapBranch scriptTree,
                                CfdKeyData keyData, CfdKeyData[] multisigKeyList, uint multisigRequireNum)
 {
     ScriptType         = scriptType;
     Depth              = depth;
     HashType           = hashType;
     Address            = address;
     RedeemScript       = redeemScript;
     KeyData            = keyData;
     ScriptTree         = scriptTree;
     MultisigKeyList    = new ArraySegment <CfdKeyData>(multisigKeyList);
     MultisigRequireNum = multisigRequireNum;
 }
        void UpdateAllData(ErrorHandle handle, TreeHandle treeHandle)
        {
            var ret = NativeMethods.CfdGetTapBranchCount(
                handle.GetHandle(), treeHandle.GetHandle(), out uint count);

            if (ret != CfdErrorCode.Success)
            {
                handle.ThrowError(ret);
            }
            TapBranch[] branchList = new TapBranch[count];
            var         offset     = branches.Length;

            for (var index = offset; index < count; ++index)
            {
                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)
            {
                var newTargetNodes = new ByteData256[count];
                for (var index = 0; index < offset; ++index)
                {
                    branchList[index]     = branches[index];
                    newTargetNodes[index] = targetNodes[index];
                }
                for (var index = offset; index < count; ++index)
                {
                    newTargetNodes[index] = branchList[index].topHash;
                }
                branches    = branchList;
                targetNodes = newTargetNodes;
            }
            UpdateBranchData(handle, treeHandle);
        }
        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;
            }
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="origin">source branch.</param>
        public TaprootScriptTree(TapBranch origin)
        {
            if (origin is null)
            {
                throw new ArgumentNullException(nameof(origin));
            }
            var script = new Script();

            if (origin.HasTapScript())
            {
                script = origin.GetTapScript();
            }
            Initialize(origin.ToString(), script, origin.GetTargetNodes());
            internalPubkey = new SchnorrPubkey();

            using (var handle = new ErrorHandle())
                using (var treeHandle = new TreeHandle(handle))
                {
                    Load(handle, treeHandle);
                    GetAllData(handle, treeHandle);
                }
        }
Exemple #9
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);
            }
        }