Files
EscapistsReintroduced/tools/ordinary_gate_choices.py
T

68 lines
4.4 KiB
Python

"""Strict read-only joins for optional native gate action-choice diagnostics."""
import re
from ordinary_gate_evidence import join_gate_snapshots
PREFIX='ERR GATE CHOICE: '
IDENT=r'([A-Za-z_][A-Za-z_0-9]{0,127}):(-?\d+)'
BOOL=r'(0|1|true|false)'
LINE=re.compile(r'run=([A-Za-z0-9]{1,32}) sample=(\d+) real=(\d+) selected='+IDENT+r' context='+BOOL+r' actions=(\d+) permissions=(\d+) shown=(\d+) truncated='+BOOL+r' ordered=\[(.*)\]')
ENTRY=re.compile(r'(\d+)='+IDENT+r':(-?\d+)')
def need(value,reason):
if not value: raise ValueError(reason)
def parse_choice_record(line,nonce):
need(type(nonce) is str and re.fullmatch(r'[A-Za-z0-9]{1,32}',nonce),'invalid choice nonce')
if PREFIX.rstrip() not in line:return None
need(PREFIX in line and line.count(PREFIX)==1 and len(line)<=4096,'invalid choice line')
match=LINE.fullmatch(line.split(PREFIX,1)[1].strip());need(match is not None,'malformed choice record')
run,index,real,selected_class,selected_id,context,count,permissions,shown,truncated,ordered=match.groups()
index,real,selected_id,count,permissions,shown=map(int,(index,real,selected_id,count,permissions,shown))
need(run==nonce and 1<=index<=450 and 0<=real<=2147483647,'choice nonce or clock mismatch')
need(-1<=selected_id<=2147483647 and ((selected_class=='none')==(selected_id==-1)),'invalid selected action identity')
need(0<=count<=4096 and 0<=permissions<=4096 and shown==min(count,8) and (truncated in ('1','true'))==(count>shown),'choice list bounds disagree')
entries=[] if not ordered else ordered.split(',');need(len(entries)==shown,'choice entry count disagrees')
actions=[]
for i,text in enumerate(entries):
m=ENTRY.fullmatch(text);need(m is not None,'malformed ordered action')
n,cls,identity,permission=m.groups();n,identity,permission=map(int,(n,identity,permission))
need(n==i and -1<=identity<=2147483647 and ((cls=='none')==(identity==-1)),'ordered action identity/index invalid')
need(permission in (-1,0,1) and ((permission==-1)==(i>=permissions)),'cached permission index mismatch')
actions.append({'class':cls,'id':identity,'permitted':None if permission==-1 else bool(permission)})
return {'nonce':nonce,'sample':index,'real_ms':real,'selected_class':selected_class,'selected_id':selected_id,'context_selected':context in ('1','true'),'action_count':count,'permission_count':permissions,'truncated':truncated in ('1','true'),'actions':actions}
def parse_choice_records(content,nonce):
need(type(content) is str and len(content)<=32*1024*1024,'choice content bound')
records={};previous_real=-1
for line in content.splitlines():
r=parse_choice_record(line,nonce)
if r is None:continue
need(r['sample']==len(records)+1 and r['real_ms']>previous_real,'choice sequence missing, repeated or reversed')
records[r['sample']]=r;previous_real=r['real_ms']
need(records,'native choices absent')
return records
def join_choice_snapshots(content,nonce):
data=join_gate_snapshots(content,nonce);records=parse_choice_records(content,nonce)
for i,c in records.items():
need(i in data['snapshots'],'choice has no native gate peer')
s=data['snapshots'][i];a=s['action'];need(c['real_ms']==s['real_ms'] and c['context_selected']==a['context_selected'],'choice/gate clock or context mismatch')
if a['selected']:need(c['selected_class']=='ERR_UnlockPrisonAction','selected lock class disagrees')
if c['selected_class']=='ERR_UnlockPrisonAction':need(a['selected'],'native selected lock flag disagrees')
s['choices']=c
return data
def exact_prison_choices(snapshot):
"""Known non-aggregating closed Open/lock pair; not a general action sorter."""
c=snapshot.get('choices');need(type(c) is dict,'native choice snapshot absent')
a=c['actions'];need(c['context_selected'] and not c['truncated'] and c['action_count']==c['permission_count']==len(a)==2,'expected exact original two-action context')
need([e['class'] for e in a]==['ERR_PrisonDoorAction','ERR_UnlockPrisonAction'],'unsupported native action order')
need(all(type(e['id']) is int and e['id']>=0 for e in a) and a[0]['id']!=a[1]['id'],'invalid original action IDs')
need(a[0]['permitted'] is False and a[1]['permitted'] is True,'native closed-door/lock permissions changed')
need((c['selected_class'],c['selected_id']) in [(e['class'],e['id']) for e in a],'selected action outside original pair')
return c