Kreye yon sistèm verifikasyon fòmèl soti nan grafouyen. Pati 1: Machin Virtual karaktè nan PHP ak Python

Verifikasyon fòmèl se verifikasyon yon pwogram oswa algorithm lè l sèvi avèk yon lòt.

Sa a se youn nan metòd ki pi pwisan ki pèmèt ou jwenn tout frajilite nan yon pwogram oswa pwouve ke yo pa egziste.

Yon deskripsyon pi detaye sou verifikasyon fòmèl ka wè nan egzanp pou rezoud pwoblèm nan Wolf, kabrit, ak chou nan atik anvan mwen an.

Nan atik sa a mwen deplase soti nan verifikasyon fòmèl nan pwoblèm nan pwogram ak dekri ki jan
ki jan yo ka konvèti nan sistèm règ fòmèl otomatikman.

Pou fè sa, mwen te ekri pwòp analòg mwen nan yon machin vityèl, lè l sèvi avèk prensip senbolik.

Li analize kòd pwogram lan epi li tradwi li nan yon sistèm ekwasyon (SMT), ki ka deja rezoud yon pwogram.

Piske enfòmasyon sou kalkil senbolik yo prezante sou Entènèt la olye fragmentary,
Mwen pral yon ti tan dekri sa li ye.

Kalkil senbolik se yon fason pou egzekite yon pwogram ansanm sou yon pakèt done epi li se zouti prensipal pou verifikasyon pwogram fòmèl.

Pou egzanp, nou ka mete kondisyon antre kote premye agiman an ka pran nenpòt valè pozitif, dezyèm negatif la, twazyèm zewo a, ak agiman pwodiksyon an, pou egzanp, 42.

Kalkil senbolik nan yon sèl kouri pral ba nou repons lan si li posib pou nou jwenn rezilta a vle ak yon egzanp yon seri paramèt opinyon sa yo. Oswa prèv ke pa gen okenn paramèt sa yo.

Anplis, nou ka mete agiman yo antre nan tout sa yo posib, epi chwazi sèlman sa yo pwodiksyon, pou egzanp, modpas administratè a.

Nan ka sa a, nou pral jwenn tout frajilite pwogram nan oswa jwenn prèv ke modpas administratè a an sekirite.

Li ka remake ke ekzekisyon an klasik nan yon pwogram ak done espesifik opinyon se yon ka espesyal nan ekzekisyon senbolik.

Se poutèt sa, karaktè mwen VM ka travay tou nan mòd imitasyon nan yon machin vityèl estanda.

Nan kòmantè yo nan atik anvan an, yon moun ka jwenn kritik jis nan verifikasyon fòmèl ak yon diskisyon sou feblès li yo.

Pwoblèm prensipal yo se:

  1. Eksplozyon konbinezon, depi verifikasyon fòmèl finalman desann nan P = NP
  2. Pwosesis apèl nan sistèm dosye a, rezo ak lòt depo ekstèn se pi difisil pou verifye
  3. Pinèz nan spesifikasyon la, lè kliyan an oswa pwogramè gen entansyon yon sèl bagay, men pa t 'dekri li avèk presizyon ase nan spesifikasyon teknik la.

Kòm yon rezilta, yo pral verifye pwogram nan epi konfòme li ak spesifikasyon la, men li pral fè yon bagay konplètman diferan de sa kreyatè yo te espere nan men li.

Depi nan atik sa a mwen sitou konsidere itilizasyon verifikasyon fòmèl nan pratik, mwen pa pral frape tèt mwen kont miray la pou kounye a, epi mwen pral chwazi yon sistèm kote konpleksite algoritmik ak kantite apèl ekstèn yo minim.

Depi kontra entelijan pi byen adapte kondisyon sa yo, chwa a te tonbe sou kontra RIDE soti nan platfòm la Waves: yo pa Turing konplè, ak konpleksite maksimòm yo limite atifisyèlman.

Men, nou pral konsidere yo sèlman nan bò teknik.

Anplis de sa nan tout bagay, verifikasyon fòmèl yo pral espesyalman nan demann pou nenpòt ki kontra: li se anjeneral enposib korije yon erè kontra apre li te lanse.
Ak pri a nan erè sa yo ka trè wo, depi byen gwo kantite lajan yo souvan estoke sou kontra entelijan.

Machin vityèl senbolik mwen an ekri nan PHP ak Python, epi li sèvi ak Z3Prover soti nan Microsoft Research pou rezoud fòmil SMT ki kapab lakòz yo.

Nan nwayo li yo se yon pwisan rechèch milti-tranzaksyon, ki
pèmèt ou jwenn solisyon oswa frajilite, menm si li mande anpil tranzaksyon.
Menm Mythril, youn nan kad senbolik ki pi pwisan pou jwenn frajilite Ethereum, sèlman te ajoute kapasite sa a kèk mwa de sa.

Men, li vo anyen ke kontra etè yo pi konplèks ak Turing konplè.

PHP tradui kòd sous RIDE entelijan kontra a nan yon script python, kote pwogram nan prezante kòm yon sistèm Z3 SMT-konpatib nan eta kontra ak kondisyon pou tranzisyon yo:

Kreye yon sistèm verifikasyon fòmèl soti nan grafouyen. Pati 1: Machin Virtual karaktè nan PHP ak Python

Koulye a, mwen pral dekri sa k ap pase andedan an plis detay.

Men, anvan, kèk mo sou lang nan kontra entelijan RIDE.

Li se yon langaj pwogramasyon fonksyonèl ak ekspresyon ki se parese pa konsepsyon.
RIDE kouri nan izolasyon nan blockchain la epi li ka rekipere epi ekri enfòmasyon ki soti nan depo ki lye ak bous itilizatè a.

Ou ka tache yon kontra RIDE nan chak bous, epi rezilta egzekisyon an pral sèlman VRE oswa FO.

VRE vle di ke kontra entelijan an pèmèt tranzaksyon an, ak FO vle di li entèdi li.
Yon egzanp senp: yon script ka entèdi yon transfè si balans lan bous se mwens pase 100.

Kòm yon egzanp, mwen pral pran menm Wolf, kabrit, ak Chou, men deja prezante nan fòm lan nan yon kontra entelijan.

Itilizatè a pa pral kapab retire lajan nan bous la sou ki kontra a deplwaye jiskaske li te voye tout moun lòt bò a.

#Извлекаем положение всех объектов из блокчейна
let contract = tx.sender
let human= extract(getInteger(contract,"human"))
let wolf= extract(getInteger(contract,"wolf"))
let goat= extract(getInteger(contract,"goat"))
let cabbage= extract(getInteger(contract,"cabbage"))

#Это так называемая дата-транзакция, в которой пользователь присылает новые 4 переменные.
#Контракт разрешит её только в случае если все объекты останутся в сохранности.
match tx {
case t:DataTransaction =>
   #Извлекаем будущее положение всех объектов из транзакции
   let newHuman= extract(getInteger(t.data,"human")) 
   let newWolf= extract(getInteger(t.data,"wolf"))
   let newGoat= extract(getInteger(t.data,"goat"))
   let newCabbage= extract(getInteger(t.data,"cabbage"))
   
   #0 обозначает, что объект на левом берегу, а 1 что на правом
   let humanSide= human == 0 || human == 1
   let wolfSide= wolf == 0 || wolf == 1
   let goatSide= goat == 0 || goat == 1
   let cabbageSide= cabbage == 0 || cabbage == 1
   let side= humanSide && wolfSide && goatSide && cabbageSide

   #Будут разрешены только те транзакции, где с козой никого нет в отсутствии фермера.
   let safeAlone= newGoat != newWolf && newGoat != newCabbage
   let safe= safeAlone || newGoat == newHuman
   let humanTravel= human != newHuman 

   #Способы путешествия фермера туда и обратно, с кем-то либо в одиночку.
   let t1= humanTravel && newWolf == wolf + 1 && newGoat == goat && newCabbage == cabbage 
   let t2= humanTravel && newWolf == wolf && newGoat == goat + 1 && newCabbage == cabbage
   let t3= humanTravel && newWolf == wolf && newGoat == goat && newCabbage == cabbage + 1
   let t4= humanTravel && newWolf == wolf - 1 && newGoat == goat && newCabbage == cabbage
   let t5= humanTravel && newWolf == wolf && newGoat == goat - 1 && newCabbage == cabbage
   let t6= humanTravel && newWolf == wolf && newGoat == goat && newCabbage == cabbage - 1
   let t7= humanTravel && newWolf == wolf && newGoat == goat && newCabbage == cabbage
   let objectTravel = t1 || t2 || t3 || t4 || t5 || t6 || t7
   
   #Последняя строка в разделе транзакции описывает разрешающее транзакцию условие.
   #Переменные транзакции должны иметь значения 1 или 0, все объекты должны
   #быть в безопасности, а фермер должен переплывать реку в одиночку 
   #или с кем-то на каждом шагу
   side && safe && humanTravel && objectTravel
case s:TransferTransaction =>
   #Транзакция вывода средств разрешена только в случае если все переплыли на другой берег
   human == 1 && wolf == 1 && goat == 1 && cabbage == 1

#Все прочие типы транзакций запрещены
case _ => false

}

PHP premye ekstrè tout varyab ki soti nan kontra entelijan an nan fòm lan nan kle yo ak varyab ekspresyon Boolean ki koresponn lan.

cabbage: extract ( getInteger ( contract , "cabbage" ) )
goat: extract ( getInteger ( contract , "goat" ) )
human: extract ( getInteger ( contract , "human" ) )
wolf: extract ( getInteger ( contract , "wolf" ) )
fState: human== 1 && wolf== 1 && goat== 1 && cabbage== 1
fState: 
wolf: 
goat: 
cabbage: 
cabbageSide: cabbage== 0 || cabbage== 1
human: extract ( getInteger ( contract , "human" ) )
newGoat: extract ( getInteger ( t.data , "goat" ) )
newHuman: extract ( getInteger ( t.data , "human" ) )
goatSide: goat== 0 || goat== 1
humanSide: human== 0 || human== 1
t7: humanTravel && newWolf== wolf && newGoat== goat && newCabbage== cabbage
t3: humanTravel && newWolf== wolf && newGoat== goat && newCabbage== cabbage + 1
t6: humanTravel && newWolf== wolf && newGoat== goat && newCabbage== cabbage - 1
t2: humanTravel && newWolf== wolf && newGoat== goat + 1 && newCabbage== cabbage
t5: humanTravel && newWolf== wolf && newGoat== goat - 1 && newCabbage== cabbage
t1: humanTravel && newWolf== wolf + 1 && newGoat== goat && newCabbage== cabbage
t4: humanTravel && newWolf== wolf - 1 && newGoat== goat && newCabbage== cabbage
safeAlone: newGoat != newWolf && newGoat != newCabbage
wolfSide: wolf== 0 || wolf== 1
humanTravel: human != newHuman
side: humanSide && wolfSide && goatSide && cabbageSide
safe: safeAlone || newGoat== newHuman
objectTravel: t1 || t2 || t3 || t4 || t5 || t6 || t7

PHP Lè sa a, konvèti yo nan yon Z3Prover SMT-konpatib deskripsyon sistèm nan Python.
Done yo vlope nan yon bouk, kote varyab depo resevwa endèks i, varyab tranzaksyon endèks i + 1, ak varyab ak ekspresyon mete règ yo pou tranzisyon soti nan eta anvan an nan pwochen an.

Sa a se kè machin vityèl nou an, ki bay yon mekanis rechèch milti-tranzaksyon.

fState:  And( And( And( human[Steps]  ==  1 , wolf[Steps]  ==  1 )  , goat[Steps]  ==  1 )  , cabbage[Steps]  ==  1 )  
final:  fState[Steps] 
fState:   
wolf:   
goat:   
cabbage:   
cabbageSide:  Or( cabbage[i]  ==  0 , cabbage[i]  ==  1 )  
goatSide:  Or( goat[i]  ==  0 , goat[i]  ==  1 )  
humanSide:  Or( human[i]  ==  0 , human[i]  ==  1 )  
t7:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] )  , goat[i+1]  ==  goat[i] )  , cabbage  ==  cabbage[i] )  
t3:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] )  , goat[i+1]  ==  goat[i] )  , cabbage  ==  cabbage[i] + 1 )  
t6:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] )  , goat[i+1]  ==  goat[i] )  , cabbage  ==  cabbage[i] - 1 )  
t2:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] )  , goat[i+1]  ==  goat[i] + 1 )  , cabbage  ==  cabbage[i] )  
t5:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] )  , goat[i+1]  ==  goat[i] - 1 )  , cabbage  ==  cabbage[i] )  
t1:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] + 1 )  , goat[i+1]  ==  goat[i] )  , cabbage  ==  cabbage[i] )  
t4:  And( And( And( humanTravel[i] , wolf  ==  wolf[i] - 1 )  , goat[i+1]  ==  goat[i] )  , cabbage  ==  cabbage[i] )  
safeAlone:  And( goat[i+1] != wolf , goat[i+1] != cabbage )  
wolfSide:  Or( wolf[i]  ==  0 , wolf[i]  ==  1 )  
humanTravel:  human[i] != human[i+1] 
side:  And( And( And( humanSide[i] , wolfSide[i] )  , goatSide[i] )  , cabbageSide[i] )  
safe:  Or( safeAlone[i] , goat[i+1]  ==  human[i+1] )  
objectTravel:  Or( Or( Or( Or( Or( Or( t1[i] , t2[i] )  , t3[i] )  , t4[i] )  , t5[i] )  , t6[i] )  , t7[i] )  
data:  And( And( And( side[i] , safe[i] )  , humanTravel[i] )  , objectTravel[i] )  

Kondisyon yo klase epi antre nan yon modèl script ki fèt pou dekri sistèm SMT nan Python.

Modèl vid


import json

from z3 import *

s = Solver()

  
  
    
Steps=7
Num= Steps+1

$code$



#template, only start rest
s.add(data + start)

#template
s.add(final)




ind = 0

f = open("/var/www/html/all/bin/python/log.txt", "a")



while s.check() == sat:
  ind = ind +1
  

  print ind
  m = s.model()
  print m

  print "traversing model..." 
  #for d in m.decls():
	#print "%s = %s" % (d.name(), m[d])

  
 
  f.write(str(m))
  f.write("nn")
  exit()
  #s.add(Or(goat[0] != s.model()[data[0]] )) # prevent next model from using the same assignment as a previous model



print "Total solution number: "
print ind  

f.close()
 


Pou dènye eta a nan tout chèn lan, règ yo ki espesifye nan seksyon tranzaksyon transfè yo aplike.

Sa vle di ke Z3Prover pral chèche jisteman seri kondisyon sa yo ki pral finalman pèmèt yo retire lajan nan kontra a.

Kòm yon rezilta, nou otomatikman resevwa yon modèl SMT konplètman fonksyonèl nan kontra nou an.
Ou ka wè ke li trè menm jan ak modèl la nan atik anvan mwen an, ke mwen konpile manyèlman.

Modèl ranpli


import json

from z3 import *

s = Solver()

  
  
    
Steps=7
Num= Steps+1

human = [ Int('human_%i' % (i + 1)) for i in range(Num) ]
wolf = [ Int('wolf_%i' % (i + 1)) for i in range(Num) ]
goat = [ Int('goat_%i' % (i + 1)) for i in range(Num) ]
cabbage = [ Int('cabbage_%i' % (i + 1)) for i in range(Num) ]
nothing= [  And( human[i] == human[i+1], wolf[i] == wolf[i+1], goat[i] == goat[i+1], cabbage[i] == cabbage[i+1] )   for i in range(Num-1) ]


start= [ human[0] == 1, wolf[0] == 0, goat[0] == 1, cabbage[0] == 0 ]

safeAlone= [  And( goat[i+1] != wolf[i+1] , goat[i+1] != cabbage[i+1] )   for i in range(Num-1) ]
safe= [  Or( safeAlone[i] , goat[i+1]  ==  human[i+1] )   for i in range(Num-1) ]
humanTravel= [  human[i] != human[i+1]  for i in range(Num-1) ]
cabbageSide= [  Or( cabbage[i]  ==  0 , cabbage[i]  ==  1 )   for i in range(Num-1) ]
goatSide= [  Or( goat[i]  ==  0 , goat[i]  ==  1 )   for i in range(Num-1) ]
humanSide= [  Or( human[i]  ==  0 , human[i]  ==  1 )   for i in range(Num-1) ]
t7= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] )  , goat[i+1]  ==  goat[i] )  , cabbage[i+1]  ==  cabbage[i] )   for i in range(Num-1) ]
t3= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] )  , goat[i+1]  ==  goat[i] )  , cabbage[i+1]  ==  cabbage[i] + 1 )   for i in range(Num-1) ]
t6= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] )  , goat[i+1]  ==  goat[i] )  , cabbage[i+1]  ==  cabbage[i] - 1 )   for i in range(Num-1) ]
t2= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] )  , goat[i+1]  ==  goat[i] + 1 )  , cabbage[i+1]  ==  cabbage[i] )   for i in range(Num-1) ]
t5= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] )  , goat[i+1]  ==  goat[i] - 1 )  , cabbage[i+1]  ==  cabbage[i] )   for i in range(Num-1) ]
t1= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] + 1 )  , goat[i+1]  ==  goat[i] )  , cabbage[i+1]  ==  cabbage[i] )   for i in range(Num-1) ]
t4= [  And( And( And( humanTravel[i] , wolf[i+1]  ==  wolf[i] - 1 )  , goat[i+1]  ==  goat[i] )  , cabbage[i+1]  ==  cabbage[i] )   for i in range(Num-1) ]
wolfSide= [  Or( wolf[i]  ==  0 , wolf[i]  ==  1 )   for i in range(Num-1) ]
side= [  And( And( And( humanSide[i] , wolfSide[i] )  , goatSide[i] )  , cabbageSide[i] )   for i in range(Num-1) ]
objectTravel= [  Or( Or( Or( Or( Or( Or( t1[i] , t2[i] )  , t3[i] )  , t4[i] )  , t5[i] )  , t6[i] )  , t7[i] )   for i in range(Num-1) ]
data= [ Or(  And( And( And( side[i] , safe[i] )  , humanTravel[i] )  , objectTravel[i] )   , nothing[i]) for i in range(Num-1) ]


fState=  And( And( And( human[Steps]  ==  1 , wolf[Steps]  ==  1 )  , goat[Steps]  ==  1 )  , cabbage[Steps]  ==  1 )  
final=  fState 




#template, only start rest
s.add(data + start)

#template
s.add(final)




ind = 0

f = open("/var/www/html/all/bin/python/log.txt", "a")



while s.check() == sat:
  ind = ind +1
  

  print ind
  m = s.model()
  print m

  print "traversing model..." 
  #for d in m.decls():
	#print "%s = %s" % (d.name(), m[d])

  
 
  f.write(str(m))
  f.write("nn")
  exit()
  #s.add(Or(goat[0] != s.model()[data[0]] )) # prevent next model from using the same assignment as a previous model



print "Total solution number: "
print ind  

f.close()
 


Apre lansman, Z3Prover rezoud kontra entelijan an epi li ba nou yon chèn tranzaksyon ki pral pèmèt nou retire lajan:

Winning transaction chain found:
Data transaction: human= 0, wolf= 0, goat= 1, cabbage= 0
Data transaction: human= 1, wolf= 0, goat= 1, cabbage= 1
Data transaction: human= 0, wolf= 0, goat= 0, cabbage= 1
Data transaction: human= 1, wolf= 1, goat= 0, cabbage= 1
Data transaction: human= 0, wolf= 1, goat= 0, cabbage= 1
Data transaction: human= 1, wolf= 1, goat= 1, cabbage= 1
Data transaction: human= 1, wolf= 1, goat= 1, cabbage= 1
Transfer transaction

Anplis de kontra Ferry a, ou ka fè eksperyans ak pwòp kontra ou oswa eseye egzanp senp sa a, ki rezoud nan 2 tranzaksyon yo.

let contract = tx.sender
let a= extract(getInteger(contract,"a"))
let b= extract(getInteger(contract,"b"))
let c= extract(getInteger(contract,"c"))
let d= extract(getInteger(contract,"d"))

match tx {
case t:DataTransaction =>
let na= extract(getInteger(t.data,"a")) 
let nb= extract(getInteger(t.data,"b"))
let nc= extract(getInteger(t.data,"c"))
let nd= extract(getInteger(t.data,"d"))
   
   nd == 0 || a == 100 - 5
case s:TransferTransaction =>
   ( a + b - c ) * d == 12

case _ => true

}

Piske sa a se premye vèsyon an, sentaks la trè limite epi ka gen pinèz.
Nan atik sa yo, mwen planifye yo kouvri plis devlopman nan VM a, epi montre ki jan ou ka kreye fòmèlman verifye kontra entelijan avèk èd li yo, epi yo pa jis rezoud yo.

Machin vityèl karaktè a disponib nan http://2.59.42.98/hyperbox/
Apre mete kòd sous VM senbolik la nan lòd epi ajoute kòmantè la, mwen planifye mete l sou GitHub pou aksè gratis.

Sous: www.habr.com

Add nouvo kòmantè