@@ -74,6 +74,117 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
7474 }
7575}
7676
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+
77188namespace
78189{
79190
@@ -299,6 +410,43 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
299410 return root;
300411}
301412
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+
302450AssemblyItem Assembly::namedTag (string const & _name, size_t _params, size_t _returns, optional<uint64_t > _sourceID)
303451{
304452 assertThrow (!_name.empty (), AssemblyException, " Empty named tag." );
0 commit comments