皮皮网

【购物源码】【慧谷动力 源码】【黑白棋源码】cid技术源码_cci源码

2024-11-23 12:53:19 来源:查查源码网

1.屏幕取词
2.如何获取bilibili cid
3.谁能提供一个小区水电费管理的术源C程序代码啊~~~~~非常非常感谢~~~
4.软件开发工具
5.Estuary概览

cid技术源码_cci源码

屏幕取词

       â€œé¼ æ ‡å±å¹•å–词”技术是在电子字典中得到广泛地应用的,如四通利方和金山词霸等软件,这个技术看似简单,其实在WINDOWS系统中实现却是非常复杂的,总的来说有两种实现方式:

        第一种:采用截获对部分GDI的API调用来实现,如TextOut,TextOutA等。

        第二种:对每个设备上下文(DC)做一分Copy,并跟踪所有修改上下文(DC)的操作。

        第二种方法更强大,但兼容性不好,而第一种方法使用的截获WindowsAPI的调用,这项技术的强大可能远远超出了您的想象,毫不夸张的说,利用WindowsAPI拦截技术,你可以改造整个操作系统,事实上很多外挂式Windows中文平台就是这么实现的!而这项技术也正是这篇文章的主题。

        截WindowsAPI的调用,具体的说来也可以分为两种方法:

        第一种方法通过直接改写WinAPI 在内存中的映像,嵌入汇编代码,使之被调用时跳转到指定的地址运行来截获;第二种方法则改写IAT(Import Address Table 输入地址表),重定向WinAPI函数的调用来实现对WinAPI的截获。

        第一种方法的实现较为繁琐,而且在Win、下面更有难度,这是因为虽然微软说WIN的API只是为了兼容性才保留下来,程序员应该尽可能地调用位的API,实际上根本就不是这样!WIN 9X内部的大部分位API经过变换调用了同名的位API,也就是说我们需要在拦截的函数中嵌入位汇编代码!

        我们将要介绍的是第二种拦截方法,这种方法在Win、和NT下面运行都比较稳定,兼容性较好。由于需要用到关于Windows虚拟内存的管理、打破进程边界墙、向应用程序的进程空间中注入代码、PE(Portable Executable)文件格式和IAT(输入地址表)等较底层的知识,所以我们先对涉及到的这些知识大概地做一个介绍,最后会给出拦截部分的关键代码。

        先说Windows虚拟内存的管理。Windows9X给每一个进程分配了4GB的地址空间,对于NT来说,这个数字是2GB,系统保留了2GB到 4GB之间的地址空间禁止进程访问,而在Win9X中,2GB到4GB这部分虚拟地址空间实际上是由所有的WIN进程所共享的,这部分地址空间加载了共享Win DLL、内存映射文件和VXD、内存管理器和文件系统码,Win9X中这部分对于每一个进程都是可见的,这也是Win9X操作系统不够健壮的原因。

        Win9X中为位操作系统保留了0到4MB的地址空间,而在4MB到2GB之间也就是Win进程私有的地址空间,由于 每个进程的地址空间都是相对独立的,也就是说,如果程序想截获其它进程中的API调用,就必须打破进程边界墙,向其它的进程中注入截获API调用的代码,这项工作我们交给钩子函数(SetWindowsHookEx)来完成,关于如何创建一个包含系统钩子的动态链接库,《电脑高手杂志》已经有过专题介绍了,这里就不赘述了。

        所有系统钩子的函数必须要在动态库里,这样的话,当进程隐式或显式调用一个动态库里的函数时,系统会把这个动态库映射到这个进程的虚拟地址空间里,这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈,也就是说动态链接库中的代码被钩子函数注入了其它GUI进程的地址空间(非GUI进程,钩子函数就无能为力了),当包含钩子的DLL注入其它进程后,就可以取得映射到这个进程虚拟内存里的各个模块(EXE和DLL)的基地址,如:

       HMODULE hmodule=GetModuleHandle(“Mypro.exe”);

        在MFC程序中,我们可以用AfxGetInstanceHandle()函数来得到模块的基地址。EXE和DLL被映射到虚拟内存空间的什么地方是由它们的基地址决定的。它们的基地址是在链接时由链接器决定的。当你新建一个Win工程时,VC++链接器使用缺省的基地址0x。可以通过链接器的BASE选项改变模块的基地址。EXE通常被映射到虚拟内存的0x处,DLL也随之有不同的基地址,通常被映射到不同进程的相同的虚拟地址空间处。

        系统将EXE和DLL原封不动映射到虚拟内存空间中,它们在内存中的结构与磁盘上的静态文件结构是一样的。即PE (Portable Executable) 文件格式。我们得到了进程模块的基地址以后,就可以根据PE文件的格式穷举这个模块的IMAGE_IMPORT_DESCRIPTOR数组,看看进程空间中是否引入了我们需要截获的函数所在的动态链接库,比如需要截获“TextOutA”,就必须检查“Gdi.dll”是否被引入了。

        说到这里,我们有必要介绍一下PE文件的格式,如右图,这是PE文件格式的大致框图,最前面是文件头,我们不必理会,从PE File Optional Header后面开始,就是文件中各个段的说明,说明后面才是真正的段数据,而实际上我们关心的只有一个段,那就是“.idata”段,这个段中包含了所有的引入函数信息,还有IAT(Import Address Table)的RVA(Relative Virtual Address)地址。

        说到这里,截获WindowsAPI的整个原理就要真相大白了。实际上所有进程对给定的API函数的调用总是通过PE文件的一个地方来转移的,这就是一个该模块(可以是EXE或DLL)的“.idata”段中的IAT输入地址表(Import Address Table)。在那里有所有本模块调用的其它DLL的函数名及地址。对其它DLL的函数调用实际上只是跳转到输入地址表,由输入地址表再跳转到DLL真正的函数入口。

        具体来说,我们将通过IMAGE_IMPORT_DESCRIPTOR数组来访问“.idata”段中引入的DLL的信息,然后通过IMAGE_THUNK_DATA数组来针对一个被引入的DLL访问该DLL中被引入的每个函数的信息,找到我们需要截获的函数的跳转地址,然后改成我们自己的函数的地址……具体的做法在后面的关键代码中会有详细的讲解。

        讲了这么多原理,现在让我们回到“鼠标屏幕取词”的专题上来。除了API函数的截获,要实现“鼠标屏幕取词”,还需要做一些其它的工作,简单的说来,可以把一个完整的取词过程归纳成以下几个步骤:

        1. 安装鼠标钩子,通过钩子函数获得鼠标消息。

        使用到的API函数:SetWindowsHookEx

        2. 得到鼠标的当前位置,向鼠标下的窗口发重画消息,让它调用系统函数重画窗口。

        使用到的API函数:WindowFromPoint,ScreenToClient,InvalidateRect

        3. 截获对系统函数的调用,取得参数,也就是我们要取的词。

        对于大多数的Windows应用程序来说,如果要取词,我们需要截获的是“Gdi.dll”中的“TextOutA”函数。

        我们先仿照TextOutA函数写一个自己的MyTextOutA函数,如:

       BOOL WINAPI MyTextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString,int cbString)

       {

       // 这里进行输出lpszString的处理

       // 然后调用正版的TextOutA函数

       }

        把这个函数放在安装了钩子的动态连接库中,然后调用我们最后给出的HookImportFunction函数来截获进程对TextOutA函数的调用,跳转到我们的MyTextOutA函数,完成对输出字符串的捕捉。

        HookImportFunction的用法:

       HOOKFUNCDESC hd;

       PROC pOrigFuns;

       hd.szFunc="TextOutA";

       hd.pProc=(PROC)MyTextOutA;

       HookImportFunction (AfxGetInstanceHandle(),"gdi.dll",&hd,pOrigFuns);

        下面给出了HookImportFunction的源代码,相信详尽的注释一定不会让您觉得理解截获到底是怎么实现的很难,Ok,Let’s Go:

       ///////////////////////////////////////////// Begin ///////////////////////////////////////////////////////////////

       #include <crtdbg.h>

       // 这里定义了一个产生指针的宏

       #define MakePtr(cast, ptr, AddValue) (cast)((DWORD)(ptr)+(DWORD)(AddValue))

       // 定义了HOOKFUNCDESC结构,我们用这个结构作为参数传给HookImportFunction函数

       typedef struct tag_HOOKFUNCDESC

       {

       LPCSTR szFunc; // The name of the function to hook.

       PROC pProc; // The procedure to blast in.

       } HOOKFUNCDESC , * LPHOOKFUNCDESC;

       // 这个函数监测当前系统是否是WindowNT

       BOOL IsNT();

       // 这个函数得到hModule -- 即我们需要截获的函数所在的DLL模块的引入描述符(import descriptor)

       PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportModule);

       // 我们的主函数

       BOOL HookImportFunction(HMODULE hModule, LPCSTR szImportModule,

       LPHOOKFUNCDESC paHookFunc, PROC* paOrigFuncs)

       {

       /////////////////////// 下面的代码检测参数的有效性 ////////////////////////////

       _ASSERT(szImportModule);

       _ASSERT(!IsBadReadPtr(paHookFunc, sizeof(HOOKFUNCDESC)));

       #ifdef _DEBUG

       if (paOrigFuncs) _ASSERT(!IsBadWritePtr(paOrigFuncs, sizeof(PROC)));

       _ASSERT(paHookFunc.szFunc);

       _ASSERT(*paHookFunc.szFunc != '\0');

       _ASSERT(!IsBadCodePtr(paHookFunc.pProc));

       #endif

       if ((szImportModule == NULL) || (IsBadReadPtr(paHookFunc, sizeof(HOOKFUNCDESC))))

       {

       _ASSERT(FALSE);

       SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);

       return FALSE;

       }

       //////////////////////////////////////////////////////////////////////////////

       // 监测当前模块是否是在2GB虚拟内存空间之上

       // 这部分的地址内存是属于Win进程共享的

       if (!IsNT() && ((DWORD)hModule >= 0x))

       {

       _ASSERT(FALSE);

       SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);

       return FALSE;

       }

       // 清零

       if (paOrigFuncs) memset(paOrigFuncs, NULL, sizeof(PROC));

       // 调用GetNamedImportDescriptor()函数,来得到hModule -- 即我们需要

       // 截获的函数所在的DLL模块的引入描述符(import descriptor)

       PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor(hModule, szImportModule);

       if (pImportDesc == NULL)

       return FALSE; // 若为空,则模块未被当前进程所引入

       // 从DLL模块中得到原始的THUNK信息,因为pImportDesc->FirstThunk数组中的原始信息已经

       // 在应用程序引入该DLL时覆盖上了所有的引入信息,所以我们需要通过取得pImportDesc->OriginalFirstThunk

       // 指针来访问引入函数名等信息

       PIMAGE_THUNK_DATA pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule,

       pImportDesc->OriginalFirstThunk);

       // 从pImportDesc->FirstThunk得到IMAGE_THUNK_DATA数组的指针,由于这里在DLL被引入时已经填充了

       // 所有的引入信息,所以真正的截获实际上正是在这里进行的

       PIMAGE_THUNK_DATA pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk);

       // 穷举IMAGE_THUNK_DATA数组,寻找我们需要截获的函数,这是最关键的部分!

       while (pOrigThunk->u1.Function)

       {

       // 只寻找那些按函数名而不是序号引入的函数

       if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))

       {

       // 得到引入函数的函数名

       PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule,

       pOrigThunk->u1.AddressOfData);

       // 如果函数名以NULL开始,跳过,继续下一个函数

       if ('\0' == pByName->Name[0])

       continue;

       // bDoHook用来检查是否截获成功

       BOOL bDoHook = FALSE;

       // 检查是否当前函数是我们需要截获的函数

       if ((paHookFunc.szFunc[0] == pByName->Name[0]) &&

       (strcmpi(paHookFunc.szFunc, (char*)pByName->Name) == 0))

       {

       // 找到了!

       if (paHookFunc.pProc)

       bDoHook = TRUE;

       }

       if (bDoHook)

       {

       // 我们已经找到了所要截获的函数,那么就开始动手吧

       // 首先要做的是改变这一块虚拟内存的内存保护状态,让我们可以自由存取

       MEMORY_BASIC_INFORMATION mbi_thunk;

       VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));

       _ASSERT(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,

       PAGE_READWRITE, &mbi_thunk.Protect));

       // 保存我们所要截获的函数的正确跳转地址

       if (paOrigFuncs)

       paOrigFuncs = (PROC)pRealThunk->u1.Function;

       // 将IMAGE_THUNK_DATA数组中的函数跳转地址改写为我们自己的函数地址!

       // 以后所有进程对这个系统函数的所有调用都将成为对我们自己编写的函数的调用

       pRealThunk->u1.Function = (PDWORD)paHookFunc.pProc;

       // 操作完毕!将这一块虚拟内存改回原来的保护状态

       DWORD dwOldProtect;

       _ASSERT(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,

       mbi_thunk.Protect, &dwOldProtect));

       SetLastError(ERROR_SUCCESS);

       return TRUE;

       }

       }

       // 访问IMAGE_THUNK_DATA数组中的下一个元素

       pOrigThunk++;

       pRealThunk++;

       }

       return TRUE;

       }

       // GetNamedImportDescriptor函数的实现

       PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportModule)

       {

       // 检测参数

       _ASSERT(szImportModule);

       _ASSERT(hModule);

       if ((szImportModule == NULL) || (hModule == NULL))

       {

       _ASSERT(FALSE);

       SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);

       return NULL;

       }

       // 得到Dos文件头

       PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;

       // 检测是否MZ文件头

       if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) ||

       (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE))

       {

       _ASSERT(FALSE);

       SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);

       return NULL;

       }

       // 取得PE文件头

       PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);

       // 检测是否PE映像文件

       if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) ||

       (pNTHeader->Signature != IMAGE_NT_SIGNATURE))

       {

       _ASSERT(FALSE);

       SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);

       return NULL;

       }

       // 检查PE文件的引入段(即 .idata section)

       if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)

       return NULL;

       // 得到引入段(即 .idata section)的指针

       PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader,

       pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

       // 穷举PIMAGE_IMPORT_DESCRIPTOR数组寻找我们需要截获的函数所在的模块

       while (pImportDesc->Name)

       {

       PSTR szCurrMod = MakePtr(PSTR, pDOSHeader, pImportDesc->Name);

       if (stricmp(szCurrMod, szImportModule) == 0)

       break; // 找到!中断循环

       // 下一个元素

       pImportDesc++;

       }

       // 如果没有找到,说明我们寻找的模块没有被当前的进程所引入!

       if (pImportDesc->Name == NULL)

       return NULL;

       // 返回函数所找到的模块描述符(import descriptor)

       return pImportDesc;

       }

       // IsNT()函数的实现

       BOOL IsNT()

       {

       OSVERSIONINFO stOSVI;

       memset(&stOSVI, NULL, sizeof(OSVERSIONINFO));

       stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

       BOOL bRet = GetVersionEx(&stOSVI);

       _ASSERT(TRUE == bRet);

       if (FALSE == bRet) return FALSE;

       return (VER_PLATFORM_WIN_NT == stOSVI.dwPlatformId);

       }

       /////////////////////////////////////////////// End //////////////////////////////////////////////////////////////////////

       ä¸çŸ¥é“在之前,有多少朋友尝试过去实现“鼠标屏幕取词”这项充满了挑战的技术,也只有尝试过的朋友才能体会到其间的不易,尤其在探索API函数的截获时,手头的几篇资料没有一篇是涉及到关键代码的,重要的地方都是一笔代过,MSDN更是显得苍白而无力,也不知道除了IMAGE_IMPORT_DESCRIPTOR和IMAGE_THUNK_DATA,微软还隐藏了多少秘密,好在硬着头皮还是把它给攻克了,希望这篇文章对大家能有所帮助。

如何获取bilibili cid

       æ‰“开要查看cid的视频页,Ctrl+U查看网页源码,然后Ctrl+F搜索cid就可以了。

       å¦‚果视频不了了就进入原视频av号-1,之后进行上述搬操作获取cid,最后cid+1即可得到原视频的cid

       æ³¨æ„å¦‚果原视频-1的视频有多个分P,那么最后也要加上分P的数量。

谁能提供一个小区水电费管理的C程序代码啊~~~~~非常非常感谢~~~

       网上有很多C语言的源码查考滴

       /browse.aspx/Public/NetToolSet

       1. Snippet Compiler: /dotnet/SnippetCompiler

       2. Source Analysis: /sourceanalysis

       3. GhostDoc: /Sandcastle

       5. NUnit: /products/reflector

       8. Regex Tester: /dotnet/SnippetCompiler/

       Microsoft Source Analysis for C#

        Microsoft Source Analysis for C#是一款C#(不支持VB.NET)代码规范检查工具,前身是微软内部代码规范检查和代码格式强制工具StyleCop,目的是帮助项目团队执行一系列常用的源代码格式规范,它会根据预定义的C#代码格式的最佳实践进行检查,与FxCop不同的是它直接对源代码进行检查,且并不提供灵活的规则设置,强制开发者使用相同的习惯进行C#代码的编写。

       å®˜æ–¹ä¸»é¡µï¼š/sourceanalysis

       GhostDoc

        GhostDoc是Visual Studio的一个免费插件,可以帮助开发者生成比较完整规范的XML格式代码注释,如果你的代码遵循微软类库开发人员设计规范 ,由它自动产生的注释就已经完全可以很好地表达开发者创建的方法或者属性的意图,无需手工再进行修改。有了这些标准的XML注释,我们可以使用微软的文档工具Sandcastle生成专业级别的帮助文档。如我们有这样一段代码:

       public bool Add(string item)

       {

       //......

       }

       public void AppendHtmlText(IHtmlProvider htmlProvider)

       {

       //......

       }

       ä½¿ç”¨GhostDoc生成的注释如下:

       /// <summary>

       /// Adds the specified item.

       /// </summary>

       /// <param name="item">The item.</param>

       /// <returns></returns>

       public bool Add(string item)

       {

       //......

       }

       /// <summary>

       /// Appends the HTML text.

       /// </summary>

       /// <param name="htmlProvider">The HTML provider.</param>

       public void AppendHtmlText(IHtmlProvider htmlProvider)

       {

       //......

       }

       å®˜æ–¹ä¸»é¡µï¼š/Sandcastle

       Nunit

        NUnit 是为 .NET 框架生成的开放源代码单元测试框架。NUnit 使你可以用你喜欢的语言编写测试,从而测试应用程序的特定功能。当你首次编写代码时,单元测试是一种测试代码功能的很好方法,它还提供了一种对应用程序进行回归测试的方法。NUnit 应用程序提供了一个用于编写单元测试的框架,以及一个运行这些测试和查看结果的图形界面。

       å®˜æ–¹ä¸»é¡µï¼š/products/reflector

       The Regulator

        The Regulator能够使生成和测试正则表达式变得很容易,它允许你输入一个正则表达式以及一些针对其运行该表达式的输入。这样,在应用程序中实现该正则表达式之前,你便可以了解它将产生什么效果以及它将返回哪些种类的匹配项。另外它还提供了正则表达式库管理功能,在线更新正则表达式库,可以在RegexLib.com上搜索需要的正则表达式.

       å®˜æ–¹ä¸»é¡µï¼š/projects/regulator

       Regex Tester: /tutorials/regex/downloads/RegexTester.zip

       LINQPad

        随着在.NET Framework 3.5中对于LINQ的支持,越来越多的开发者在开发中使用了LINQ to SQL,但是编写LINQ to SQL查询似乎又成了一件很麻烦的事情,好在我们还有LINQPad这个工具,用来编写LINQ查询,不仅仅是LINQ to SQL,同时它也支持LINQ to XML、LINQ to Objects,另外LINQPad是完全免费的且无需安装,只要下载它的可执行文件就可以了。官方主页:

       NAnt

        NAnt 是一个基于 .NET 的生成工具,与当前版本的 Visual Studio .NET 不同,它使得为你的项目创建生成过程变得非常容易。当你拥有大量从事单个项目的开发人员时,你不能依赖于从单个用户的座位进行生成。你也不希望必须定期手动生成该项目。你更愿意创建每天晚上运行的自动生成过程。NAnt 使你可以生成解决方案、复制文件、运行 NUnit 测试、发送电子邮件,等等。遗憾的是,NAnt 缺少漂亮的图形界面,但它的确具有可以指定应该在生成过程中完成哪些任务的控制台应用程序和 XML 文件。目前NAnt已经支持.NET Framework 3.5,它的最新版本是0. Beta 1。官方主页:

Estuary概览

       Estuary是一个开源项目,旨在利用Filecoin网络进行公共数据检索。源码

       它由Protocol Labs应用研究小组(ARG)构思,术源旨在简化Filecoin存储过程,源码购物源码让新用户无需技术背景或了解底层技术即可使用。术源

       任何软件或脚本都可通过ARG托管的源码Estuary节点(estuary.tech)的API,在去中心化的术源Filecoin网络上存储公共数据,然后在全球范围内检索。源码

       截至今年8月,术源已有超过万份文件上传至Estuary,源码并进行了超过,术源慧谷动力 源码次存储交易。

       Estuary节点能够将CID托管至IPFS,源码并自动化存储交易,术源实现去中心化存储。源码

       用户只需上传文件至ARG托管的术源Estuary节点(estuary.tech)或查阅文档(docs.estuary.tech)尝试API。

       ARG小组认为,黑白棋源码开源端到端堆栈对证明Filecoin在应用层的工作方式至关重要,同时提供范例给刚接触Filecoin的开发人员。

       每次上传文件,都将经历一系列步骤,其中包括将信息存储在Estuary节点上。源码开发工具

       与传统云存储不同,Estuary提供了一个简单方式使用Filecoin,这是一个去中心化的存储网络,通过开放源代码和内置的经济激励机制确保文件可靠存储。

       在Filecoin中,军事网站源码用户付费将文件存储至存储提供者,这些提供者负责存储数据并证明其进行存储操作。

       Filecoin与传统云存储的主要区别在于其可用存储和存储价格不由单一公司控制,而是推动了一个开放市场的形成。

       Estuary是任何人都可以在任何时候使用且不受限制的开源软件,已有众多生态合作者,包括Textile、Miner Index、Fission、QRI以及Filecoin存储提供商社区中的其他合作者。

       现在即可开始使用Estuary,只需申请邀请码并在Estuary网站上开设账户,然后通过图形用户界面上传文件或生成API密钥。

       Estuary提供了精准且完整的文档,实时编辑示例代码,用户可以将其插入API密钥中,观察其与Estuary节点提供的每个API方法一起运作。

       需要注意的是,ARG的Estuary节点仅用于存储公开许可且满足ARG规定质量水平的数据,用户需自行完成数据加密。

       Estuary是Filecoin网络基础设施和协议方面的重要突破,为自由使用开源堆栈存储公共数据提供了途径。