@@ -74,6 +74,117 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
74
74
}
75
75
}
76
76
77
+ void Assembly::addAssemblyItemsFromJSON (Json::Value const & _code)
78
+ {
79
+ solAssert (_code.isArray (), " " );
80
+ for (auto const & jsonItem: _code)
81
+ m_items.emplace_back (loadItemFromJSON (jsonItem));
82
+
83
+ for (auto current = m_items.begin (); current != m_items.end (); ++current)
84
+ {
85
+ // During the assembly json export a `JUMPDEST` is always generated after a `tag`.
86
+ // So we just ignore exactly these `JUMPDEST`'s.
87
+ auto const next = std::next (current);
88
+ if (
89
+ next != m_items.end () &&
90
+ current->type () == AssemblyItemType::Tag &&
91
+ next->type () == AssemblyItemType::Operation &&
92
+ next->instruction () == Instruction::JUMPDEST
93
+ )
94
+ m_items.erase (next);
95
+ }
96
+ }
97
+
98
+ AssemblyItem Assembly::loadItemFromJSON (Json::Value const & _json)
99
+ {
100
+ std::string name = _json[" name" ].isString () ? _json[" name" ].asString () : " " ;
101
+ int begin = _json[" begin" ].isInt () ? _json[" begin" ].asInt () : -1 ;
102
+ int end = _json[" end" ].isInt () ? _json[" end" ].asInt () : -1 ;
103
+ int srcIndex = _json[" source" ].isInt () ? _json[" source" ].asInt () : -1 ;
104
+ size_t modifierDepth = _json[" modifierDepth" ].isInt () ? static_cast <size_t >(_json[" modifierDepth" ].asInt ()) : 0 ;
105
+ std::string value = _json[" value" ].isString () ? _json[" value" ].asString () : " " ;
106
+ std::string jumpType = _json[" jumpType" ].isString () ? _json[" jumpType" ].asString () : " " ;
107
+ solAssert (!name.empty (), " " );
108
+
109
+ auto updateUsedTags = [&](u256 const & data) {
110
+ auto tag = static_cast <unsigned >(data);
111
+ if (m_usedTags <= tag)
112
+ m_usedTags = tag + 1 ;
113
+ return data;
114
+ };
115
+
116
+ auto immutableHash = [&](string const & _immutableName) -> h256 {
117
+ h256 hash (util::keccak256 (value));
118
+ m_immutables[hash] = _immutableName;
119
+ return hash;
120
+ };
121
+
122
+ auto libraryHash = [&](string const & _libraryName) -> h256 {
123
+ h256 hash (util::keccak256 (value));
124
+ m_libraries[hash] = _libraryName;
125
+ return hash;
126
+ };
127
+
128
+ SourceLocation location;
129
+ location.start = begin;
130
+ location.end = end;
131
+ if (srcIndex > -1 && srcIndex < static_cast <int >(sources ().size ()))
132
+ location.sourceName = sources ()[static_cast <size_t >(srcIndex)];
133
+
134
+ AssemblyItem result (0 );
135
+
136
+ if (c_instructions.find (name) != c_instructions.end ())
137
+ {
138
+ AssemblyItem item{c_instructions.at (name), location};
139
+ item.m_modifierDepth = modifierDepth;
140
+ if (!jumpType.empty ())
141
+ item.setJumpType (jumpType);
142
+ result = item;
143
+ }
144
+ else
145
+ {
146
+ if (name == " PUSH" )
147
+ {
148
+ AssemblyItem item{AssemblyItemType::Push, u256 (" 0x" + value), location};
149
+ if (!jumpType.empty ())
150
+ item.setJumpType (jumpType);
151
+ result = item;
152
+ }
153
+ else if (name == " PUSH [ErrorTag]" )
154
+ result = {AssemblyItemType::PushTag, 0 , location};
155
+ else if (name == " PUSH [tag]" )
156
+ result = {AssemblyItemType::PushTag, updateUsedTags (u256 (value)), location};
157
+ else if (name == " PUSH [$]" )
158
+ result = {AssemblyItemType::PushSub, u256 (" 0x" + value), location};
159
+ else if (name == " PUSH #[$]" )
160
+ result = {AssemblyItemType::PushSubSize, u256 (" 0x" + value), location};
161
+ else if (name == " PUSHSIZE" )
162
+ result = {AssemblyItemType::PushProgramSize, 0 , location};
163
+ else if (name == " PUSHLIB" )
164
+ result = {AssemblyItemType::PushLibraryAddress, libraryHash (value), location};
165
+ else if (name == " PUSHDEPLOYADDRESS" )
166
+ result = {AssemblyItemType::PushDeployTimeAddress, 0 , location};
167
+ else if (name == " PUSHIMMUTABLE" )
168
+ result = {AssemblyItemType::PushImmutable, immutableHash (value), location};
169
+ else if (name == " ASSIGNIMMUTABLE" )
170
+ result = {AssemblyItemType::AssignImmutable, immutableHash (value), location};
171
+ else if (name == " tag" )
172
+ result = {AssemblyItemType::Tag, updateUsedTags (u256 (value)), location};
173
+ else if (name == " PUSH data" )
174
+ result = {AssemblyItemType::PushData, u256 (" 0x" + value), location};
175
+ else if (name == " VERBATIM" )
176
+ {
177
+ AssemblyItem item (fromHex (value), 0 , 0 );
178
+ item.setLocation (location);
179
+ result = item;
180
+ }
181
+ else
182
+ assertThrow (false , InvalidOpcode, " " );
183
+ }
184
+ result.m_modifierDepth = modifierDepth;
185
+ return result;
186
+ }
187
+
77
188
namespace
78
189
{
79
190
@@ -299,6 +410,43 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
299
410
return root;
300
411
}
301
412
413
+ bool Assembly::loadFromAssemblyJSON (Json::Value const & _json, bool _loadSources /* = true */ )
414
+ {
415
+ if (!_json[" .code" ].isArray ())
416
+ return false ;
417
+ bool success{true };
418
+
419
+ if (_loadSources)
420
+ {
421
+ vector<string> sourceList;
422
+ if (_json.isMember (" sourceList" ))
423
+ for (auto const & it: _json[" sourceList" ])
424
+ sourceList.emplace_back (it.asString ());
425
+ setSources (sourceList);
426
+ }
427
+
428
+ addAssemblyItemsFromJSON (_json[" .code" ]);
429
+ if (_json[" .auxdata" ].isString ())
430
+ m_auxiliaryData = fromHex (_json[" .auxdata" ].asString ());
431
+ Json::Value const & data = _json[" .data" ];
432
+ for (Json::ValueConstIterator itr = data.begin (); itr != data.end (); itr++)
433
+ {
434
+ solAssert (itr.key ().isString (), " " );
435
+ std::string key = itr.key ().asString ();
436
+ Json::Value const & code = data[key];
437
+ if (code.isString ())
438
+ m_data[h256 (fromHex (key))] = fromHex (code.asString ());
439
+ else
440
+ {
441
+ shared_ptr<Assembly> subassembly = make_shared<Assembly>(false , " " );
442
+ subassembly->setSources (sources ());
443
+ success &= subassembly->loadFromAssemblyJSON (code, false );
444
+ m_subs.emplace_back (subassembly);
445
+ }
446
+ }
447
+ return success;
448
+ }
449
+
302
450
AssemblyItem Assembly::namedTag (string const & _name, size_t _params, size_t _returns, optional<uint64_t > _sourceID)
303
451
{
304
452
assertThrow (!_name.empty (), AssemblyException, " Empty named tag." );
0 commit comments