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); }
internal void Load(ErrorHandle handle, TreeHandle treeHandle) { if (handle is null) { throw new ArgumentNullException(nameof(handle)); } if (treeHandle is null) { throw new ArgumentNullException(nameof(treeHandle)); } string nodes = ""; foreach (var node in targetNodes) { nodes += node.ToHexString(); } var ret = NativeMethods.CfdSetScriptTreeFromString(handle.GetHandle(), treeHandle.GetHandle(), treeString, tapscript.ToHexString(), leafVersion, nodes); if (ret != CfdErrorCode.Success) { handle.ThrowError(ret); } }
/// <summary> /// Get taproot data. /// </summary> /// <param name="internalPubkey">internal pubkey</param> /// <returns>taproot data</returns> public TaprootScriptData GetTaprootData(SchnorrPubkey internalPubkey) { if (internalPubkey is null) { throw new ArgumentNullException(nameof(internalPubkey)); } using (var handle = new ErrorHandle()) using (var treeHandle = new TreeHandle(handle)) { Load(handle, treeHandle); var ret = NativeMethods.CfdGetTaprootScriptTreeHash( handle.GetHandle(), treeHandle.GetHandle(), internalPubkey.ToHexString(), out IntPtr witnessProgram, out IntPtr tapLeafHashPtr, out IntPtr controlBlockStr); if (ret != CfdErrorCode.Success) { handle.ThrowError(ret); } var witnessProgramStr = CCommon.ConvertToString(witnessProgram); var tapLeafHash = CCommon.ConvertToString(tapLeafHashPtr); var controlBlock = CCommon.ConvertToString(controlBlockStr); return(new TaprootScriptData( new SchnorrPubkey(witnessProgramStr), new ByteData(controlBlock), new ByteData256(tapLeafHash), GetTapScript())); } }
/// <summary> /// Constructor. /// </summary> /// <param name="controlBlock">control block</param> /// <param name="tapscript">tapscript</param> public TaprootScriptTree(ByteData controlBlock, Script tapscript) { if (controlBlock is null) { throw new ArgumentNullException(nameof(controlBlock)); } if (tapscript is null) { throw new ArgumentNullException(nameof(tapscript)); } using (var handle = new ErrorHandle()) using (var treeHandle = new TreeHandle(handle)) { var ret = NativeMethods.CfdSetTapScriptByWitnessStack(handle.GetHandle(), treeHandle.GetHandle(), controlBlock.ToHexString(), tapscript.ToHexString(), out IntPtr internalPubkeyPtr); if (ret != CfdErrorCode.Success) { handle.ThrowError(ret); } internalPubkey = new SchnorrPubkey(CCommon.ConvertToString(internalPubkeyPtr)); GetAllData(handle, treeHandle); } }
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); }
void UpdateBranchData(ErrorHandle handle, TreeHandle treeHandle) { if (handle is null) { throw new ArgumentNullException(nameof(handle)); } if (treeHandle is null) { throw new ArgumentNullException(nameof(treeHandle)); } var ret = NativeMethods.CfdGetTaprootScriptTreeSrting(handle.GetHandle(), treeHandle.GetHandle(), out IntPtr treeString); if (ret != CfdErrorCode.Success) { handle.ThrowError(ret); } this.treeString = CCommon.ConvertToString(treeString); if (branches.Length != 0) { var index = branches.Length - 1; ret = NativeMethods.CfdGetTapBranchData(handle.GetHandle(), treeHandle.GetHandle(), (byte)index, true, out IntPtr branchHash, out _, out IntPtr tempScript, out byte _); if (ret != CfdErrorCode.Success) { handle.ThrowError(ret); } CCommon.ConvertToString(tempScript); topHash = new ByteData256(CCommon.ConvertToString(branchHash)); } else if (topHash.IsEmpty()) { ret = NativeMethods.CfdGetBaseTapLeaf(handle.GetHandle(), treeHandle.GetHandle(), out byte _, out IntPtr tapscript, out IntPtr tapLeafHash); if (ret != CfdErrorCode.Success) { handle.ThrowError(ret); } CCommon.ConvertToString(tapscript); string tapLeafHashStr = CCommon.ConvertToString(tapLeafHash); topHash = new ByteData256(tapLeafHashStr); } }
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> /// 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); } }
/// <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)); } }