diff --git a/API.md b/API.md index 58677c97..5b58ef2d 100644 --- a/API.md +++ b/API.md @@ -60,6 +60,9 @@ contract development. * [\.set()](#optionaltypeset) * [\.reset()](#optionaltypereset) * [Keyword `null`](#keyword-null) + * [variant](#variant) + * [variant.isUint()](#variantisuint) + * [variant.toUint()](#varianttouint) * [vector(Type)](#vectortype) * [\.push(Type)](#vectortypepushtype) * [\.pop()](#vectortypepop) @@ -68,6 +71,7 @@ contract development. * [TON specific control structures](#ton-specific-control-structures) * [Range-based for loop](#range-based-for-loop) * [repeat](#repeat) + * [try-catch](#trycatch) * [Changes and extensions in Solidity types](#changes-and-extensions-in-solidity-types) * [Integers](#integers) * [bitSize() and uBitSize()](#bitsize-and-ubitsize) @@ -893,7 +897,7 @@ Replaces content of the `optional` with **value**. .reset(); ``` -Deletes contents of the `optional`. +Deletes content of the `optional`. ##### Keyword `null` @@ -905,6 +909,22 @@ optional(uint) x = 123; x = null; // reset value ``` +#### variant + +The `variant` type acts like a union for the most common solidity data types. Supported only `uint` so far. + +#### variant.isUint() + +```TVMSolidity +.isUint() returns (bool) +``` + +Checks whether `` holds `uint` type. + +#### variant.toUint() + +Converts `` to `uint` type if it's possible. Otherwise, throws an exception with code `77`. + #### vector(Type) `vector(Type)` is a template container type capable of storing an arbitrary set of values of a @@ -1053,6 +1073,45 @@ repeat(a - 1) { // a == 1 ``` +#### try-catch + +It is an experimental feature available only in certain blockchain networks. + +The `try` statement allows you to define a block of code to be tested for errors while it is executed. The +`catch` statement allows you to define a block of code to be executed, if an error occurs in the try block. +`catch` block gets two parameters of type variant and uint, whick contain exception argument and code respectively. +Example: + +```TVMSolidity +TvmBuilder builder; +uint c = 0; +try { + c = a + b; + require(c != 42, 100, 22); + require(c != 43, 100, 33); + builder.store(c); +} catch (variant value, uint errorCode) { + uint errorValue; + if (value.isUint()) { + errorValue = value.toUint(); + } + + if (errorCode == 100) { + if (errorValue == 22) { + // it was line: `require(c != 42, 100, 22);` + } else if (errorValue == 33) { + // it was line: `require(c != 43, 100, 33);` + } + } else if (errorCode == 8) { + // Cell overflow + // It was line: `builder.store(c);` + } else if (errorCode == 4) { + // Integer overflow + // It was line: `c = a + b;` + } +} +``` + ### Changes and extensions in Solidity types #### Integers @@ -4386,6 +4445,7 @@ Solidity runtime error codes: * **74** - Await answer message has wrong source address. * **75** - Await answer message has wrong function id. * **76** - Public function was called before constructor. +* **77** - It's impossible to convert `variant` type to target type. See [variant.toUint()](#varianttouint) ### Division and rounding diff --git a/Changelog_TON.md b/Changelog_TON.md index 1679e760..d3c9abf9 100644 --- a/Changelog_TON.md +++ b/Changelog_TON.md @@ -1,3 +1,15 @@ +### 0.64.0 (2022-08-18) + +Fixed build [sold](https://github.com/tonlabs/TON-Solidity-Compiler/tree/master/sold) for Windows and macOS. + +Compiler features: + * Supported [ABI v2.3](https://github.com/tonlabs/ton-labs-abi/blob/master/docs/ABI_2.3_spec.md). + * Supported try-catch (experimental feature). + * Supported type `variant`. + +Typo: + * Rename function `storeZeros` -> `storeZeroes`. + ### 0.63.0 (2022-07-27) Compiler features: diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index d05cf43a..c1237d8a 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -10,7 +10,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.63.0") +set(PROJECT_VERSION "0.64.0") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) include(TestBigEndian) diff --git a/compiler/liblangutil/Token.h b/compiler/liblangutil/Token.h index f56d5d4b..9feb7351 100644 --- a/compiler/liblangutil/Token.h +++ b/compiler/liblangutil/Token.h @@ -249,6 +249,7 @@ namespace solidity::langutil K(TvmSlice, "TvmSlice", 0) \ K(TvmBuilder, "TvmBuilder", 0) \ K(ExtraCurrencyCollection, "ExtraCurrencyCollection", 0) \ + K(Variant, "variant", 0) \ K(Fixed, "fixed", 0) \ K(UFixed, "ufixed", 0) \ T(IntM, "intM", 0) \ diff --git a/compiler/libsolidity/analysis/ControlFlowBuilder.cpp b/compiler/libsolidity/analysis/ControlFlowBuilder.cpp index 23b844c5..3dbdc219 100644 --- a/compiler/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/compiler/libsolidity/analysis/ControlFlowBuilder.cpp @@ -87,11 +87,10 @@ bool ControlFlowBuilder::visit(Conditional const& _conditional) bool ControlFlowBuilder::visit(TryStatement const& _tryStatement) { - appendControlFlow(_tryStatement.externalCall()); + appendControlFlow(_tryStatement.body()); - auto nodes = splitFlow(_tryStatement.clauses().size()); - for (size_t i = 0; i < _tryStatement.clauses().size(); ++i) - nodes[i] = createFlow(nodes[i], _tryStatement.clauses()[i]->block()); + auto nodes = splitFlow(1); + nodes[0] = createFlow(nodes[0], _tryStatement.clause().block()); mergeFlow(nodes); return false; diff --git a/compiler/libsolidity/analysis/TypeChecker.cpp b/compiler/libsolidity/analysis/TypeChecker.cpp index 24460c6f..c146a3cd 100644 --- a/compiler/libsolidity/analysis/TypeChecker.cpp +++ b/compiler/libsolidity/analysis/TypeChecker.cpp @@ -1026,134 +1026,24 @@ bool TypeChecker::visit(IfStatement const& _ifStatement) void TypeChecker::endVisit(TryStatement const& _tryStatement) { - m_errorReporter.fatalTypeError( - _tryStatement.location(), - "Try-catch statement is not supported yet." - ); - - FunctionCall const* externalCall = dynamic_cast(&_tryStatement.externalCall()); - if (!externalCall || externalCall->annotation().kind != FunctionCallKind::FunctionCall) - { - m_errorReporter.typeError( - _tryStatement.externalCall().location(), - "Try can only be used with external function calls and contract creation calls." - ); - return; - } - - FunctionType const& functionType = dynamic_cast(*externalCall->expression().annotation().type); - if ( - functionType.kind() != FunctionType::Kind::External && - functionType.kind() != FunctionType::Kind::Creation && - functionType.kind() != FunctionType::Kind::DelegateCall - ) - { - m_errorReporter.typeError( - _tryStatement.externalCall().location(), - "Try can only be used with external function calls and contract creation calls." - ); - return; - } - - externalCall->annotation().tryCall = true; - - solAssert(_tryStatement.clauses().size() >= 2, ""); - solAssert(_tryStatement.clauses().front(), ""); - - TryCatchClause const& successClause = *_tryStatement.clauses().front(); - if (successClause.parameters()) - { - TypePointers returnTypes = - m_evmVersion.supportsReturndata() ? - functionType.returnParameterTypes() : - functionType.returnParameterTypesWithoutDynamicTypes(); - std::vector> const& parameters = - successClause.parameters()->parameters(); - if (returnTypes.size() != parameters.size()) - m_errorReporter.typeError( - successClause.location(), - "Function returns " + - to_string(functionType.returnParameterTypes().size()) + - " values, but returns clause has " + - to_string(parameters.size()) + - " variables." - ); - size_t len = min(returnTypes.size(), parameters.size()); - for (size_t i = 0; i < len; ++i) - { - solAssert(returnTypes[i], ""); - if (parameters[i] && *parameters[i]->annotation().type != *returnTypes[i]) - m_errorReporter.typeError( - parameters[i]->location(), - "Invalid type, expected " + - returnTypes[i]->toString(false) + - " but got " + - parameters[i]->annotation().type->toString() + - "." - ); - } - } - - TryCatchClause const* errorClause = nullptr; - TryCatchClause const* lowLevelClause = nullptr; - for (size_t i = 1; i < _tryStatement.clauses().size(); ++i) - { - TryCatchClause const& clause = *_tryStatement.clauses()[i]; - if (clause.errorName() == "") - { - if (lowLevelClause) - m_errorReporter.typeError( - clause.location(), - SecondarySourceLocation{}.append("The first clause is here:", lowLevelClause->location()), - "This try statement already has a low-level catch clause." - ); - lowLevelClause = &clause; - if (clause.parameters() && !clause.parameters()->parameters().empty()) - { - if ( - clause.parameters()->parameters().size() != 1 || - *clause.parameters()->parameters().front()->type() != *TypeProvider::bytesMemory() - ) - m_errorReporter.typeError(clause.location(), "Expected `catch (bytes memory ...) { ... }` or `catch { ... }`."); - if (!m_evmVersion.supportsReturndata()) - m_errorReporter.typeError( - clause.location(), - "This catch clause type cannot be used on the selected EVM version (" + - m_evmVersion.name() + - "). You need at least a Byzantium-compatible EVM or use `catch { ... }`." - ); - } - } - else if (clause.errorName() == "Error") - { - if (!m_evmVersion.supportsReturndata()) - m_errorReporter.typeError( - clause.location(), - "This catch clause type cannot be used on the selected EVM version (" + - m_evmVersion.name() + - "). You need at least a Byzantium-compatible EVM or use `catch { ... }`." - ); - - if (errorClause) - m_errorReporter.typeError( - clause.location(), - SecondarySourceLocation{}.append("The first clause is here:", errorClause->location()), - "This try statement already has an \"Error\" catch clause." - ); - errorClause = &clause; - if ( - !clause.parameters() || - clause.parameters()->parameters().size() != 1 || - *clause.parameters()->parameters().front()->type() != *TypeProvider::stringMemory() - ) - m_errorReporter.typeError(clause.location(), "Expected `catch Error(string memory ...) { ... }`."); - } - else - m_errorReporter.typeError( - clause.location(), - "Invalid catch clause name. Expected either `catch (...)` or `catch Error(...)`." - ); - } + TryCatchClause const& clause = _tryStatement.clause(); + std::vector> const& errArgs = clause.parameters()->parameters(); + + auto printError = [&](SourceLocation const& loc){ + m_errorReporter.typeError( + loc, + "Expected `catch (variant value, uint number) { ... }`."); + }; + if (errArgs.size() != 2) { + printError(clause.location()); + return; + } + if (*errArgs.at(0)->type() != *TypeProvider::variant()) { + printError(errArgs.at(0)->location()); + } + if (*errArgs.at(1)->type() != *TypeProvider::uint256()) { + printError(errArgs.at(1)->location()); + } } bool TypeChecker::visit(WhileStatement const& _whileStatement) diff --git a/compiler/libsolidity/ast/AST.h b/compiler/libsolidity/ast/AST.h index 8adaf2c2..d805155a 100644 --- a/compiler/libsolidity/ast/AST.h +++ b/compiler/libsolidity/ast/AST.h @@ -1431,22 +1431,22 @@ class TryStatement: public Statement int64_t _id, SourceLocation const& _location, ASTPointer const& _docString, - ASTPointer const& _externalCall, - std::vector> const& _clauses + ASTPointer _body, + ASTPointer _clause ): Statement(_id, _location, _docString), - m_externalCall(_externalCall), - m_clauses(_clauses) + m_body(_body), + m_clause(_clause) {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; - Expression const& externalCall() const { return *m_externalCall; } - std::vector> const& clauses() const { return m_clauses; } + Block const& body() const { return *m_body; } + TryCatchClause const& clause() const { return *m_clause; } private: - ASTPointer m_externalCall; - std::vector> m_clauses; + ASTPointer m_body; + ASTPointer m_clause; }; /** diff --git a/compiler/libsolidity/ast/ASTJsonConverter.cpp b/compiler/libsolidity/ast/ASTJsonConverter.cpp index eaaf204f..109564a3 100644 --- a/compiler/libsolidity/ast/ASTJsonConverter.cpp +++ b/compiler/libsolidity/ast/ASTJsonConverter.cpp @@ -530,8 +530,8 @@ bool ASTJsonConverter::visit(TryCatchClause const& _node) bool ASTJsonConverter::visit(TryStatement const& _node) { setJsonNode(_node, "TryStatement", { - make_pair("externalCall", toJson(_node.externalCall())), - make_pair("clauses", toJson(_node.clauses())) + make_pair("body", toJson(_node.body())), + make_pair("clause", toJson(_node.clause())) }); return false; } diff --git a/compiler/libsolidity/ast/ASTJsonImporter.cpp b/compiler/libsolidity/ast/ASTJsonImporter.cpp index bffeaced..119cf9c8 100644 --- a/compiler/libsolidity/ast/ASTJsonImporter.cpp +++ b/compiler/libsolidity/ast/ASTJsonImporter.cpp @@ -578,16 +578,14 @@ ASTPointer ASTJsonImporter::createTryCatchClause(Json::Value con ASTPointer ASTJsonImporter::createTryStatement(Json::Value const& _node) { - vector> clauses; - - for (auto& param: _node["clauses"]) - clauses.emplace_back(createTryCatchClause(param)); + ASTPointer body = createBlock(_node["block"]); + ASTPointer clause = createTryCatchClause(_node["clause"]); return createASTNode( _node, nullOrASTString(_node, "documentation"), - convertJsonToASTNode(member(_node, "externalCall")), - clauses + body, + clause ); } diff --git a/compiler/libsolidity/ast/AST_accept.h b/compiler/libsolidity/ast/AST_accept.h index 3458f8b3..d47a8e42 100644 --- a/compiler/libsolidity/ast/AST_accept.h +++ b/compiler/libsolidity/ast/AST_accept.h @@ -566,8 +566,8 @@ void TryStatement::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) { - m_externalCall->accept(_visitor); - listAccept(m_clauses, _visitor); + m_body->accept(_visitor); + m_clause->accept(_visitor); } _visitor.endVisit(*this); } @@ -576,8 +576,8 @@ void TryStatement::accept(ASTConstVisitor& _visitor) const { if (_visitor.visit(*this)) { - m_externalCall->accept(_visitor); - listAccept(m_clauses, _visitor); + m_body->accept(_visitor); + m_clause->accept(_visitor); } _visitor.endVisit(*this); } diff --git a/compiler/libsolidity/ast/TypeProvider.cpp b/compiler/libsolidity/ast/TypeProvider.cpp index def69a21..0c696cf2 100644 --- a/compiler/libsolidity/ast/TypeProvider.cpp +++ b/compiler/libsolidity/ast/TypeProvider.cpp @@ -40,6 +40,7 @@ unique_ptr TypeProvider::m_bytesStorage; unique_ptr TypeProvider::m_bytesMemory; unique_ptr TypeProvider::m_bytesCalldata; unique_ptr TypeProvider::m_stringStorage; +unique_ptr TypeProvider::m_variant; unique_ptr TypeProvider::m_stringMemory; TupleType const TypeProvider::m_emptyTuple{}; @@ -646,6 +647,7 @@ void TypeProvider::reset() clearCache(m_bytesMemory); clearCache(m_bytesCalldata); clearCache(m_stringStorage); + clearCache(m_variant); clearCache(m_stringMemory); clearCache(m_emptyTuple); clearCache(m_address); @@ -724,6 +726,8 @@ Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& return bytesStorage(); case Token::String: return stringStorage(); + case Token::Variant: + return variant(); default: solAssert( false, @@ -793,6 +797,13 @@ ArrayType const* TypeProvider::stringStorage() return m_stringStorage.get(); } +Variant const* TypeProvider::variant() +{ + if (!m_variant) + m_variant = make_unique(); + return m_variant.get(); +} + ArrayType const* TypeProvider::stringMemory() { if (!m_stringMemory) diff --git a/compiler/libsolidity/ast/TypeProvider.h b/compiler/libsolidity/ast/TypeProvider.h index b50a9b9b..a6bbda32 100644 --- a/compiler/libsolidity/ast/TypeProvider.h +++ b/compiler/libsolidity/ast/TypeProvider.h @@ -72,6 +72,7 @@ class TypeProvider static ArrayType const* bytesMemory(); static ArrayType const* bytesCalldata(); static ArrayType const* stringStorage(); + static Variant const* variant(); static ArrayType const* stringMemory(); /// Constructor for a byte array ("bytes") and string. @@ -225,6 +226,7 @@ class TypeProvider static std::unique_ptr m_bytesMemory; static std::unique_ptr m_bytesCalldata; static std::unique_ptr m_stringStorage; + static std::unique_ptr m_variant; static std::unique_ptr m_stringMemory; static TupleType const m_emptyTuple; diff --git a/compiler/libsolidity/ast/Types.cpp b/compiler/libsolidity/ast/Types.cpp index 195ff0f0..5190ca66 100644 --- a/compiler/libsolidity/ast/Types.cpp +++ b/compiler/libsolidity/ast/Types.cpp @@ -2952,6 +2952,9 @@ string FunctionType::richIdentifier() const case Kind::TXtimestamp: id += "txtimestamp"; break; + case Kind::VariantIsUint: id += "variantisuint"; break; + case Kind::VariantToUint: id += "varianttouint"; break; + case Kind::ExtraCurrencyCollectionMethods: id += "extracurrencycollectionmethods"; break; case Kind::MsgPubkey: id += "msgpubkey"; break; case Kind::AddressIsZero: id += "addressiszero"; break; @@ -4895,6 +4898,29 @@ MemberList::MemberMap TvmCellType::nativeMembers(const ContractDefinition *) con return members; } +MemberList::MemberMap Variant::nativeMembers(ContractDefinition const* /*_currentScope*/) const { + MemberList::MemberMap members; + members.emplace_back("isUint", TypeProvider::function( + {}, + {TypeProvider::boolean()}, + {}, + {{}}, + FunctionType::Kind::VariantIsUint, + false, + StateMutability::Pure + )); + members.emplace_back("toUint", TypeProvider::function( + {}, + {TypeProvider::uint256()}, + {}, + {{}}, + FunctionType::Kind::VariantToUint, + false, + StateMutability::Pure + )); + return members; +} + TypeResult TvmVectorType::unaryOperatorResult(Token _operator) const { if (_operator == Token::Delete) return TypeProvider::emptyTuple(); @@ -5077,7 +5103,7 @@ MemberList::MemberMap TvmBuilderType::nativeMembers(const ContractDefinition *) false, StateMutability::Pure )); - for (const std::string func : {"storeOnes", "storeZeros"}) { + for (const std::string func : {"storeOnes", "storeZeroes"}) { members.emplace_back(func, TypeProvider::function( {TypeProvider::uint256()}, {}, diff --git a/compiler/libsolidity/ast/Types.h b/compiler/libsolidity/ast/Types.h index 2374208f..2c41d991 100644 --- a/compiler/libsolidity/ast/Types.h +++ b/compiler/libsolidity/ast/Types.h @@ -160,7 +160,7 @@ class Type Address, Integer, RationalNumber, StringLiteral, Bool, FixedPoint, Array, ArraySlice, FixedBytes, Contract, Struct, Function, Enum, Tuple, Mapping, TypeType, Modifier, Magic, Module, - InaccessibleDynamic, TvmCell, TvmSlice, TvmBuilder, ExtraCurrencyCollection, TvmVector, + InaccessibleDynamic, TvmCell, TvmSlice, TvmBuilder, ExtraCurrencyCollection, TvmVector, Variant, VarInteger, InitializerList, CallList, // <-- variables of that types can't be declared in solidity contract Optional, Null, // null @@ -639,6 +639,22 @@ class TvmCellType: public Type MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; }; +/** + * The variant type that can store only `uint` type so far + */ +class Variant: public Type +{ +public: + Variant() = default; + Category category() const override { return Category::Variant; } + bool isValueType() const override { return true; } + std::string richIdentifier() const override { return "t_variant"; } + std::string toString(bool) const override { return "variant"; } + TypePointer encodingType() const override { return this; } + TypeResult interfaceType(bool) const override { return this; } + MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; +}; + /** * The TVM Tuple type. */ @@ -1174,6 +1190,9 @@ class FunctionType: public Type AddressType, ///< address.getType() for address AddressUnpack, ///< address.unpack() for address + VariantIsUint, + VariantToUint, + TVMCellDepth, ///< cell.depth() TVMCellToSlice, ///< cell.toSlice() TVMDataSize, ///< cell.dataSize() diff --git a/compiler/libsolidity/codegen/StackOptimizer.cpp b/compiler/libsolidity/codegen/StackOptimizer.cpp index e320d5cd..9a88d889 100644 --- a/compiler/libsolidity/codegen/StackOptimizer.cpp +++ b/compiler/libsolidity/codegen/StackOptimizer.cpp @@ -143,6 +143,18 @@ bool StackOptimizer::visit(CodeBlock &_node) { for (size_t i = 0; i < instructions.size(); ) { if (successfullyUpdate(i, instructions)) { m_didSome = true; + + //Printer p{std::cout}; + //std::cout << i << "\n"; + //std::cout << "<<<<<\n"; + //for (const auto& x : _node.instructions()) + // x->accept(p); + //std::cout << "=====\n"; + //for (const auto& x : instructions) + // x->accept(p); + //std::cout << ">>>>>\n"; + //_node.upd(instructions); + // do nothing } else { Pointer const& op = instructions.at(i); @@ -219,6 +231,26 @@ bool StackOptimizer::visit(TvmUntil &_node) { return false; } +bool StackOptimizer::visit(TryCatch &_node) { + const int savedStack = size(); + + // try body + startScope(); + _node.tryBody()->accept(*this); + endScope(); + solAssert(savedStack == size(), ""); + + // catch body + startScope(); + delta(2); // 2 error variables + _node.catchBody()->accept(*this); + solAssert(savedStack == size(), ""); + endScope(); + + solAssert(savedStack == size(), ""); + return false; +} + bool StackOptimizer::visit(While &_node) { int savedStack = size(); @@ -325,6 +357,9 @@ bool StackOptimizer::successfullyUpdate(int index, std::vector + // DROP if (!ok && isPOP(op)) { int startStackSize = isPOP(op).value(); Simulator sim{instructions.begin() + index + 1, instructions.end(), startStackSize, 1}; diff --git a/compiler/libsolidity/codegen/StackOptimizer.hpp b/compiler/libsolidity/codegen/StackOptimizer.hpp index 51faa15b..1313cf4f 100644 --- a/compiler/libsolidity/codegen/StackOptimizer.hpp +++ b/compiler/libsolidity/codegen/StackOptimizer.hpp @@ -40,6 +40,7 @@ namespace solidity::frontend { bool visit(TvmIfElse &_node) override; bool visit(TvmRepeat &_node) override; bool visit(TvmUntil &_node) override; + bool visit(TryCatch &_node) override; bool visit(While &_node) override; bool visit(Function &_node) override; bool visit(Contract &_node) override; diff --git a/compiler/libsolidity/codegen/TVMABI.cpp b/compiler/libsolidity/codegen/TVMABI.cpp index bac9055f..38220444 100644 --- a/compiler/libsolidity/codegen/TVMABI.cpp +++ b/compiler/libsolidity/codegen/TVMABI.cpp @@ -100,7 +100,7 @@ Json::Value TVMABI::generateABIJson( Json::Value root(Json::objectValue); root["ABI version"] = 2; - root["version"] = "2.2"; + root["version"] = "2.3"; // header { @@ -589,7 +589,7 @@ ChainDataDecoder::ChainDataDecoder(StackPusher *pusher) : int ChainDataDecoder::maxBits(bool isResponsible) { // external inbound message - int maxUsed = 1 + 512 + // signature + int maxUsed = TvmConst::Abi::MaxOptionalSignLength + (pusher->ctx().pragmaHelper().hasPubkey()? 1 + 256 : 0) + (pusher->ctx().hasTimeInAbiHeader()? 64 : 0) + (pusher->ctx().pragmaHelper().hasExpire()? 32 : 0) + diff --git a/compiler/libsolidity/codegen/TVMAnalyzer.cpp b/compiler/libsolidity/codegen/TVMAnalyzer.cpp index 2764cbb7..ffd759c6 100644 --- a/compiler/libsolidity/codegen/TVMAnalyzer.cpp +++ b/compiler/libsolidity/codegen/TVMAnalyzer.cpp @@ -327,6 +327,11 @@ bool ContactsUsageScanner::visit(const FunctionDefinition &fd) { return true; } +bool ContactsUsageScanner::visit(TryStatement const& ) { + m_hasTryCatch = true; + return true; +} + bool withPrelocatedRetValues(const FunctionDefinition *f) { LocationReturn locationReturn = ::notNeedsPushContWhenInlining(f->body()); if (!f->returnParameters().empty() && isIn(locationReturn, LocationReturn::noReturn, LocationReturn::Anywhere)) { diff --git a/compiler/libsolidity/codegen/TVMAnalyzer.hpp b/compiler/libsolidity/codegen/TVMAnalyzer.hpp index 19c10acc..a58cf3dc 100644 --- a/compiler/libsolidity/codegen/TVMAnalyzer.hpp +++ b/compiler/libsolidity/codegen/TVMAnalyzer.hpp @@ -75,11 +75,13 @@ class ContactsUsageScanner: public ASTConstVisitor bool visit(FunctionCall const& _functionCall) override; bool visit(MemberAccess const &_node) override; bool visit(FunctionDefinition const& fd) override; + bool visit(TryStatement const& fd) override; bool hasMsgPubkey() const { return m_hasMsgPubkey; } bool hasMsgSender() const { return m_hasMsgSender; } bool hasResponsibleFunction() const { return m_hasResponsibleFunction; } bool hasAwaitCall() const { return m_hasAwaitCall; } + bool hasTryCatch() const { return m_hasTryCatch; } std::set const& awaitFunctions() const { return m_awaitFunctions; } private: @@ -87,6 +89,7 @@ class ContactsUsageScanner: public ASTConstVisitor bool m_hasMsgSender{}; bool m_hasResponsibleFunction{}; bool m_hasAwaitCall{}; + bool m_hasTryCatch{}; std::set m_usedFunctions; std::set m_awaitFunctions; }; @@ -110,7 +113,8 @@ static bool doesAlways(const Statement* st) { to(st) || to(st) || to(st) || - to(st) + to(st) || + to(st) ) return false; if (auto block = to(st)) { diff --git a/compiler/libsolidity/codegen/TVMConstants.hpp b/compiler/libsolidity/codegen/TVMConstants.hpp index e0888cf4..806833f1 100644 --- a/compiler/libsolidity/codegen/TVMConstants.hpp +++ b/compiler/libsolidity/codegen/TVMConstants.hpp @@ -67,6 +67,10 @@ namespace TvmConst { // header mask (3 bit), optional signBoxHandle (33 bit). const int MAX_HASH_MAP_INFO_ABOUT_KEY = 2 + 10; // hml_long$10 + log2(1023) + namespace Abi { + const int MaxOptionalSignLength = 591; // it's max MsgAddressInt + } + namespace RuntimeException { const int BadSignature = 40; const int ArrayIndexOutOfRange = 50; @@ -94,6 +98,7 @@ namespace TvmConst { const int WrongAwaitAddress = 74; const int WrongAwaitFuncId = 75; const int CallThatWasBeforeCtorCall = 76; + const int BadVariant = 77; } namespace FunctionId { diff --git a/compiler/libsolidity/codegen/TVMContractCompiler.cpp b/compiler/libsolidity/codegen/TVMContractCompiler.cpp index f854bcee..365ebcba 100644 --- a/compiler/libsolidity/codegen/TVMContractCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMContractCompiler.cpp @@ -105,7 +105,6 @@ Pointer TVMConstructorCompiler::generateConstructors() { ChainDataDecoder{&m_pusher}.decodeFunctionParameters(types, false); m_pusher.getStack().change(-static_cast(constructor->parameters().size())); for (const ASTPointer& variable: constructor->parameters()) { - auto name = variable->name(); m_pusher.getStack().add(variable.get(), true); } } diff --git a/compiler/libsolidity/codegen/TVMFunctionCall.cpp b/compiler/libsolidity/codegen/TVMFunctionCall.cpp index 5562c23d..a44431a8 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCall.cpp +++ b/compiler/libsolidity/codegen/TVMFunctionCall.cpp @@ -126,6 +126,8 @@ void FunctionCallCompiler::compile() { addressMethod(); } else if (category == Type::Category::TvmCell) { cellMethods(*ma); + } else if (category == Type::Category::Variant) { + variantMethods(*ma); } else if (isSuper(&ma->expression())) { superFunctionCall(*ma); } else if (category == Type::Category::TypeType) { @@ -768,7 +770,7 @@ void FunctionCallCompiler::generateExtInboundMsg( } m_pusher.push(+1, "NEWC"); - builderSize += 1 + 512; + builderSize += TvmConst::Abi::MaxOptionalSignLength; if (addSignature) { m_pusher.stones(1); m_pusher.stzeroes(512); // Signature @@ -1628,7 +1630,7 @@ bool FunctionCallCompiler::checkForTvmBuilderMethods(MemberAccess const &_node, if (_node.memberName() == "storeOnes") { pushArgs(); m_pusher.push(-2 + 1, "STONES"); - } else if (_node.memberName() == "storeZeros") { + } else if (_node.memberName() == "storeZeroes") { pushArgs(); m_pusher.push(-2 + 1, "STZEROES"); } else if (_node.memberName() == "storeRef") { @@ -1915,6 +1917,39 @@ void FunctionCallCompiler::cellMethods(MemberAccess const &_node) { } } +void FunctionCallCompiler::variantMethods(MemberAccess const& _node) { + + auto isUint = [&](){ + m_pusher.push(createNode(std::vector{ + "PUSHCONT {", + " UFITS 256", + " TRUE", + "}", + "PUSHCONT {", + " FALSE", + "}", + "TRYARGS 1, 1" + }, 1, 1, true)); + }; + + switch (m_funcType->kind()) { + case FunctionType::Kind::VariantToUint: { + acceptExpr(&_node.expression()); + m_pusher.pushS(0); + isUint(); + m_pusher._throw("THROWIFNOT " + toString(TvmConst::RuntimeException::BadVariant)); + break; + } + case FunctionType::Kind::VariantIsUint: { + acceptExpr(&_node.expression()); + isUint(); + break; + } + default: + solUnimplemented(""); + } +} + void FunctionCallCompiler::addressMethod() { auto _node = to(&m_functionCall.expression()); if (_node->memberName() == "transfer") { // addr.transfer(...) diff --git a/compiler/libsolidity/codegen/TVMFunctionCall.hpp b/compiler/libsolidity/codegen/TVMFunctionCall.hpp index 9e0dcb97..88ec916c 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCall.hpp +++ b/compiler/libsolidity/codegen/TVMFunctionCall.hpp @@ -58,6 +58,7 @@ class FunctionCallCompiler { bool checkForTvmBuilderMethods(MemberAccess const& _node, Type::Category category); bool checkForTvmVectorMethods(MemberAccess const& _node, Type::Category category); void cellMethods(MemberAccess const& _node); + void variantMethods(MemberAccess const& _node); void addressMethod(); bool checkForTvmConfigParamFunction(MemberAccess const& _node); bool checkForTvmSendFunction(MemberAccess const& _node); diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp index eea35084..9ce313bb 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp @@ -349,7 +349,7 @@ TVMFunctionCompiler::generateOnTickTock(TVMCompilerContext& ctx, FunctionDefinit } TVMFunctionCompiler funCompiler{pusher, 0, function, false, false, 0}; - funCompiler.setCopyleft(); + funCompiler.setCopyleftAndTryCatch(); funCompiler.setGlobSenderAddressIfNeed(); funCompiler.visitFunctionWithModifiers(); @@ -907,6 +907,28 @@ bool TVMFunctionCompiler::visit(ExpressionStatement const& _statement) { return false; } +bool TVMFunctionCompiler::visit(TryStatement const& _tryState) { + // try body + m_pusher.startContinuation(); + const int startStackSize = m_pusher.stackSize(); + _tryState.body().accept(*this); + m_pusher.drop(m_pusher.stackSize() - startStackSize); + m_pusher.endContinuation(); + + // try body + m_pusher.startContinuation(); + for (ASTPointer const& variable : _tryState.clause().parameters()->parameters()) { + m_pusher.getStack().add(variable.get(), true); + } + _tryState.clause().block().accept(*this); + m_pusher.drop(m_pusher.stackSize() - startStackSize); + m_pusher.endContinuation(); + + m_pusher.tryOpcode(); + + return false; +} + bool TVMFunctionCompiler::visit(IfStatement const &_ifStatement) { const int saveStackSize = m_pusher.stackSize(); @@ -935,7 +957,7 @@ bool TVMFunctionCompiler::visit(IfStatement const &_ifStatement) { // if m_pusher.startContinuation(); _ifStatement.trueStatement().accept(*this); - endContinuation2(!canUseJmp); + endContinuation2(!canUseJmp); // TODO delete arg, optimizer is gonna delete DROP if (_ifStatement.falseStatement() != nullptr) { @@ -998,6 +1020,7 @@ void TVMFunctionCompiler::doWhile(WhileStatement const &_whileStatement) { _whileStatement.body().accept(*this); m_pusher.drop(m_pusher.stackSize() - ss); } + // condition acceptExpr(&_whileStatement.condition(), true); m_pusher.push(0, "NOT"); @@ -1566,7 +1589,7 @@ void TVMFunctionCompiler::setCtorFlag() { m_pusher.setGlob(TvmConst::C7::ConstructorFlag); } -void TVMFunctionCompiler::setCopyleft() { +void TVMFunctionCompiler::setCopyleftAndTryCatch() { const std::optional>> copyleft = m_pusher.ctx().pragmaHelper().hasCopyleft(); if (copyleft.has_value()) { const std::optional& addr = ExprUtils::constValue(*copyleft.value().at(1)); @@ -1576,6 +1599,10 @@ void TVMFunctionCompiler::setCopyleft() { m_pusher.pushInt(type.value()); m_pusher << "COPYLEFT"; } + + if (m_pusher.ctx().usage().hasTryCatch()) { + m_pusher << "NEWEXCMODEL"; + } } Pointer @@ -1587,8 +1614,8 @@ TVMFunctionCompiler::generateMainExternalForAbiV2() { // msg_body_slice // transaction_id = -1 - setCopyleft(); - setCtorFlag(); + setCopyleftAndTryCatch(); + setCtorFlag(); // TODO unit with setCopyleftAndTryCatch setGlobSenderAddressIfNeed(); m_pusher.pushS(1); @@ -1659,16 +1686,33 @@ void TVMFunctionCompiler::checkSignatureAndReadPublicKey() { m_pusher.startContinuation(); m_pusher.pushInt(512); - m_pusher.push(-2 + 2, "LDSLICEX ; signatureSlice msgSlice"); + m_pusher.push(-2 + 2, "LDSLICEX"); + // signatureSlice msgSlice m_pusher.pushS(0); - m_pusher.push(-1 + 1, "HASHSU ; signatureSlice msgSlice hashMsgSlice"); + + // signatureSlice msgSlice msgSlice + m_pusher << "MYADDR"; + // signatureSlice msgSlice msgSlice dest + m_pusher << "NEWC"; + // signatureSlice msgSlice msgSlice dest builder + m_pusher << "STSLICE"; + m_pusher << "STSLICE"; + // signatureSlice msgSlice builder + m_pusher << "ENDC"; + // signatureSlice msgSlice signedCell + + m_pusher.push(-1 + 1, "HASHCU"); + // signatureSlice msgSlice msgHash pushMsgPubkey(); - m_pusher.push(-3 + 1, "CHKSIGNU ; msgSlice isSigned"); - m_pusher._throw("THROWIFNOT " + toString(TvmConst::RuntimeException::BadSignature) + " ; msgSlice"); + // signatureSlice msgSlice msgHash pubkey + m_pusher.push(-3 + 1, "CHKSIGNU"); + // msgSlice isSigned + m_pusher._throw("THROWIFNOT " + toString(TvmConst::RuntimeException::BadSignature)); + // msgSlice m_pusher.endContinuation(); if (m_pusher.ctx().pragmaHelper().hasPubkey()) { - // External inbound message have not signature but have public key + // External inbound message does not have signature but have public key m_pusher.startContinuation(); m_pusher.push(+1, "LDU 1 ; hasPubkey msgSlice"); m_pusher.exchange(1); @@ -1719,7 +1763,7 @@ TVMFunctionCompiler::generateMainInternal(TVMCompilerContext& ctx, ContractDefin StackPusher pusher{&ctx}; TVMFunctionCompiler funCompiler{pusher, contract}; - funCompiler.setCopyleft(); + funCompiler.setCopyleftAndTryCatch(); funCompiler.setCtorFlag(); pusher.pushS(2); diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp index d211a852..7975c0da 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp +++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp @@ -95,6 +95,7 @@ class TVMFunctionCompiler: public ASTConstVisitor, private boost::noncopyable void acceptBody(Block const& _block, std::optional> functionBlock); bool visit(Block const& _block) override; bool visit(ExpressionStatement const& _expressionStatement) override; + bool visit(TryStatement const& _block) override; bool visit(IfStatement const& _ifStatement) override; bool visit(WhileStatement const& _whileStatement) override; bool visit(ForEachStatement const& _forStatement) override; @@ -116,7 +117,7 @@ class TVMFunctionCompiler: public ASTConstVisitor, private boost::noncopyable void setGlobSenderAddressIfNeed(); void setCtorFlag(); - void setCopyleft(); + void setCopyleftAndTryCatch(); Pointer generateMainExternalForAbiV2(); void pushMsgPubkey(); diff --git a/compiler/libsolidity/codegen/TVMPusher.cpp b/compiler/libsolidity/codegen/TVMPusher.cpp index 579747b6..8f15b162 100644 --- a/compiler/libsolidity/codegen/TVMPusher.cpp +++ b/compiler/libsolidity/codegen/TVMPusher.cpp @@ -934,6 +934,18 @@ void StackPusher::_while(bool _withBreakOrReturn) { m_instructions.back().push_back(b); } +void StackPusher::tryOpcode() { + solAssert(m_instructions.back().size() >= 2, ""); + auto catchBody = dynamic_pointer_cast(m_instructions.back().back()); + solAssert(catchBody != nullptr, ""); + m_instructions.back().pop_back(); + auto tryBody = dynamic_pointer_cast(m_instructions.back().back()); + solAssert(tryBody != nullptr, ""); + m_instructions.back().pop_back(); + auto b = createNode(tryBody, catchBody); + m_instructions.back().push_back(b); +} + void StackPusher::ret() { auto opcode = makeRET(); m_instructions.back().push_back(opcode); @@ -2727,6 +2739,7 @@ void StackPusher::pushDefaultValue(Type const* type) { break; } case Type::Category::Optional: + case Type::Category::Variant: pushNull(); break; case Type::Category::TvmVector: diff --git a/compiler/libsolidity/codegen/TVMPusher.hpp b/compiler/libsolidity/codegen/TVMPusher.hpp index 7b04f1b0..68cc04f4 100644 --- a/compiler/libsolidity/codegen/TVMPusher.hpp +++ b/compiler/libsolidity/codegen/TVMPusher.hpp @@ -198,6 +198,7 @@ class StackPusher { void repeat(bool _withBreakOrReturn); void until(bool withBreakOrReturn); void _while(bool _withBreakOrReturn); + void tryOpcode(); void ret(); void retAlt(); void ifRetAlt(); diff --git a/compiler/libsolidity/codegen/TVMSimulator.cpp b/compiler/libsolidity/codegen/TVMSimulator.cpp index 141e75f4..d4b9d237 100644 --- a/compiler/libsolidity/codegen/TVMSimulator.cpp +++ b/compiler/libsolidity/codegen/TVMSimulator.cpp @@ -385,6 +385,12 @@ bool Simulator::visit(LogCircuit &_node) { return false; } +bool Simulator::visit(TryCatch &/*_node*/) { + // TODO implement + unableToConvertOpcode(); + return false; +} + bool Simulator::visit(TvmIfElse &_node) { if (rest() == 0) { unableToConvertOpcode(); diff --git a/compiler/libsolidity/codegen/TVMSimulator.hpp b/compiler/libsolidity/codegen/TVMSimulator.hpp index b82219f9..df5fb49b 100644 --- a/compiler/libsolidity/codegen/TVMSimulator.hpp +++ b/compiler/libsolidity/codegen/TVMSimulator.hpp @@ -53,7 +53,8 @@ namespace solidity::frontend { bool visit(CodeBlock &_node) override; bool visit(SubProgram &_node) override; bool visit(LogCircuit &_node) override; - bool visit(TvmIfElse &_node) override; + bool visit(TryCatch &_node) override; + bool visit(TvmIfElse &_node) override; bool visit(TvmRepeat &_node) override; bool visit(TvmUntil &_node) override; bool visit(While &_node) override; diff --git a/compiler/libsolidity/codegen/TvmAst.cpp b/compiler/libsolidity/codegen/TvmAst.cpp index bc1fc854..65d8257e 100644 --- a/compiler/libsolidity/codegen/TvmAst.cpp +++ b/compiler/libsolidity/codegen/TvmAst.cpp @@ -405,6 +405,14 @@ void While::accept(TvmAstVisitor& _visitor) { } } +void TryCatch::accept(TvmAstVisitor& _visitor) { + if (_visitor.visit(*this)) + { + m_tryBody->accept(_visitor); + m_catchBody->accept(_visitor); + } +} + void Function::accept(TvmAstVisitor& _visitor) { if (_visitor.visit(*this)) { @@ -480,6 +488,7 @@ Pointer gen(const std::string& cmd) { const static std::unordered_map opcodes = { {"ACCEPT", {0, 0}}, {"COMMIT", {0, 0}}, + {"NEWEXCMODEL", {0, 0}}, {"PRINTSTR", {0, 0}}, {"BLOCKLT", {0, 1, true}}, diff --git a/compiler/libsolidity/codegen/TvmAst.hpp b/compiler/libsolidity/codegen/TvmAst.hpp index bf30a558..0dad2645 100644 --- a/compiler/libsolidity/codegen/TvmAst.hpp +++ b/compiler/libsolidity/codegen/TvmAst.hpp @@ -432,6 +432,21 @@ namespace solidity::frontend Pointer m_body; }; + class TryCatch : public TvmAstNode { + public: + TryCatch(Pointer _tryBody, Pointer _catchBody) : + m_tryBody{_tryBody}, + m_catchBody{_catchBody} + {} + void accept(TvmAstVisitor& _visitor) override; + bool operator==(TvmAstNode const&) const override { return false; } // TODO + Pointer const& tryBody() const { return m_tryBody; } + Pointer const& catchBody() const { return m_catchBody; } + private: + Pointer m_tryBody; + Pointer m_catchBody; + }; + class Function : public TvmAstNode { public: enum class FunctionType { diff --git a/compiler/libsolidity/codegen/TvmAstVisitor.cpp b/compiler/libsolidity/codegen/TvmAstVisitor.cpp index 7eded2b4..d01f5ec3 100644 --- a/compiler/libsolidity/codegen/TvmAstVisitor.cpp +++ b/compiler/libsolidity/codegen/TvmAstVisitor.cpp @@ -96,6 +96,7 @@ bool Printer::visit(TvmException &_node) { bool Printer::visit(GenOpcode &_node) { tabs(); if (_node.fullOpcode() == "BITNOT") m_out << "NOT"; + else if (_node.fullOpcode() == "NEWEXCMODEL") m_out << ".blob xf2fe ;; NEWEXCMODEL"; else if (_node.fullOpcode() == "TUPLE 1") m_out << "SINGLE"; else if (_node.fullOpcode() == "TUPLE 2") m_out << "PAIR"; else if (_node.fullOpcode() == "TUPLE 3") m_out << "TRIPLE"; @@ -620,6 +621,14 @@ bool Printer::visit(TvmUntil &_node) { return false; } +bool Printer::visit(TryCatch &_node) { + _node.tryBody()->accept(*this); + _node.catchBody()->accept(*this); + tabs(); + m_out << "TRY" << std::endl; + return false; +} + bool Printer::visit(While &_node) { if (!_node.isInfinite()) { _node.condition()->accept(*this); diff --git a/compiler/libsolidity/codegen/TvmAstVisitor.hpp b/compiler/libsolidity/codegen/TvmAstVisitor.hpp index 29f4e6a3..8a7097e9 100644 --- a/compiler/libsolidity/codegen/TvmAstVisitor.hpp +++ b/compiler/libsolidity/codegen/TvmAstVisitor.hpp @@ -50,6 +50,7 @@ namespace solidity::frontend virtual bool visit(TvmRepeat &_node) { return visitNode(_node); } virtual bool visit(TvmUntil &_node) { return visitNode(_node); } virtual bool visit(While &_node) { return visitNode(_node); } + virtual bool visit(TryCatch &_node) { return visitNode(_node); } virtual bool visit(Contract &_node) { return visitNode(_node); } virtual bool visit(Function &_node) { return visitNode(_node); } @@ -80,6 +81,7 @@ namespace solidity::frontend bool visit(TvmIfElse &_node) override; bool visit(TvmRepeat &_node) override; bool visit(TvmUntil &_node) override; + bool visit(TryCatch &_node) override; bool visit(While &_node) override; bool visit(Contract &_node) override; bool visit(Function &_node) override; diff --git a/compiler/libsolidity/interface/CompilerStack.cpp b/compiler/libsolidity/interface/CompilerStack.cpp index ca94394a..00ca188f 100644 --- a/compiler/libsolidity/interface/CompilerStack.cpp +++ b/compiler/libsolidity/interface/CompilerStack.cpp @@ -1186,6 +1186,10 @@ CompilerStack::Contract const& CompilerStack::contract(string const& _contractNa { stringstream ss; ss.str(contractEntry.first); +#ifdef _WIN32 + string drive; + getline(ss, drive, ':'); +#endif // All entries are : string source; string foundName; diff --git a/compiler/libsolidity/parsing/Parser.cpp b/compiler/libsolidity/parsing/Parser.cpp index 52e05b1d..77df14c9 100644 --- a/compiler/libsolidity/parsing/Parser.cpp +++ b/compiler/libsolidity/parsing/Parser.cpp @@ -1386,33 +1386,11 @@ ASTPointer Parser::parseTryStatement(ASTPointer const& RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Try); - ASTPointer externalCall = parseExpression(); - vector> clauses; - - ASTNodeFactory successClauseFactory(*this); - ASTPointer returnsParameters; - if (m_scanner->currentToken() == Token::Returns) - { - m_scanner->next(); - VarDeclParserOptions options; - options.allowEmptyName = true; - options.allowLocationSpecifier = true; - returnsParameters = parseParameterList(options, false); - } - ASTPointer successBlock = parseBlock(); - successClauseFactory.setEndPositionFromNode(successBlock); - clauses.emplace_back(successClauseFactory.createNode( - make_shared(), returnsParameters, successBlock - )); - - do - { - clauses.emplace_back(parseCatchClause()); - } - while (m_scanner->currentToken() == Token::Catch); - nodeFactory.setEndPositionFromNode(clauses.back()); + ASTPointer body = parseBlock(); + ASTPointer clause = parseCatchClause(); + nodeFactory.setEndPositionFromNode(clause); return nodeFactory.createNode( - _docString, externalCall, clauses + _docString, body, clause ); } diff --git a/sold/Cargo.lock b/sold/Cargo.lock index 933b4871..6945a354 100644 --- a/sold/Cargo.lock +++ b/sold/Cargo.lock @@ -58,13 +58,13 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "assert_cmd" -version = "1.0.8" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c98233c6673d8601ab23e77eb38f999c51100d46c5703b17288c57fddf3a1ffe" +checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" dependencies = [ "bstr", "doc-comment", - "predicates 2.1.1", + "predicates", "predicates-core", "predicates-tree", "wait-timeout", @@ -119,14 +119,14 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bindgen" -version = "0.59.2" +version = "0.60.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap 2.34.0", + "clap 3.2.17", "env_logger", "lazy_static", "lazycell", @@ -215,9 +215,9 @@ checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byte-tools" @@ -236,6 +236,9 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cexpr" @@ -254,9 +257,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f725f340c3854e3cb3ab736dc21f0cca183303acea3b3ffec30f141503ac8eb" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ "iana-time-zone", "js-sys", @@ -295,9 +298,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.16" +version = "3.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" +checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" dependencies = [ "atty", "bitflags", @@ -312,9 +315,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.15" +version = "3.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" +checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa" dependencies = [ "heck", "proc-macro-error", @@ -347,16 +350,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -365,9 +358,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "1079fb8528d9f9c888b1e8aa651e6e079ade467323d58f75faf1d30b1808f540" dependencies = [ "libc", ] @@ -435,18 +428,21 @@ dependencies = [ "zeroize", ] -[[package]] -name = "difference" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" +[[package]] +name = "diffy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c27ec7cef89a63c063e06570bb861b7d35e406d6885551b346d77c459b34d3db" +dependencies = [ + "ansi_term", +] + [[package]] name = "digest" version = "0.8.1" @@ -492,6 +488,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dunce" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" + [[package]] name = "ed25519" version = "1.5.2" @@ -517,9 +519,9 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "env_logger" @@ -564,9 +566,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "float-cmp" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ "num-traits", ] @@ -665,12 +667,12 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.41" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1779539f58004e5dba1c1f093d44325ebeb244bfc04b791acdc0aaeca9c04570" +checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" dependencies = [ "android_system_properties", - "core-foundation", + "core-foundation-sys", "js-sys", "wasm-bindgen", "winapi", @@ -701,6 +703,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.59" @@ -724,9 +735,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.127" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libloading" @@ -890,9 +901,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" [[package]] name = "opaque-debug" @@ -908,9 +919,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "os_str_bytes" -version = "6.2.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "owned-alloc" @@ -930,19 +941,6 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" -[[package]] -name = "predicates" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df" -dependencies = [ - "difference", - "float-cmp", - "normalize-line-endings", - "predicates-core", - "regex", -] - [[package]] name = "predicates" version = "2.1.1" @@ -950,8 +948,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" dependencies = [ "difflib", + "float-cmp", "itertools", + "normalize-line-endings", "predicates-core", + "regex", ] [[package]] @@ -1155,18 +1156,18 @@ checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -1175,9 +1176,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -1228,9 +1229,15 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signature" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "f0ea32af43239f0d353a7dd75a22d94c329c8cdaafdcb4c1c1335aa10c298a4a" + +[[package]] +name = "similar" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" [[package]] name = "simplelog" @@ -1251,16 +1258,17 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "sold" -version = "0.63.0" +version = "0.64.0" dependencies = [ "assert_cmd", "atty", "bindgen", - "clap 3.2.16", + "clap 3.2.17", "cmake", + "dunce", "failure", "once_cell", - "predicates 1.0.8", + "predicates", "serde", "serde_json", "strip-ansi-escapes", @@ -1374,8 +1382,8 @@ dependencies = [ [[package]] name = "ton_abi" -version = "2.3.1" -source = "git+https://github.com/tonlabs/ton-labs-abi.git?tag=2.3.1#cb442bca8244a6bfd316c96c2fc0a99114ab32c3" +version = "2.3.7" +source = "git+https://github.com/tonlabs/ton-labs-abi.git?tag=2.3.7#958fba895b3a7c4f255d89a0f292e2136350022c" dependencies = [ "base64 0.10.1", "byteorder", @@ -1396,8 +1404,8 @@ dependencies = [ [[package]] name = "ton_block" -version = "1.8.0" -source = "git+https://github.com/tonlabs/ton-labs-block.git?tag=1.8.0#403010107636ec9cb2bcc75d09b75147c72b0d82" +version = "1.8.3" +source = "git+https://github.com/tonlabs/ton-labs-block.git?tag=1.8.3#8f39a1b467919d5fb3129800f07357883be82d77" dependencies = [ "base64 0.13.0", "crc 3.0.0", @@ -1414,8 +1422,8 @@ dependencies = [ [[package]] name = "ton_labs_assembler" -version = "1.2.44" -source = "git+https://github.com/tonlabs/ton-labs-assembler.git?tag=1.2.44#028be2e35b8b39c73a60ab386384ea6ff62eb219" +version = "1.2.47" +source = "git+https://github.com/tonlabs/ton-labs-assembler.git?tag=1.2.47#4f0e7e2bf848fc74604f895fca3e7b9400b9494a" dependencies = [ "failure", "hex 0.4.3", @@ -1429,8 +1437,8 @@ dependencies = [ [[package]] name = "ton_types" -version = "1.11.3" -source = "git+https://github.com/tonlabs/ton-labs-types.git?tag=1.11.3#d62ead62339f17fda171fe45f19f5c7452e724bb" +version = "1.11.4" +source = "git+https://github.com/tonlabs/ton-labs-types.git?tag=1.11.4#fd69a6b848ddfacee86cc6b76c3ff36d61f3e1f7" dependencies = [ "base64 0.13.0", "crc 1.8.1", @@ -1449,9 +1457,10 @@ dependencies = [ [[package]] name = "ton_vm" -version = "1.8.40" -source = "git+https://github.com/tonlabs/ton-labs-vm.git?tag=1.8.40#3bd45a44c3ca454e4f16f2de06994b404500cce2" +version = "1.8.43" +source = "git+https://github.com/tonlabs/ton-labs-vm.git?tag=1.8.43#7aa03d20e32af14baeb0aae0babf4b9281453561" dependencies = [ + "diffy", "ed25519", "ed25519-dalek", "failure", @@ -1462,14 +1471,16 @@ dependencies = [ "num-traits", "rand 0.7.3", "sha2 0.9.9", + "similar", "ton_block", "ton_types", + "zstd", ] [[package]] name = "tvm_linker" -version = "0.15.65" -source = "git+https://github.com/tonlabs/TVM-linker.git?tag=0.15.65#071b3e85d24501c88cf2ee040237bac9461b2ef5" +version = "0.15.70" +source = "git+https://github.com/tonlabs/TVM-linker.git?tag=0.15.70#ca1548e8570ec642a920e1558e930a638435009f" dependencies = [ "base64 0.10.1", "clap 2.34.0", @@ -1701,3 +1712,32 @@ dependencies = [ "syn", "synstructure", ] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.1+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +dependencies = [ + "cc", + "libc", +] diff --git a/sold/Cargo.toml b/sold/Cargo.toml index b21ccb06..135f2ddf 100644 --- a/sold/Cargo.toml +++ b/sold/Cargo.toml @@ -1,26 +1,27 @@ [package] -name = "sold" -version = "0.63.0" -edition = "2021" +edition = '2021' +name = 'sold' +version = '0.64.0' [dependencies] -atty = "0.2" -clap = { version = "3.2.*", features = [ "derive" ] } -failure = "0.1" -once_cell = "1.10" -serde = { features = [ "derive" ], version = "1.0" } -serde_json = "1.0" -strip-ansi-escapes = "0.1.1" - -ton_abi = { git = 'https://github.com/tonlabs/ton-labs-abi.git', tag = '2.3.1' } -ton_block = { git = 'https://github.com/tonlabs/ton-labs-block.git', tag = '1.8.0' } -ton_types = { git = 'https://github.com/tonlabs/ton-labs-types.git', tag = '1.11.3' } -tvm_linker = { git = 'https://github.com/tonlabs/TVM-linker.git', tag = '0.15.65' } +atty = '0.2' +dunce = '1.0' +failure = '0.1' +once_cell = '1.10' +serde_json = '1.0' +strip-ansi-escapes = '0.1.1' +clap = { features = [ 'derive' ], version = '3.2.*' } +serde = { features = [ 'derive' ], version = '1.0' } +ton_abi = { git = 'https://github.com/tonlabs/ton-labs-abi.git', tag = '2.3.7' } +ton_block = { git = 'https://github.com/tonlabs/ton-labs-block.git', tag = '1.8.3' } +ton_types = { git = 'https://github.com/tonlabs/ton-labs-types.git', tag = '1.11.4' } +tvm_linker = { git = 'https://github.com/tonlabs/TVM-linker.git', tag = '0.15.70' } [build-dependencies] -bindgen = "0.59" -cmake = "0.1" +bindgen = '0.60.1' +cmake = '0.1' [dev-dependencies] -assert_cmd = "1.0.3" -predicates = "1" +assert_cmd = '2.0.4' +predicates = '2.1.1' + diff --git a/sold/README.md b/sold/README.md index f4a90811..15021781 100644 --- a/sold/README.md +++ b/sold/README.md @@ -10,10 +10,11 @@ cd ./sold cargo build --release ``` -### Windows 10 +### Windows 11 Install Visual Studio Build Tools, Rust, Git, cmake. -Run Visual Studio Developer Command Prompt +Also install [LLVM-14.0.6-win64.exe](https://github.com/llvm/llvm-project/releases) +Run Developer PowerShell for VS 2022. ```shell cmake -P compiler\scripts\install_deps.cmake diff --git a/sold/build.rs b/sold/build.rs index 69916539..635d0951 100644 --- a/sold/build.rs +++ b/sold/build.rs @@ -34,6 +34,7 @@ fn main() { if cfg!(target_os = "macos") { println!("cargo:rustc-link-search=native=/opt/homebrew/lib"); + println!("cargo:rustc-link-search=native=/usr/local/lib"); } println!("cargo:rustc-link-search=native={}/lib", sol2tvm.display()); diff --git a/sold/src/main.rs b/sold/src/main.rs index 8abcbd9f..0af22ac8 100644 --- a/sold/src/main.rs +++ b/sold/src/main.rs @@ -91,6 +91,7 @@ fn compile(args: &Args, input: &str) -> Result { }; let force_remote_update = args.tvm_refresh_remote; let main_contract = args.contract.clone().unwrap_or_default(); + let input = serde_json::ser::to_string(input)?; let input = format!(r#" {{ "language": "Solidity", @@ -99,15 +100,15 @@ fn compile(args: &Args, input: &str) -> Result { "forceRemoteUpdate": {force_remote_update}, "mainContract": "{main_contract}", "outputSelection": {{ - "{input}": {{ + {input}: {{ "*": [ "abi"{assembly}{show_function_ids} ], "": [ "ast" ] }} }} }}, "sources": {{ - "{input}": {{ - "urls": [ "{input}" ] + {input}: {{ + "urls": [ {input} ] }} }} }} @@ -158,7 +159,7 @@ fn parse_comp_result( .ok_or_else(|| parse_error!())? .as_str() .ok_or_else(|| parse_error!())?; - let message = if atty::is(atty::Stream::Stderr) { + let message = if atty::is(atty::Stream::Stderr) && !cfg!(target_family = "windows") { message.to_string() } else { let bytes = strip_ansi_escapes::strip(message)?; @@ -227,14 +228,22 @@ fn build(args: Args) -> Status { } } - let input_canonical = Path::new(&args.input).canonicalize()?; + let input_canonical = dunce::canonicalize(Path::new(&args.input))?; let input = input_canonical.as_os_str().to_str() .ok_or_else(|| format_err!("Failed to get canonical path"))?; - let res = compile(&args, input)?; + let input = if cfg!(target_family = "windows") { + // conform to boost::filesystem::canonical() + // note the first slash: C:/Users\Dummy\work\tests\Test.sol + input.replacen('\\', "/", 1) + } else { + input.to_owned() + }; + + let res = compile(&args, &input)?; let out = parse_comp_result( &res, - input, + &input, args.contract, !(args.abi_json || args.ast_json || args.ast_compact_json) )?;