34
34
#include < liblangutil/CharStream.h>
35
35
#include < liblangutil/Exceptions.h>
36
36
37
- #include < json/json .h>
37
+ #include < libsolutil/JSON .h>
38
38
39
39
#include < range/v3/algorithm/any_of.hpp>
40
40
#include < range/v3/view/enumerate.hpp>
41
41
42
42
#include < fstream>
43
43
#include < limits>
44
+ #include < iterator>
44
45
45
46
using namespace std ;
46
47
using namespace solidity ;
@@ -74,6 +75,123 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
74
75
}
75
76
}
76
77
78
+ void Assembly::addAssemblyItemsFromJSON (Json::Value const & _code)
79
+ {
80
+ solAssert (m_items.empty ());
81
+ solAssert (_code.isArray ());
82
+ for (auto const & jsonItem: _code)
83
+ m_items.emplace_back (createAssemblyItemFromJSON (jsonItem));
84
+
85
+ for (auto current = m_items.begin (); current != m_items.end (); ++current)
86
+ {
87
+ // During the assembly json export a `JUMPDEST` is always generated after a `tag`.
88
+ // So we just ignore exactly these `JUMPDEST`'s.
89
+ auto const next = std::next (current);
90
+ if (
91
+ next != m_items.end () &&
92
+ current->type () == AssemblyItemType::Tag &&
93
+ next->type () == AssemblyItemType::Operation &&
94
+ next->instruction () == Instruction::JUMPDEST
95
+ )
96
+ m_items.erase (next);
97
+ }
98
+ }
99
+
100
+ AssemblyItem Assembly::createAssemblyItemFromJSON (Json::Value const & _json)
101
+ {
102
+ solAssert (isOfType<string>(_json[" name" ]));
103
+ solAssert (isOfType<int >(_json[" begin" ]));
104
+ solAssert (isOfType<int >(_json[" end" ]));
105
+ solAssert (isOfType<int >(_json[" source" ]));
106
+ solAssert (isOfTypeIfExists<string>(_json, " value" ));
107
+ solAssert (isOfTypeIfExists<int >(_json, " modifierDepth" ));
108
+ solAssert (isOfTypeIfExists<string>(_json, " jumpType" ));
109
+
110
+ string name = getOrDefault<string>(_json[" name" ], " " );
111
+ solAssert (!name.empty ());
112
+
113
+ SourceLocation location;
114
+ location.start = get<int >(_json[" begin" ]);
115
+ location.end = get<int >(_json[" end" ]);
116
+ int srcIndex = get<int >(_json[" source" ]);
117
+ size_t modifierDepth = static_cast <size_t >(getOrDefault<int >(_json[" modifierDepth" ], 0 ));
118
+ string value = getOrDefault<string>(_json[" value" ], " " );
119
+ string jumpType = getOrDefault<string>(_json[" jumpType" ], " " );
120
+
121
+
122
+ auto updateUsedTags = [&](u256 const & data) {
123
+ m_usedTags = max (m_usedTags, static_cast <unsigned >(data) + 1 );
124
+ return data;
125
+ };
126
+
127
+ auto immutableHash = [&](string const & _immutableName) -> h256 {
128
+ h256 hash (util::keccak256 (_immutableName));
129
+ m_immutables[hash] = _immutableName;
130
+ return hash;
131
+ };
132
+
133
+ auto libraryHash = [&](string const & _libraryName) -> h256 {
134
+ h256 hash (util::keccak256 (_libraryName));
135
+ m_libraries[hash] = _libraryName;
136
+ return hash;
137
+ };
138
+
139
+ if (srcIndex > -1 && srcIndex < static_cast <int >(sources ().size ()))
140
+ location.sourceName = sources ()[static_cast <size_t >(srcIndex)];
141
+
142
+ AssemblyItem result (0 );
143
+
144
+ if (c_instructions.count (name))
145
+ {
146
+ AssemblyItem item{c_instructions.at (name), location};
147
+ if (!jumpType.empty ())
148
+ item.setJumpType (jumpType);
149
+ result = item;
150
+ }
151
+ else
152
+ {
153
+ if (name == " PUSH" )
154
+ {
155
+ AssemblyItem item{AssemblyItemType::Push, u256 (" 0x" + value)};
156
+ if (!jumpType.empty ())
157
+ item.setJumpType (jumpType);
158
+ result = item;
159
+ }
160
+ else if (name == " PUSH [ErrorTag]" )
161
+ result = {AssemblyItemType::PushTag, 0 };
162
+ else if (name == " PUSH [tag]" )
163
+ result = {AssemblyItemType::PushTag, updateUsedTags (u256 (value))};
164
+ else if (name == " PUSH [$]" )
165
+ result = {AssemblyItemType::PushSub, u256 (" 0x" + value)};
166
+ else if (name == " PUSH #[$]" )
167
+ result = {AssemblyItemType::PushSubSize, u256 (" 0x" + value)};
168
+ else if (name == " PUSHSIZE" )
169
+ result = {AssemblyItemType::PushProgramSize, 0 };
170
+ else if (name == " PUSHLIB" )
171
+ result = {AssemblyItemType::PushLibraryAddress, libraryHash (value)};
172
+ else if (name == " PUSHDEPLOYADDRESS" )
173
+ result = {AssemblyItemType::PushDeployTimeAddress, 0 };
174
+ else if (name == " PUSHIMMUTABLE" )
175
+ result = {AssemblyItemType::PushImmutable, immutableHash (value)};
176
+ else if (name == " ASSIGNIMMUTABLE" )
177
+ result = {AssemblyItemType::AssignImmutable, immutableHash (value)};
178
+ else if (name == " tag" )
179
+ result = {AssemblyItemType::Tag, updateUsedTags (u256 (value))};
180
+ else if (name == " PUSH data" )
181
+ result = {AssemblyItemType::PushData, u256 (" 0x" + value)};
182
+ else if (name == " VERBATIM" )
183
+ {
184
+ AssemblyItem item (fromHex (value), 0 , 0 );
185
+ result = item;
186
+ }
187
+ else
188
+ assertThrow (false , InvalidOpcode, " " );
189
+ }
190
+ result.setLocation (location);
191
+ result.m_modifierDepth = modifierDepth;
192
+ return result;
193
+ }
194
+
77
195
namespace
78
196
{
79
197
@@ -244,7 +362,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
244
362
jsonItem[" end" ] = item.location ().end ;
245
363
if (item.m_modifierDepth != 0 )
246
364
jsonItem[" modifierDepth" ] = static_cast <int >(item.m_modifierDepth );
247
- std:: string jumpType = item.getJumpTypeAsString ();
365
+ string jumpType = item.getJumpTypeAsString ();
248
366
if (!jumpType.empty ())
249
367
jsonItem[" jumpType" ] = jumpType;
250
368
if (name == " PUSHLIB" )
@@ -286,7 +404,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
286
404
287
405
for (size_t i = 0 ; i < m_subs.size (); ++i)
288
406
{
289
- std:: stringstream hexStr;
407
+ stringstream hexStr;
290
408
hexStr << hex << i;
291
409
data[hexStr.str ()] = m_subs[i]->assemblyJSON (_sourceIndices, /* _includeSourceList = */ false );
292
410
}
@@ -298,6 +416,43 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
298
416
return root;
299
417
}
300
418
419
+ shared_ptr<Assembly> Assembly::loadFromAssemblyJSON (Json::Value const & _json, vector<string> const & _sourceList /* = {} */ , bool _isCreation /* = true */ )
420
+ {
421
+ if (!_json[" .code" ].isArray ())
422
+ return {};
423
+
424
+ shared_ptr<Assembly> result = make_shared<Assembly>(_isCreation, " " );
425
+ vector<string> sourceList;
426
+ if (_sourceList.empty ())
427
+ {
428
+ if (_json.isMember (" sourceList" ))
429
+ for (auto const & it: _json[" sourceList" ])
430
+ sourceList.emplace_back (it.asString ());
431
+ }
432
+ else
433
+ sourceList = _sourceList;
434
+ result->setSources (sourceList);
435
+ result->addAssemblyItemsFromJSON (_json[" .code" ]);
436
+ if (_json[" .auxdata" ].isString ())
437
+ result->m_auxiliaryData = fromHex (_json[" .auxdata" ].asString ());
438
+ Json::Value const & data = _json[" .data" ];
439
+ for (Json::ValueConstIterator itr = data.begin (); itr != data.end (); itr++)
440
+ {
441
+ solAssert (itr.key ().isString (), " " );
442
+ string key = itr.key ().asString ();
443
+ Json::Value const & code = data[key];
444
+ if (code.isString ())
445
+ result->m_data [h256 (fromHex (key))] = fromHex (code.asString ());
446
+ else
447
+ {
448
+ shared_ptr<Assembly> subassembly (Assembly::loadFromAssemblyJSON (code, sourceList, /* isCreation = */ false ));
449
+ assertThrow (subassembly, AssemblyException, " " );
450
+ result->m_subs .emplace_back (make_shared<Assembly>(*subassembly));
451
+ }
452
+ }
453
+ return result;
454
+ }
455
+
301
456
AssemblyItem Assembly::namedTag (string const & _name, size_t _params, size_t _returns, optional<uint64_t > _sourceID)
302
457
{
303
458
assertThrow (!_name.empty (), AssemblyException, " Empty named tag." );
@@ -341,7 +496,7 @@ Assembly& Assembly::optimise(OptimiserSettings const& _settings)
341
496
342
497
map<u256, u256> const & Assembly::optimiseInternal (
343
498
OptimiserSettings const & _settings,
344
- std:: set<size_t > _tagsReferencedFromOutside
499
+ set<size_t > _tagsReferencedFromOutside
345
500
)
346
501
{
347
502
if (m_tagReplacements)
0 commit comments