English · 学习系列总导航 · 上一篇 · 下一篇:调试与回归笔记
离线状态模拟器把区块链学习规则连到可执行转换,不必运营网络。初态、请求、条件、结果和后态都在小程序中可检查。本指南将教回课的笔记例子变成完整Python学习项目。
你会分独立材料与顺序重放,保留拒绝请求,检查旧输入不变,并解释有限测试运行。完整源码及十二测试方法在文内。下一篇使用同一参考项目,演示具体错误怎样产生具体失败模式。
这是虚构应用状态练习,不是区块链实现或Ethereum模拟器。真实性是给定布尔前提;无签名、账户、费用、共识、网络、持久记录或交易,published仅为模型字段。
精选照片说明学习场景,不是已核验区块链课堂。
目录
目标是实现指定转换并按给定顺序重放,不是建账本或真发布笔记。小项目有用,但不能因名字而获得未实现能力。
上一篇代码处理表示:字符串、整数、字节、显示;本项目处理请求与当前状态如何决定接受及后态。输入解析正确,不等于转换正确。
能力句可写“给合法State和Request,按合同算Result且不改输入”;重放另写“把每后态给下一请求,保所有结果”。两任务均可观察。
先让学习者分别预测接受标记和后态,再检查两者是否来自同一条规则。只猜中最后修订号,可能仍没理解拒绝请求;只说拒绝,却把状态改掉,也没有满足合同。代码项目需要同时连接决定及效果。
概念不清回重放或教回指南。会运行却讲不清拒绝为何不变,应补精确推理,不自动加真实集成。绿色指示不能替代关系解释。
模型是声明的简化,练条件与转换,不重现生产执行。Ethereum官方EVM文档是另一技术路线,本文件不实现其指令、记账或失败规则。Ethereum EVM文档
这里无gas、账户随机数、区块选择、最终性或网络状态。拒绝不改三个字段是给定规则,不能推所有真实失败交易的每个变量都不变。
相似术语不使系统相同。state、request、revision在别处可有不同定义,代码旁保本合同,超范围再查技术库。
范围说明写研究什么、缺什么。完整解释小模型可正确却只支持窄结论。叫模拟器不会增加权威,也不能作为生产验证代码交付。
真实系统可能在应用结果外另有协议记账。这里不模拟这些字段,因此“拒绝不变”必须带上“本模型三个追踪字段”范围。这样学习者以后看到真实平台的不同结果,不会误以课堂规则应覆盖全部实现。
State含owner、revision、published。owner为精确非空Python字符串,作不透明课堂标识;revision为精确非负整数,排布尔;published精确布尔。纯空白owner未另禁止,字符串不带身份权威。
Request含caller、expected_revision、authentic:非空精确字符串、非负精确整数排布尔、精确布尔。True由材料给定,不是签名算法输出。
S为owner A、revision2、published False。B请求expected2、authentic True在字段上合法,却可能无应用权限。
错字段构造时ValueError;格式合法但不允许时返回拒绝Result。两路径分开,不能把类型正确说成符合用途。规范阅读指南可修这种层次混淆。
owner与caller用精确字符串相等比较,没有姓名解析、组织认证或密钥注册。A和B只是材料标识,不代表已经核验某真实人物。这个小选择让权限条件可计算,同时明确现实身份连接尚未实现。
接受需authentic True、caller等当前owner、expected等当前revision、published False,全部满足,不投票、不平均、不以信任替代某项。
成功owner不变、revision加1、published True;拒绝全部字段不变。Result保accepted、reason、before、after,决定与作用都可查。
实现按authenticity、owner、revision、published报告首个失败。这是明确报告选择,使多失败确定;首因不表示后项都过。
先分开合取与更新。未决定就增号改了合同;把拒绝说成字段错误混了层。四条件卡保留到能解释每项并预测新材料。
Result的before使读者知道检查针对哪个状态,after则显示决定后的状态。两者不应只靠一张最终截图替代。reason也不能单独替代accepted,因为报告文本和决定标记各有合同,测试分别保留。
使用frozen dataclass。Python官方说明生成方法及模拟只读的frozen选项,这是便利,不是密码防篡改。Python dataclasses文档
成功用replace构造新State,不对输入赋新值;拒绝before、after指未变状态。当前字段为简单类型,方便与基线比。
frozen不是不可改区块链历史,无持久历史或对抗保护。测试只检查正常字段赋值被阻,以及调用后基线保留,不能扩大。
若C1修改共享基线,下一独立题会无意从后态开始。新结果和明示重置保护题目;顺序重放则有意传后态,是另一任务,不是偶然副作用。
frozen在这里帮助阻止普通字段赋值,不等于抵抗恶意修改的安全边界。我们也没有保存带签名的审计记录。不要把程序语言的只读便利与分布式账本的证据、治理或恢复能力混为一谈。
C1从S,A、expected2、True,接受到A、3、True。C2独立从S,B、2、True,因owner拒绝,S不变。
C3从S,A、1、True,revision拒绝。C4另给A、2、True初态,A、2、True请求因published拒绝,保该不同初态。
C5从S,A、2、False,因authenticity拒绝。关系同教回指南,现变可执行材料,不是新真实协议。
一成功四拒绝,拒绝仍保成功项:C2真实性True,C3 caller是owner。合取失败不是全部失败,输出含身份、初态、请求、决定、原因、后态供重做。
C4的初状态有意另给,不需从C1推它怎样形成。C1成功后号为3,而C4初号为2,混接会改材料。独立案例可以检查某一条件,顺序案例才要求前后历史连接,读题时先确认属于哪一种。
| 独立材料 | 初owner/revision/published | caller/expected/authentic | 结果/后态 |
|---|---|---|---|
| C1 | A/2/False | A/2/True | 接受;A/3/True |
| C2 | A/2/False | B/2/True | owner;不变 |
| C3 | A/2/False | A/1/True | revision;不变 |
| C4 | A/2/True | A/2/True | published;不变 |
| C5 | A/2/False | A/2/False | authenticity;不变 |
独立材料按各声明重置,顺序将前一后态给下一。差异是输入合同,不只是表格外观,暗混会改题。
一次从S:T1 A、2、True;T2 A、2、True;T3 A、3、True,中途不重置。
T1接受到A、3、True;T2因expected2不等3报revision,published也True但后查;T3号匹配却已发布,报published。最终A、3、True。
flags为True、False、False;理由accepted、revision、published。每后续before等前after。若每次重置,第二错成功,第三在错revision上判断,下一篇会实验此错误。
特别注意T2同时不满足修订号及未发布,报告只选较早的revision。T3的号已经匹配,才报告published。相同终态下,两次拒绝原因不同;保逐步记录,才能解释为什么不是重复的同一种失败。
| 步骤 | 预期号 | 接受 | 原因 | 之后号/published |
|---|---|---|---|---|
| T1 | 2 | True | accepted | 3 / True |
| T2 | 2 | False | revision | 3 / True |
| T3 | 3 | False | published | 3 / True |
replay接精确State及list或tuple,所有成员为精确Request。先验整个集合,坏成员ValueError,不把半份结果当完整运行返回。
合法时回最终State及顺序Result tuple。空集合回初态和空tuple,不因函数调用虚增号或造成功操作。
顺序由课堂给,不决定谁有排序权、不处理并发或独立运营者协议,相关问题回共识架构。
只留终态可藏错路径,只留理由可藏错更新,所以决定、解释、转换一起保。纸面过程由此成为可检查实现,不补未实现能力。
空序列也是有意义边界:没有请求就没有更新。它不说明系统停机或所有请求失败,只表明这次给定输入为空。返回初态及空结果,使调用者能把“没有操作”与“操作被拒绝”分开。
下一节是完整blockchain_state_lab.py,字段、转换、重放及十二unittest方法,仅标准库,无包、账户、API密钥、端点。
先State、Request,再apply_request,再replay,每分支指合同句,最后看对应测试。先预测,再把执行视为证据。
发布准备于Python3.12.14测试,不替设备安装解释器,也不建立本地环境。可只读,真跑则识别文件及运行时。
下一调试伴随按此模块名导入,两个文件同选定目录。它是普通文件依赖,不藏网络。伴随完整提供,故意错误与参考清楚分开。
若命令找到的是另一个旧副本,输出也不代表眼前文件。记录源文件身份和实际路径,属于简单但必要的运行证据。不能仅凭屏幕同样显示OK,就把不同版本的观察合并。
原生代码块为整文件,含测试入口,与附件相同,不需猜省略部分。
注解本身不是字段验证逻辑,显式初始化后检查执行本地合同。转换入口再查对象类型,非法构造与合法拒绝分开。
读源码时可从测试反向追到分支,再回合同句。例如test_stale_revision应走revision拒绝,而不是真实性分支。这样的对照帮助你理解测试在观察什么,而不是把测试名称当已证明全部机制的标签。
测试含成功、owner、旧号、已发布、真实性、多失败优先、输入保留、顺序、空序列、owner变化、坏输入,共十二方法,有多断言。
不加凭证或真实记录。讲不清分支回纸面,跑完整不等理解全部连接,下一任务按缺口,而非自动扩项目。
"""Offline note-state teaching model; not a blockchain protocol."""
from dataclasses import dataclass, replace, FrozenInstanceError
import unittest
@dataclass(frozen=True)
class State:
owner: str
revision: int
published: bool
def __post_init__(self):
if type(self.owner) is not str or not self.owner:
raise ValueError("owner must be a nonempty string")
if type(self.revision) is not int or self.revision < 0:
raise ValueError("revision must be a nonnegative integer")
if type(self.published) is not bool:
raise ValueError("published must be Boolean")
@dataclass(frozen=True)
class Request:
caller: str
expected_revision: int
authentic: bool
def __post_init__(self):
if type(self.caller) is not str or not self.caller:
raise ValueError("caller must be a nonempty string")
if type(self.expected_revision) is not int or self.expected_revision < 0:
raise ValueError("expected revision must be a nonnegative integer")
if type(self.authentic) is not bool:
raise ValueError("authentic must be Boolean")
@dataclass(frozen=True)
class Result:
accepted: bool
reason: str
before: State
after: State
def apply_request(state, request):
if type(state) is not State or type(request) is not Request:
raise ValueError("expected State and Request")
if not request.authentic:
return Result(False, "authenticity", state, state)
if request.caller != state.owner:
return Result(False, "owner", state, state)
if request.expected_revision != state.revision:
return Result(False, "revision", state, state)
if state.published:
return Result(False, "published", state, state)
after = replace(state, revision=state.revision + 1, published=True)
return Result(True, "accepted", state, after)
def replay(initial, requests):
if type(initial) is not State or type(requests) not in (list, tuple):
raise ValueError("expected State and a list or tuple of Request")
if any(type(request) is not Request for request in requests):
raise ValueError("every item must be a Request")
current = initial
results = []
for request in requests:
result = apply_request(current, request)
results.append(result)
current = result.after
return current, tuple(results)
class StateLabTests(unittest.TestCase):
def setUp(self):
self.initial = State("A", 2, False)
def test_success(self):
result = apply_request(self.initial, Request("A", 2, True))
self.assertEqual(result, Result(True, "accepted", self.initial,
State("A", 3, True)))
def test_wrong_owner(self):
result = apply_request(self.initial, Request("B", 2, True))
self.assertEqual(result, Result(False, "owner", self.initial, self.initial))
def test_stale_revision(self):
result = apply_request(self.initial, Request("A", 1, True))
self.assertEqual(result.reason, "revision")
self.assertFalse(result.accepted)
self.assertEqual(result.after, self.initial)
def test_already_published(self):
state = State("A", 2, True)
self.assertEqual(apply_request(state, Request("A", 2, True)),
Result(False, "published", state, state))
def test_authenticity(self):
self.assertEqual(apply_request(self.initial, Request("A", 2, False)),
Result(False, "authenticity", self.initial, self.initial))
def test_reason_priority(self):
self.assertEqual(apply_request(self.initial,
Request("B", 1, False)).reason, "authenticity")
self.assertEqual(apply_request(self.initial,
Request("B", 1, True)).reason, "owner")
def test_unchanged_input(self):
apply_request(self.initial, Request("A", 2, True))
self.assertEqual(self.initial, State("A", 2, False))
with self.assertRaises(FrozenInstanceError):
self.initial.revision = 9
def test_sequential_replay(self):
final, results = replay(self.initial, [Request("A", 2, True),
Request("A", 2, True), Request("A", 3, True)])
self.assertEqual(final, State("A", 3, True))
self.assertEqual([r.accepted for r in results], [True, False, False])
self.assertEqual([r.reason for r in results],
["accepted", "revision", "published"])
self.assertEqual(results[1].before, results[0].after)
self.assertEqual(results[2].before, results[1].after)
def test_empty_replay(self):
self.assertEqual(replay(self.initial, []), (self.initial, ()))
def test_changed_owner(self):
state = State("B", 2, False)
self.assertFalse(apply_request(state, Request("A", 2, True)).accepted)
self.assertEqual(apply_request(state, Request("B", 2, True)).after,
State("B", 3, True))
def test_field_validation(self):
for args in [("", 2, False), ("A", True, False),
("A", -1, False), ("A", 2, 0)]:
with self.subTest(state=args):
with self.assertRaises(ValueError):
State(*args)
for args in [("", 2, True), ("A", True, True),
("A", -1, True), ("A", 2, 1)]:
with self.subTest(request=args):
with self.assertRaises(ValueError):
Request(*args)
def test_api_validation(self):
with self.assertRaises(ValueError):
apply_request({}, Request("A", 2, True))
with self.assertRaises(ValueError):
replay(self.initial, [Request("A", 2, True), {}])
with self.assertRaises(ValueError):
replay(self.initial, "requests")
if __name__ == "__main__":
unittest.main(verbosity=2)
准备中该文件Python3.12.14十二方法通过,记录给定程序材料,不是部署、安全审查或真实链执行,无交易。
成功覆盖这些正负路径、重放、验证,不穷尽所有owner、revision、列表和运行时,也不证明无缺陷。
自选本地命令python3 blockchain_state_lab.py,保自己的版本输出;只读标检查预测,不把发布记录当自己的运行。
耗时不比链吞吐。小本地负载无网络接受或最终性终点,重要是实际是否匹配转换预期,不是看起来快。
python3 blockchain_state_lab.py
B、expected1、False对S会先报authenticity;只改True则报owner。严格按声明顺序。
首例owner和revision也失败,次例revision仍失败。reason是报告政策下选一因,不是所有条件真值向量。
若将来要输出全部失败项,那是新报告接口,要明确顺序、类型及测试。当前函数只承诺首项,不能因为读者想看到更多,就把没有返回的项写成通过。缺省输出与条件真假是不同层。
合取与报告分开。换检查顺序可不改接受,却改变reason测试,因为API承诺顺序。应标变化,不把每个新reason当新接受结果。
教回问报告因、另一个失败项、后态,三关系都保。若误以一因表示其余过,回条件表逐项评,再重建有序报告。
拒绝after等before;接受owner不变、号恰加1、published True;顺序下一before等前after;输入不被调用修改。
局部不变量帮助组织,不证明安全或替代接受依据。错误程序可保拒绝态却错接受无权请求,也可拒绝对却增号错。
因此要求表要同时有决定见证和状态见证。下一篇的两类故意错误会分别击穿这两种检查。先理解为什么单看flag不够,再运行实验,更容易把失败解释为具体关系而不是笼统程序坏了。
决定材料与不变量都用:C2查权限及不变,C1查依据及精确更新,顺序查连接及终值,胜于只查最终号。
卡写范围及反例:拒绝加1违反不变。下一篇只在隔离变体做,不推广到真实失败交易全部记账,模型明排那些字段。
S2为B、2、False,C1及C2请求与True保留,各独立从S2,不接旧成功态。
C1因A非B拒绝保S2;C2因B等B等条件接受到B、3、True。真实性未变。
测当前状态依赖,不背A总成功B总失败。原S及新S2并存,各按初态正确,不互删。
作品集写单变事实、未变、新决定、限制。说A密钥坏,指出True未变;初号错,修材料身份。纸面受控比较现有具体代码测试支持。
布尔revision或整数1的authentic超合同,构造ValueError,无合法Result。语言可数值用True不覆盖此要求。
B、2、True格式合法,对S才owner拒绝。期待构造失败问错层,类型不授权限。
如果replay材料后面有一个字典,程序先验全体并抛错,不返回前面请求的部分结果。这里没有外部写入可回滚,输入也不变。这个明确API选择不应被解释为真实交易系统的原子提交保证。
重放含普通dict也拒绝,全部预查。此局部行为不是内存池、传输解析或批交易说明。
诊断表分非法对象与合法被拒,列预期及负责函数。上一数据实验也分表示失败,本项目扩到状态决定但不合并证据。
authentic True是输入,不是独立签名证据;published True不证明有人收到;revision3不是区块号、时间戳或最终性证书。
无持久化、认证服务、权限注册、共享排序或对抗网络,字段检查与frozen不能补这些。名字含blockchain也不赋能力。
执行可读从用户意图到交易证据:构造、授权与执行、把智能合约读成状态机:核对调用者、条件与边界、合约存储、事件与索引:核对同一记录的三种视图、诊断失败的区块链交易:区分拒绝、回退与调用边界,排序协议回共识,各例不成为隐藏行为。
“按本规则重放给定请求”有支持,“验证区块链交易”没有。有限并非无用,目的是先看清机制,再学其他层关系。
字段到构造及field_validation;接受到test_success;权限到wrong_owner;报告序到reason_priority;连接到sequential_replay;基线到unchanged_input。
限制同表:owner测试不测全部权限设计,冻结赋值不证防篡改存储,重放不证并发协议。表用于路由,不装饰保证。
unittest官方提供断言框架,材料和规则原创,工具文档不背书模型或认证覆盖。Python unittest文档
作品集保表、纸面、源码、运行时、结果,再加新解释。学习参考不说独立设计全部,诚实支持标签有利选下一步。
五类各2:完整合同;分字段与接受;独立及顺序结果;保留及原因序;本地证据和范围。全对2、部分1、缺或矛盾0。
终态碰对却每步重置不能满重放分;本地都懂却称True为算出的签名证明,扣范围。
教育标准不授工程资格,十二通过不自动个人精通分。写实际读、预测、运行、修改或新变化解释。
存初答修正,伙伴或模型给连接标辅助,再无模型新题测迁移。作品集和教回提供记录方法,本篇给新可执行对象。
保存参考身份、完整合同、纸面预期、基线运行,未来可比已知任务,不是不断改的描述。
先选一错:漏owner、拒绝增号、成功加2、重放重置。看实验前预测哪材料受影响,它们有不同诊断图样。
不往生产或覆盖参考练错。伴随用另名离线函数,参考保留,对独立探针,避免制造误导线上补丁。
下一输出含问题、版本、失败、违规则、修复目标、复测。解释为何失败转匹配,比不明改动后绿灯更有学习证据。
示范:“blockchain_state_lab.py实现给定笔记转换及有序重放,准备时Python3.12.14十二方法通过,含独立拒绝、连接及owner变化,无真实密码核验、网络、持久化或共识。”
自己的说明换实际观察,只读就说只读,修改注明版本合同。读者应可查,不靠自信。
完整源码、测试、纸面、要求表并存,小但可重做可理解修正,是有限成果,不假装完整链。
下一调试篇看四种错误及回归笔记,大库给技术深度,学习项目把声明切片变可执行、可测、可讲,同时保假设边界。
继续学习
English · 学习系列总导航 · 上一篇 · 下一篇:调试与回归笔记
来源与范围
笔记规则、材料、诊断变体及学习评分为原创离线教学练习。真实性是给定布尔,不是计算核验。程序不是区块链实现、审计或生产补丁。链接技术文保留各自例子与条件。来源与路线于2026年10月15日核验。阅读和纸面练习不认证实现能力。
Ethereum EVM documentation — separate real execution environment
