
简介基于区块链的学术论文版权保护系统配套课程报告与毕业设计资料面向计算机、信息安全及相关专业学生也适合需完成区块链应用类课题的研究者。资源压缩包共3个文件包含PDF、Markdown、HTML三种格式的文档整体约2.09MBPDF适合打印阅读Markdown与HTML便于在线查看和二次编辑。报告内容完整覆盖摘要、绪论、相关技术与理论、需求分析、总体设计、详细设计与实现、系统测试、总结展望、参考文献及附件实现指南系统讲解了Hyperledger Fabric的通道机制、背书-排序-提交三阶段流程、链码设计以及IPFS分布式存储与仅存哈希上链的方案。针对学术论文版权确权难、存证易篡改、交易不透明和维权成本高等问题给出了基于VueSpring BootFabricIPFS四层架构的完整实现思路并涵盖前端功能模块、后端业务交互、智能合约开发及系统测试分析。已有37人学习浏览适合作为课程报告范文、毕业设计参考或区块链版权保护系统开发蓝本。1. 论文版权保护真正能落地的只有两件事存证与取证一篇论文从投出去到正式见刊常常要等半年甚至更久。这半年里稿件会在作者、期刊、审稿人之间来回流转中间任何一个版本流出去都可能成为日后说不清的源头谁能证明这个观点是你先提出的谁能证明你手里这份 PDF 才是初稿网页截图和邮件往来在这种场景下都太脆弱了。基于区块链的学术论文版权保护系统解决的就是这个“证明”的问题——在论文投稿、预印本发布、会议报告这些关键时间点把论文文件的哈希值、作者身份和上链时间一起固化到区块链上形成一条可以反复验证的证据链。它适合正在搭建期刊投稿系统或预印本平台的研发团队也适合想给作者提供首发权证明的科研管理机构。2. 选链与节点设计版权保护的参与方到底谁该跑节点把系统拆开看真正被业务方买单的能力只有两个存证和取证。存证是在写作完成或投稿提交的那一刻用最快速度把“内容指纹 身份 时间”写进链里取证是任何时间、任何第三方都能用一个公开入口对这份存证做核验。其余如自动识别抄袭、全网监测洗稿本质上是独立的文本比对工程不该由区块链系统承担。想清楚这一层选链和架构设计才会有明确方向。2.1 论文版权保护的痛点与区块链的边界学术论文版权纠纷集中发生在四个场景它们共同指向同一个需求。第一首发时间难以自证。投稿周期长作者往往先在预印本平台发布或者在学术会议上报告等正式见刊时已经过了一两年一旦被抢先“整理发表”很难说清谁是原创。第二稿件版本混乱。一篇论文从初稿、修改稿到终稿可能产生七八个版本哪个版本在什么时间点形成作者自己都未必能追踪。第三多作者权属模糊。通讯作者、第一作者、单位署名在不同阶段会调整纠纷发生时缺少一个可追溯的确认节点。第四传统版权登记成本高流程以周甚至月计赶不上快速发表的节奏。区块链在这四件事里的真正价值有限且明确它解决的是“存在性证明”和“时间证明”也就是在某一个时间点某个作者确实掌握某一份内容且该内容未被篡改。它不解决“是否抄袭”的判断也不解决“洗稿”的识别。很多项目失败就是因为试图让区块链承担它不擅长的内容理解工作。当一个系统把相似度检测、语义分析全部塞进链上智能合约时性能、费用和误判率都会无法收场。把边界划清楚后面的技术选型才不会被带偏。2.2 选型标准为什么版权存证的主流路径是联盟链我见过不少团队一上来就讨论“用以太坊还是用自研公链”这个方向通常走不通。公有链的存证记录公开可查公信力确实存在但学术论文版权场景会涉及机构身份、未发表内容、作者隐私把哈希以外的任何元数据写到公有链上都存在合规风险而只写哈希又很难沉淀出有业务价值的系统。更现实的问题是用公有链做存证要支付手续费频率一高运维和财务模型都不好跟机构解释。从公信力和可控性的平衡来看联盟链是这个场景最常见的答案。联盟链没有挖矿代币节点由准入的机构组成链上数据对节点成员可见可控且支持国密算法符合国内机构对安全合规的要求。落地时见得最多的是 FISCO BCOS 和 Hyperledger Fabric 两条链前者在国内的开源社区活跃度高自带一体化的部署工具和管理台适合快速搭建存证原型后者组件多、上手重但在企业级网络权限控制上更细适合已有成熟运维体系的组织。选哪条不是关键关键是你得能管住节点、能控制准入、能翻到每一笔历史记录。选型维度公有链私有链联盟链参与方任何人仅内部成员通过准入审核的机构公信力来源全网共识内部背书多机构联合背书数据隐私完全公开完全封闭受控可见可审计存证成本按交易计费内部运维成本内部运维成本合规适配风险较高公信力弱版权存证的主流选择选链还有一个容易忽略的评判标准生态是否完整。版权保护系统不是一条链就能交付的还需要浏览器、管理台、SDK、监控工具。只提供一个链内核而周边工具缺失会让开发周期拖长好几倍。团队在选型时我一般会要求把“运维一条链”的全流程走一遍再决定而不是只看共识算法和 TPS 指标。2.3 节点角色设计作者不跑节点期刊和权威机构跑节点怎么分配决定这条链后来有没有人认。如果把所有节点都放在一家公司内部那这条链本质上就是数据库加个签名出了纠纷没人愿意采信。合理的做法是由多方共同组成节点网络常见配置是期刊社节点承担作者提交入口负责接收稿件并发起存证交易预印本平台或机构知识库节点负责对作者自存证做交叉确认图书馆或文献情报中心节点作为独立第三方提供时间验证和只读查询版权保护中心等权威机构节点最终做背书保证这条链的“见证”身份。作者不需要自己运行节点。实际产品里作者通过期刊投稿系统或预印本平台提交论文由机构节点的身份代为发起存证交易但合约里记录的真实作者字段是作者本人信息。这个环节要特别注意机构代提交不等于机构拥有版权数据模型上必须把“提交者”和“权利人”分开。一个完整的存证流程通常是投稿系统计算文件哈希把作者信息和哈希封装成交易由机构节点的私钥签名后广播链上节点完成共识和出块交易回执返回给业务系统业务系统再把回执和区块信息写入本地库。链上链下各司其职才能支撑后续的证据包生成。3. 把论文哈希写进区块链最小链搭建与存证合约开发落地一个版权保护系统不需要从共识算法写起。常见做法是先基于开源的联盟链框架搭一条可供开发的最小链把存证合约跑通再去对接业务系统。这一章的内容足够让你在本地机器上把“哈希上链”这件事跑通并理解每一步的参数含义。3.1 设计链上存证数据结构该存什么、不该存什么设计存证结构时最大的原则是“能不上链的都不上链”。链上只放与证明直接相关且不可变的数据论文全文、PDF 文件、作者手机号这类信息放在链下业务系统链上只存它们的摘要和索引。以 FISCO BCOS 上常见的 Solidity 合约为例一份版权存证记录通常包含这些字段字段类型说明recordIdbytes32存证记录唯一标识由论文哈希生成paperHashstring论文原始文件的 SHA-256 哈希十六进制字符串authorNamestring经过脱敏处理的作者名或笔名不存证件号submitteraddress发起存证交易的机构节点地址titleDigestbytes32论文标题的哈希用于检索和展示externalIdstring链下业务系统中论文记录的 ID用于回查timestampuint256区块时间戳代表存证上链时间statusuint256存证状态1 为有效2 为作者主动撤回标记为什么要用哈希而不是直接用标题和作者名账号的考虑有两个一是链上存储空间有限哈希定长且占用小二是哈希值天然具备“内容指纹”属性只要论文文件有任何字节变化哈希就完全不同这为后续比对提供了严格依据。authorName 的脱敏处理不是多余的链上数据对节点成员可见手机号、身份证号一旦上链就永久存在想撤回也撤回不掉。externalId 这个字段很多人会忽略但它非常重要它是链上存证和链下投稿记录之间的关联键没有它事后无法从一条链上记录定位到原始论文。还有一个常见的陷阱不要把论文的下载 URL 存进链上。URL 会因系统迁移、域名变更而失效一旦失效链上留下一个永久不可修改的死链接反而削弱证据可信度。正确做法是把 URL 放在链下数据库链上只存 externalId由业务系统通过外部 ID 去关联最新的访问地址。3.2 在本地跑通一条最小联盟链部署命令与端口含义搭建本地开发链我推荐直接用 FISCO BCOS 的快速部署工具它能在一台机器上生成多个节点模拟出多机构的最小网络形态。提前说明不同安装包版本的参数细节会有差异以你实际拿到的 release 包为准我这里讲的是核心步骤和参数含义。# 生成一条包含 4 个节点的本地链 # -l 指定节点列表127.0.0.1:4 表示本机跑 4 个节点 # -p 依次指定 p2p、channel、jsonrpc 三类端口 bash build_chain.sh -l 127.0.0.1:4 -p 30300,20200,8545 # 启动全部节点 bash start_all.sh # 进入控制台 bash console.sh start三个端口各有分工30300 是节点之间同步数据的 P2P 端口节点通过它广播交易和区块这个端口必须互通否则节点无法组网20200 是控制台和 SDK 连接链的 channel 端口业务系统通过它发送交易安全配置也集中在这里8545 是 JSON-RPC 端口主要用来做查询区块浏览器和管理台都走它。四节点是最常见的开发配置模拟了四个机构各跑一个节点的场景和生产环境的差别只是物理机换成了多台服务器。进入控制台后先执行getBlockNumber看当前区块高度刚启动的链应该是 0 或很小的数值。如果这个命令能正常返回说明节点组网和生产链路都通了。随后还要做一件事把控制台里生成的账号地址记下来后面部署合约要用。FISCO BCOS 的 dev 模式有内置的账户但正式开发时我会创建独立业务账户避免把默认账户带到生产环境。3.3 编写版权存证合约注册、查询与防重复下面的合约是一个最小可用的版权存证合约它只做两件事登记一份论文存证、根据论文哈希查询存证记录。核心是require那行防重复校验。// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract CopyrightRegistry { struct CopyrightRecord { string paperHash; // 论文文件 SHA-256 哈希 string authorName; // 脱敏后的作者名 string title; // 论文标题 address submitter; // 提交机构节点地址 uint256 timestamp; // 上链时间 bool exists; // 是否存在 } // 以论文哈希的 keccak256 作为记录唯一键 mapping(bytes32 CopyrightRecord) private records; event CopyrightStored( bytes32 indexed recordId, string indexed paperHash, address submitter, uint256 timestamp ); function registerPaper( string calldata _paperHash, string calldata _authorName, string calldata _title ) external returns (bytes32 recordId) { recordId keccak256(abi.encodePacked(_paperHash)); require(!records[recordId].exists, paper hash already registered); records[recordId] CopyrightRecord({ paperHash: _paperHash, authorName: _authorName, title: _title, submitter: msg.sender, timestamp: block.timestamp, exists: true }); emit CopyrightStored(recordId, _paperHash, msg.sender, block.timestamp); return recordId; } function verifyRecord( string calldata _paperHash ) external view returns ( string memory authorName, string memory title, address submitter, uint256 timestamp, bool exists ) { bytes32 recordId keccak256(abi.encodePacked(_paperHash)); CopyrightRecord memory record records[recordId]; return ( record.authorName, record.title, record.submitter, record.timestamp, record.exists ); } }合约的映射键用的是keccak256(abi.encodePacked(_paperHash))而不是直接用_paperHash字符串做键。这是 Solidity 的常见习惯将变长字符串转成定长 bytes32节省存储空间也让查询效率更高。require的存在非常关键它保证同一个论文哈希只能注册一次后到的重复交易会直接回滚。这个特性会在第 4 章被用来做幂等兜底。block.timestamp是区块打包时间并非业务提交时间所以合约里没有把作者的电脑时间作为依据。部署合约时我一般用控制台或自动化脚本调用把编译后的 bytecode 和 abi 交给部署工具即可。部署完成后要保存三样东西合约地址、abi 文件、部署账户地址。abi 文件是给 SDK 调用合约用的没有它后续业务系统无法解析交易返回值。这块代码并不是从某个现成项目里抄来的而是版权存证场景中结构最简单、边界最清晰的一种写法适合作为团队内部的基础模板继续扩展。3.4 业务端调用合约Python SDK 的封装方式链搭好、合约部署完接下来是业务系统调用。下面以 Python 调用 FISCO BCOS SDK 为例展示从计算文件哈希到提交交易的完整流程。不同版本 SDK 的函数名略有差异但参数结构和逻辑是通用的。import hashlib from client.bcosclient import BcosClient from client.datatype_parser import DatatypeParser CONTRACT_ADDRESS 0x... # 部署合约后拿到的地址 abi_file CopyrightRegistry.abi def sha256_of_file(file_path: str) - str: digest hashlib.sha256() # 分块读取防止大 PDF 一次性载入内存 with open(file_path, rb) as f: for chunk in iter(lambda: f.read(65536), b): digest.update(chunk) return digest.hexdigest() def register_paper(file_path: str, author_name: str, title: str): paper_hash sha256_of_file(file_path) client BcosClient() parser DatatypeParser() parser.load_abi_file(abi_file) tx_result client.sendRawTransactionGetResult( contract_addressCONTRACT_ADDRESS, abi_parserparser, function_nameregisterPaper, args[paper_hash, author_name, title], # 与合约函数参数顺序一致 ) return tx_result这里的重点是paper_hash必须由原始文件计算不能先对文件做 base64 编码再算否则哈希与链上验证时所用的内容就不一致。参数顺序必须与 Solidity 合约的registerPaper(string,string,string)保持一致这是新手最常见的失败点。65536 字节的分块读取是为了避免把几十 MB 的 PDF 一次性读进内存对投稿系统这种文件大小差异很大的场景是稳妥习惯。注意业务系统应把作者身份、机构 ID 等敏感属性放在链下数据库而不是全部塞进合约参数。链上只保留证明所需的最小集合出了问题才有回旋余地。4. 把存证嵌进期刊投稿系统事务、幂等与证据包链上合约跑通只完成了技术验证真正要交付的是与投稿流程的融合。这一章讲的是业务系统怎么与链交互重点在三个工程细节事务边界、重复提交的兜底、证据包的生成。4.1 投稿提交时自动上链事务边界怎么划投稿系统接入存证时最容易犯的错误是“为了上链而上链”把存证放在接口的某个随意位置。常见做法是把它放在稿件“正式提交”这个状态变更的节点也就是作者点击提交、系统校验通过、稿件状态变成已提交的那一刻。下面是接入逻辑的简化示意from django.db import transaction from evidence.models import Evidence def submit_paper(paper_obj, author): paper_hash sha256_of_file(paper_obj.path) # 本地事务只负责数据库操作不包含链上调用 with transaction.atomic(): ev Evidence.objects.create( paper_idpaper_obj.id, paper_hashpaper_hash, statuspending, ) try: tx_result chain_client.register_paper( paper_hash, author.display_name, paper_obj.title ) receipt chain_client.get_transaction_receipt(tx_result) ev.tx_hash receipt.transaction_hash ev.block_number receipt.block_number ev.block_timestamp receipt.block_timestamp ev.status confirmed ev.save() except ChainRpcError as exc: # 链上失败本地记录标记为 failed不影响稿件入库 ev.status failed ev.save() raise这里没有把链上调用包进本地事务里原因是链上交易的成功与否由节点共识决定时机上不可控强行放进数据库事务会让事务长时间挂起。正确的思想是数据库落一条 pending 状态记录再调链最后根据链上回执更新本地状态。如果链上失败稿件本身仍然入库但存证记录标记失败方便后续重试或人工介入。设计上有两个细节值得单独强调。第一Evidence表的paper_id应该设唯一索引保证一篇论文在系统里只有一条存证主记录后续所有版本都挂在主记录之下。第二status字段要允许 pending、confirmed、failed 三种状态只留“成功/失败”两态会在链上回执延迟时造成假失败实际交易可能已经出块成功。4.2 幂等与防重链上 require 和本地唯一索引的双保险投稿系统的前端如果没做按钮防抖用户双击提交会发出两个几乎同时到达的请求这是存证场景最容易翻车的地方。两个请求会计算出同一个paper_hash如果合约没有防重逻辑链上就会出现两条相同哈希的存证时间戳还一样法官看到后会问“为什么同一篇论文被登记了两次”。解决方案是双保险。链上那层就是第 3 章合约里的require(!records[recordId].exists, paper hash already registered)同一哈希的第二次交易会被直接回滚。但合约层只能阻断链上不能阻止业务层创建重复的本地记录所以本地数据库也要加唯一约束# 表结构关键约束 # UNIQUE INDEX idx_paper_hash ON evidence (paper_hash)有了这层唯一索引两个并发请求只有一个能成功插入另一个直接抛主键冲突异常。结合合约层的 require即使业务层漏判链上也不会产生冗余证据。处理重复提交的正确姿势是捕获异常后返回“该稿件已完成存证”的提示而不是报 500 错误。我在实际项目里还倾向于在服务层加一个分布式锁以paper_hash作为锁键把并发窗口进一步压缩。三层防护看起来冗余但存证系统出一次重复证据后续所有档案可信度都受影响。从工程结构上看这套存证模型与常见的区块链溯源系统代码在底子上同源——同样是用哈希做索引、用 require 做防重、用回执回写状态。区别只是溯源场景里字段换成了批次号、物流状态和产地信息而版权场景换成了论文哈希、作者和时间戳。如果你们团队之前做过溯源链把这套逻辑迁移过来的成本并不高。4.3 证据包设计取证时拿什么去证明存证的价值最终体现在取证环节无论面对期刊编辑部还是仲裁机构都需要一个能自解释的证据包。证据包不是简单打印一条链上记录而是一组相互印证的材料通常包含以下内容证据项来源作用原始论文文件链下业务系统证明持有内容本身论文 SHA-256 哈希本地计算与链上哈希做比对链上存证记录合约查询证明哈希、作者、时间交易哈希链上回执在区块浏览器中定位交易区块高度与出块时间区块链浏览器证明交易被打包进链合约地址部署信息证明验证入口的权威性存证凭证 PDF本系统生成面向非技术人员的展示文件生成证据包的代码逻辑不复杂核心是把链上查询结果和本地元数据组装起来def build_evidence_package(evidence_id: int): ev Evidence.objects.get(idevidence_id) onchain chain_client.verify_record(ev.paper_hash) evidence_package { paper_id: ev.paper_id, paper_sha256: ev.paper_hash, onchain_author: onchain[authorName], tx_hash: ev.tx_hash, block_number: ev.block_number, block_timestamp: ev.block_timestamp, verify_url: fhttps://verify.example.org/hash/{ev.paper_hash}, generated_at: datetime.now().isoformat(), } return evidence_package真正增强可信度的是verify_url这一项。第三方拿到证据包后可以打开这个公开查询页面输入论文哈希系统会实时从链上拉取存证记录并展示。这个入口的存在让“验证”从口头承诺变成了可操作的动作是证据包设计里最值得投入的一环。我建议查询页面只接受哈希输入不做任何模糊搜索因为模糊匹配的结果会给人“系统可被篡改”的联想直接精确比对反而干净。查询记录本身也要留审计日志谁查了、查了什么、结果如何都要可追溯这会在纠纷处理时多一层保护。5. 避坑排查时间戳逆序、合约升级与跨机构互认链上存证系统的坑和普通 Web 系统很不一样很多问题不在代码逻辑而在链本身的状态和外部机构的认可度。下面四条是我见过的典型问题按“现象—原因—解决”的方式记录下来希望能帮你少走弯路。5.1 节点时间不一致导致时间戳逆序现象某次存证完成后第二天作者查记录发现链上时间比自己实际提交的时间早了两个小时甚至在同一条链上出现了后一笔交易的时间戳早于前一笔的情况。原因联盟链的区块时间戳来自打包节点本地时钟而不是某个全局时间服务。如果节点服务器没有开启 NTP 同步或某台机器时钟漂移那么它打包出的区块时间戳就可能比前一个区块更早造成时间倒挂。这在测试环境单机跑时完全暴露不出来生产环境多节点部署后必然遇到。解决所有节点统一配置 NTP 服务并设定时间偏移告警阈值超过 5 秒就把节点从共识列表中临时剔除。同时业务系统不能只依赖区块时间戳要在存证记录里单独保存“业务提交时间”以链下时间为准、链上时间作为旁证。这两者本来就不该完全相等向用户解释时也要说清楚避免把区块时间当成唯一权威。5.2 合约升级后旧存证全部失效现象存证合约部署后因为业务需求变化升级了新版本换了一个新合约地址。结果所有历史存证在新合约里都查不到而旧合约地址已经没人维护团队自己也找不到原合约的 abi 文件。原因Solidity 合约的数据存储与合约地址强绑定新部署的合约是一块全新的存储空间旧数据并不会自动迁移。很多人误以为“链上的数据永不丢失”就意味着“换合约也能查到”实际上查询接口不存在就等同于数据消失。解决版权存证合约不要轻易升级。如果需要增加功能正确做法是部署一个新合约但把旧合约地址硬编码进新合约的管理字段查询时如果一个地址查不到就自动路由到另一个地址。更稳妥的方案是存证合约只做“写”和“查”两件事永远不加入销毁、修改逻辑从结构上断绝升级需求。合约部署完成后abi 文件必须归档到版本库最好额外存一份到独立的冷备目录。5.3 跨机构不承认链的权威性现象作者拿着系统生成的存证凭证去找另一家期刊或仲裁机构对方看一眼就说“这是你们自己搭的链我怎么知道有没有被改过”拒不采信。原因链上节点全都在同一家公司或同一个体系内没有外部机构的见证节点链的公信力完全取决于节点的组成结构。区块链技术本身不能凭空产生信任网络里只有一个利益方时它就是一条私有链权威性自然受限。解决在项目早期就把权威节点引入进来。让期刊学会、省级版权保护中心、大型高校图书馆以节点身份加入链网络哪怕他们暂时只跑一个只读节点也意味着这些机构对链的存在知情并认可。如果条件不允许可以对接已经有司法背书经验的存证链或公证处存证服务作为最终存档层把自家链上的证据定期固化到更权威的通道上。选型阶段就把“这条链将来谁会认”想清楚比事后补节点容易太多。5.4 哈希与原始文件丢失绑定现象一年后作者要维权拿原始论文计算 SHA-256发现和链上记录的哈希完全对不上系统也没法解释了。原因哈希是内容指纹内容稍变一点哈希就完全改变。当初存证时如果没冻结原始文件版本后来作者自己把 PDF 重新导出、压缩或者在投稿系统里覆盖了原文件哈希自然就对不上。还有一种常见情况计算哈希的文件和存证时不是同一个文件——系统后台存了一份处理过的文件用户本地留的是另一份。解决在存证发生时就把“文件版本”固定下来。业务系统里存证所指向的文件必须设置为只读禁止任何覆盖操作。如果确实需要转格式要生成新的文件版本单独计算哈希并追加一条存证记录而不是覆盖原记录。同时保留哈希算法的计算规则说明比如“对 PDF 原始字节做 SHA-256”避免未来因工具链变化导致计算口径不一致。存证系统的本质是证据系统原文丢失链上的一切都失去了比对的锚点。6. 验证这套系统是否可靠双盲自检与对账习惯系统上线后的验证工作比上线本身更重要。这里提供一个我长期使用的验证方法每晚对账加定期双盲自检。对账的逻辑很简单每天跑一个脚本把本地库里的全部存证记录重新和链上比对一遍发现差异就告警。def nightly_reconcile(): local_records Evidence.objects.filter(statusconfirmed) for ev in local_records: onchain chain_client.verify_record(ev.paper_hash) if ( onchain[timestamp] ! ev.block_timestamp or onchain[authorName] ! ev.author_name ): alert(fevidence mismatch: {ev.id}) logger.info(freconciled {len(local_records)} records)为什么不能只靠事件订阅因为事件订阅在节点重启、网络抖动时可能丢消息而区块链本身是最终一致的数据源以链上数据为准做对账才靠谱。这个习惯救过我不止一次我有一次上线后几周才发现一笔旧存证的本地时间戳和链上差了 1 秒原因就是回执解析时用了本地服务器时间而不是区块时间老一批记录全部标记错误。双盲自检的做法是定期请一位不参与开发的同事在一台干净的机器上从零同步节点然后随机抽查几条存证记录从链上查询结果与本地系统显示必须完全一致。如果新节点同步出来的区块头哈希和管理台显示一致且抽查记录都能对上说明系统没有隐藏的逻辑分支。最后一条建议如果要面向作者展示存证结果务必做一个极简的“验证页”只留一个哈希输入框和一个查询按钮。入口越简单第三方机构越愿意使用证据的可验证性就越强。我自己在设计这类系统时曾经只关心链上功能而忽略验证入口结果被仲裁方反问“我怎么验证”从那以后我都是先做验证页再做存证流程。希望这些方法和教训能帮你在做区块链学术论文版权保护系统时少踩一些坑。本文还有配套的精品资源点击获取