@@ -515,6 +515,10 @@ The local memory of execution is a byte-array (instead of a word-array).
515
515
// --------------------------------------------------
516
516
rule #asInteger(WS) => Bytes2Int(WS, BE, Unsigned)
517
517
518
+ syntax String ::= #asString ( ByteArray ) [function]
519
+ // ----------------------------------------------------
520
+ rule #asString(WS) => Bytes2String(WS)
521
+
518
522
syntax Account ::= #asAccount ( ByteArray ) [function]
519
523
// ------------------------------------------------------
520
524
rule #asAccount(BS) => .Account requires lengthBytes(BS) ==Int 0
@@ -560,6 +564,12 @@ The local memory of execution is a byte-array (instead of a word-array).
560
564
rule #asInteger( W : .WordStack ) => W
561
565
rule #asInteger( W0 : W1 : WS ) => #asInteger(((W0 *Int 256) +Int W1) : WS)
562
566
567
+ syntax String ::= #asString ( ByteArray ) [function]
568
+ // ----------------------------------------------------
569
+ rule #asString( .WordStack ) => ""
570
+ rule #asString( W : .WordStack ) => chrChar( W )
571
+ rule #asString( W0 : WS ) => chrChar( W0 ) +String #asString( WS )
572
+
563
573
syntax Account ::= #asAccount ( ByteArray ) [function]
564
574
// ------------------------------------------------------
565
575
rule #asAccount( .WordStack ) => .Account
@@ -914,6 +924,48 @@ Encoding
914
924
rule #rlpEncodeLength(STR, OFFSET) => chrChar(lengthString(STR) +Int OFFSET) +String STR requires lengthString(STR) <Int 56
915
925
rule #rlpEncodeLength(STR, OFFSET) => #rlpEncodeLength(STR, OFFSET, #unparseByteStack(#asByteStack(lengthString(STR)))) requires lengthString(STR) >=Int 56
916
926
rule #rlpEncodeLength(STR, OFFSET, BL) => chrChar(lengthString(BL) +Int OFFSET +Int 55) +String BL +String STR
927
+
928
+ syntax String ::= #rlpEncodeMerkleTree ( MerkleTree ) [function]
929
+ // ----------------------------------------------------------------
930
+ rule #rlpEncodeMerkleTree ( .MerkleTree ) => "\x80"
931
+
932
+ rule #rlpEncodeMerkleTree ( MerkleLeaf ( PATH, VALUE ) )
933
+ => #rlpEncodeLength( #rlpEncodeString( #asString( #HPEncode( PATH, 1 ) ) )
934
+ +String #rlpEncodeString( VALUE )
935
+ , 192
936
+ )
937
+
938
+ rule #rlpEncodeMerkleTree ( MerkleExtension ( PATH, TREE ) )
939
+ => #rlpEncodeLength( #rlpEncodeString( #asString( #HPEncode( PATH, 0 ) ) )
940
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( TREE ) )
941
+ , 192
942
+ )
943
+
944
+ rule #rlpEncodeMerkleTree ( MerkleBranch ( 0 |-> P0:MerkleTree 1 |-> P1:MerkleTree 2 |-> P2:MerkleTree 3 |-> P3:MerkleTree
945
+ 4 |-> P4:MerkleTree 5 |-> P5:MerkleTree 6 |-> P6:MerkleTree 7 |-> P7:MerkleTree
946
+ 8 |-> P8:MerkleTree 9 |-> P9:MerkleTree 10 |-> P10:MerkleTree 11 |-> P11:MerkleTree
947
+ 12 |-> P12:MerkleTree 13 |-> P13:MerkleTree 14 |-> P14:MerkleTree 15 |-> P15:MerkleTree
948
+ , VALUE
949
+ )
950
+ )
951
+ => #rlpEncodeLength( #rlpMerkleH( #rlpEncodeMerkleTree( P0 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P1 ) )
952
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P2 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P3 ) )
953
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P4 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P5 ) )
954
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P6 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P7 ) )
955
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P8 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P9 ) )
956
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P10 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P11 ) )
957
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P12 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P13 ) )
958
+ +String #rlpMerkleH( #rlpEncodeMerkleTree( P14 ) ) +String #rlpMerkleH( #rlpEncodeMerkleTree( P15 ) )
959
+ +String #rlpEncodeString( VALUE )
960
+ , 192
961
+ )
962
+
963
+ syntax String ::= #rlpMerkleH ( String ) [function,klabel(MerkleRLPAux)]
964
+ // ------------------------------------------------------------------------
965
+ rule #rlpMerkleH ( X ) => #rlpEncodeString( Hex2Raw( Keccak256( X ) ) )
966
+ requires lengthString( X ) >=Int 32
967
+
968
+ rule #rlpMerkleH ( X ) => X [owise]
917
969
```
918
970
919
971
Decoding
@@ -955,5 +1007,154 @@ Decoding
955
1007
rule #decodeLengthPrefixLength(#str, STR, START, B0) => #decodeLengthPrefixLength(#str, START, B0 -Int 128 -Int 56 +Int 1, #asWord(#parseByteStackRaw(substrString(STR, START +Int 1, START +Int 1 +Int (B0 -Int 128 -Int 56 +Int 1)))))
956
1008
rule #decodeLengthPrefixLength(#list, STR, START, B0) => #decodeLengthPrefixLength(#list, START, B0 -Int 192 -Int 56 +Int 1, #asWord(#parseByteStackRaw(substrString(STR, START +Int 1, START +Int 1 +Int (B0 -Int 192 -Int 56 +Int 1)))))
957
1009
rule #decodeLengthPrefixLength(TYPE, START, LL, L) => TYPE(L, START +Int 1 +Int LL)
1010
+ ```
1011
+
1012
+ Merkle Patricia Tree
1013
+ ====================
1014
+
1015
+ - Appendix C and D from the Ethereum Yellow Paper
1016
+ - https://github.com/ethereum/wiki/wiki/Patricia-Tree
1017
+
1018
+ ``` k
1019
+ syntax KItem ::= Int | MerkleTree // For testing purposes
1020
+
1021
+ syntax MerkleTree ::= MerkleBranch ( Map, String )
1022
+ | MerkleExtension ( ByteArray, MerkleTree )
1023
+ | MerkleLeaf ( ByteArray, String )
1024
+ | ".MerkleTree"
1025
+ | ".MerkleBranch" [function]
1026
+ // -----------------------------------------------------------
1027
+ rule .MerkleBranch
1028
+ => MerkleBranch ( 0 |-> .MerkleTree 1 |-> .MerkleTree 2 |-> .MerkleTree 3 |-> .MerkleTree
1029
+ 4 |-> .MerkleTree 5 |-> .MerkleTree 6 |-> .MerkleTree 7 |-> .MerkleTree
1030
+ 8 |-> .MerkleTree 9 |-> .MerkleTree 10 |-> .MerkleTree 11 |-> .MerkleTree
1031
+ 12 |-> .MerkleTree 13 |-> .MerkleTree 14 |-> .MerkleTree 15 |-> .MerkleTree
1032
+ , ""
1033
+ )
1034
+
1035
+ syntax MerkleTree ::= MerkleUpdate ( MerkleTree, String, String ) [function]
1036
+ | MerkleUpdate ( MerkleTree, ByteArray, String ) [function,klabel(MerkleUpdateAux)]
1037
+ // --------------------------------------------------------------------------------------------------------
1038
+ rule MerkleUpdate ( TREE, S:String, VALUE ) => MerkleUpdate ( TREE, #nibbleize ( #parseByteStackRaw( S ) ), VALUE )
1039
+
1040
+ rule MerkleUpdate ( .MerkleTree, PATH:ByteArray, VALUE ) => MerkleLeaf ( PATH, VALUE )
1041
+
1042
+ rule MerkleUpdate ( MerkleLeaf ( LEAFPATH, _ ), PATH, VALUE )
1043
+ => MerkleLeaf( LEAFPATH, VALUE )
1044
+ requires #asInteger( LEAFPATH ) ==Int #asInteger( PATH )
1045
+
1046
+ rule MerkleUpdate ( MerkleLeaf ( LEAFPATH, LEAFVALUE ), PATH, VALUE )
1047
+ => MerkleUpdate ( MerkleUpdate ( .MerkleBranch, LEAFPATH, LEAFVALUE ), PATH, VALUE )
1048
+ requires #sizeByteArray( LEAFPATH ) >Int 0
1049
+ andBool #sizeByteArray( PATH ) >Int 0
1050
+ andBool LEAFPATH[0] =/=Int PATH[0]
1051
+
1052
+ rule MerkleUpdate ( MerkleLeaf ( LEAFPATH, LEAFVALUE ), PATH, VALUE )
1053
+ => #merkleExtensionBuilder( .ByteArray, LEAFPATH, LEAFVALUE, PATH, VALUE ) [owise]
1054
+
1055
+ rule MerkleUpdate ( MerkleExtension ( EXTPATH, EXTTREE ), PATH, VALUE )
1056
+ => MerkleExtension ( EXTPATH, MerkleUpdate ( EXTTREE, .ByteArray, VALUE ) )
1057
+ requires #asInteger( EXTPATH ) ==Int #asInteger( PATH )
1058
+
1059
+ rule MerkleUpdate ( MerkleExtension ( EXTPATH, EXTTREE ), PATH, VALUE )
1060
+ => #merkleExtensionBrancher( MerkleUpdate( .MerkleBranch, PATH, VALUE ), EXTPATH, EXTTREE )
1061
+ requires #sizeByteArray( EXTPATH ) >Int 0
1062
+ andBool #sizeByteArray( PATH ) >Int 0
1063
+ andBool EXTPATH[0] =/=Int PATH[0]
1064
+
1065
+ rule MerkleUpdate ( MerkleExtension ( EXTPATH, EXTTREE ), PATH, VALUE )
1066
+ => #merkleExtensionSplitter( .ByteArray, EXTPATH, EXTTREE, PATH, VALUE ) [owise]
1067
+
1068
+ rule MerkleUpdate ( MerkleBranch( M, _ ), PATH, VALUE )
1069
+ => MerkleBranch( M, VALUE )
1070
+ requires #sizeByteArray( PATH ) ==Int 0
1071
+
1072
+ rule MerkleUpdate ( MerkleBranch( M, BRANCHVALUE ), PATH, VALUE )
1073
+ => #merkleBrancher ( M, BRANCHVALUE, PATH[0], PATH[1 .. #sizeByteArray(PATH) -Int 1], VALUE ) [owise]
1074
+ ```
1075
+
1076
+ Merkle Tree Aux Functions
1077
+ -------------------------
1078
+
1079
+ ``` k
1080
+ syntax ByteArray ::= #nibbleize ( ByteArray ) [function]
1081
+ | #byteify ( ByteArray ) [function]
1082
+ // --------------------------------------------------------
1083
+ rule #nibbleize ( B ) => #asByteStack ( ( B [ 0 ] /Int 16 ) *Int 256 +Int ( B [ 0 ] %Int 16 ) )[0 .. 2]
1084
+ ++ #nibbleize ( B[1 .. #sizeByteArray(B) -Int 1] )
1085
+ requires #sizeByteArray( B ) >Int 0
1086
+
1087
+ rule #nibbleize ( _ ) => .ByteArray [owise]
1088
+
1089
+ rule #byteify ( B ) => #asByteStack ( B[0] *Int 16 +Int B[1] )
1090
+ ++ #byteify ( B[2 .. #sizeByteArray(B) -Int 2] )
1091
+ requires #sizeByteArray(B) >Int 0
1092
+
1093
+ rule #byteify ( _ ) => .ByteArray [owise]
1094
+
1095
+ syntax ByteArray ::= #HPEncode ( ByteArray, Int ) [function]
1096
+ // ------------------------------------------------------------
1097
+ rule #HPEncode ( X, T ) => #asByteStack ( ( HPEncodeAux(T) +Int 1 ) *Int 16 +Int X[0] ) ++ #byteify( X[1 .. #sizeByteArray(X) -Int 1] )
1098
+ requires #sizeByteArray(X) %Int 2 =/=Int 0
1099
+
1100
+ rule #HPEncode ( X, T ) => #asByteStack ( HPEncodeAux(T) *Int 16 )[0 .. 1] ++ #byteify( X ) [owise]
1101
+
1102
+ syntax Int ::= HPEncodeAux ( Int ) [function]
1103
+ // ---------------------------------------------
1104
+ rule HPEncodeAux ( X ) => 0 requires X ==Int 0
1105
+ rule HPEncodeAux ( _ ) => 2 [owise]
1106
+
1107
+ syntax MerkleTree ::= #merkleBrancher ( Map, String, Int, ByteArray, String ) [function]
1108
+ // ----------------------------------------------------------------------------------------
1109
+ rule #merkleBrancher ( X |-> TREE M, BRANCHVALUE, X, PATH, VALUE )
1110
+ => MerkleBranch( M[X <- MerkleUpdate( TREE, PATH, VALUE )], BRANCHVALUE )
1111
+
1112
+ syntax MerkleTree ::= #merkleExtensionBuilder( ByteArray, ByteArray, String, ByteArray, String ) [function]
1113
+ // -----------------------------------------------------------------------------------------------------------
1114
+ rule #merkleExtensionBuilder( PATH, P1, V1, P2, V2 )
1115
+ => #merkleExtensionBuilder( PATH ++ ( #asByteStack( P1[0] )[0 .. 1] )
1116
+ , P1[1 .. #sizeByteArray(P1) -Int 1], V1
1117
+ , P2[1 .. #sizeByteArray(P2) -Int 1], V2
1118
+ )
1119
+ [owise]
1120
+
1121
+ rule #merkleExtensionBuilder( PATH, P1, V1, P2, V2 )
1122
+ => MerkleExtension( PATH, MerkleUpdate( MerkleUpdate( .MerkleBranch, P1, V1 ), P2, V2 ) )
1123
+ requires #sizeByteArray(P1) >Int 0
1124
+ andBool #sizeByteArray(P2) >Int 0
1125
+ andBool P1[0] =/=Int P2[0]
1126
+
1127
+ rule #merkleExtensionBuilder( PATH, P1, V1, P2, V2 )
1128
+ => MerkleExtension( PATH, MerkleUpdate( MerkleUpdate( .MerkleBranch, P1, V1 ), P2, V2 ) )
1129
+ requires #sizeByteArray(P1) ==Int 0
1130
+ orBool #sizeByteArray(P2) ==Int 0
1131
+
1132
+ syntax MerkleTree ::= #merkleExtensionBrancher ( MerkleTree, ByteArray, MerkleTree ) [function]
1133
+ | #merkleExtensionSplitter ( ByteArray, ByteArray, MerkleTree, ByteArray, String ) [function]
1134
+ // -----------------------------------------------------------------------------------------------------------------
1135
+ rule #merkleExtensionBrancher( MerkleBranch(M, VALUE), PATH, EXTTREE )
1136
+ => MerkleBranch( M[PATH[0] <- MerkleExtension( PATH[1 .. #sizeByteArray(PATH) -Int 1], EXTTREE )], VALUE )
1137
+
1138
+ rule #merkleExtensionSplitter( PATH, P1, TREE, P2, VALUE )
1139
+ => #merkleExtensionSplitter( PATH ++ ( #asByteStack( P1[0] )[0 .. 1] )
1140
+ , P1[1 .. #sizeByteArray(P1) -Int 1], TREE
1141
+ , P2[1 .. #sizeByteArray(P2) -Int 1], VALUE
1142
+ )
1143
+ [owise]
1144
+
1145
+ rule #merkleExtensionSplitter( PATH, P1, TREE, P2, VALUE )
1146
+ => MerkleExtension( PATH, #merkleExtensionBrancher( MerkleUpdate( .MerkleBranch, P2, VALUE ), P1, TREE ) )
1147
+ requires #sizeByteArray(P1) >Int 0
1148
+ andBool #sizeByteArray(P2) >Int 0
1149
+ andBool P1[0] =/=Int P2[0]
1150
+
1151
+ rule #merkleExtensionSplitter( PATH, P1, TREE, P2, VALUE )
1152
+ => MerkleExtension( PATH, MerkleUpdate( TREE, P2, VALUE ) )
1153
+ requires #sizeByteArray(P1) ==Int 0
1154
+
1155
+ rule #merkleExtensionSplitter( PATH, P1, TREE, P2, VALUE )
1156
+ => MerkleExtension( PATH, #merkleExtensionBrancher( MerkleUpdate( .MerkleBranch, P2, VALUE ), P1, TREE ) )
1157
+ requires #sizeByteArray(P2) ==Int 0
1158
+
958
1159
endmodule
959
1160
```
0 commit comments