diff --git a/unittests/contracts/CMakeLists.txt b/unittests/contracts/CMakeLists.txt index 289450ccf1..9293c7cc13 100644 --- a/unittests/contracts/CMakeLists.txt +++ b/unittests/contracts/CMakeLists.txt @@ -21,6 +21,7 @@ elseif( USE_EOSIO_CDT_1_8_X ) add_definitions(-DUSE_EOSIO_CDT_1_8_X=true) endif() +add_subdirectory(eosio.boot) add_subdirectory(eosio.msig) add_subdirectory(eosio.system) add_subdirectory(eosio.token) diff --git a/unittests/contracts/eosio.boot/CMakeLists.txt b/unittests/contracts/eosio.boot/CMakeLists.txt new file mode 100644 index 0000000000..3b37a86c76 --- /dev/null +++ b/unittests/contracts/eosio.boot/CMakeLists.txt @@ -0,0 +1,6 @@ +if( EOSIO_COMPILE_TEST_CONTRACTS ) + add_contract( eosio.boot eosio.boot eosio.boot.cpp ) +else() + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/eosio.boot.wasm ${CMAKE_CURRENT_BINARY_DIR}/eosio.boot.wasm COPYONLY ) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/eosio.boot.abi ${CMAKE_CURRENT_BINARY_DIR}/eosio.boot.abi COPYONLY ) +endif() diff --git a/unittests/contracts/eosio.boot/eosio.boot.abi b/unittests/contracts/eosio.boot/eosio.boot.abi new file mode 100644 index 0000000000..fa76e88486 --- /dev/null +++ b/unittests/contracts/eosio.boot/eosio.boot.abi @@ -0,0 +1,328 @@ +{ + "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", + "version": "eosio::abi/1.2", + "types": [], + "structs": [ + { + "name": "activate", + "base": "", + "fields": [ + { + "name": "feature_digest", + "type": "checksum256" + } + ] + }, + { + "name": "authority", + "base": "", + "fields": [ + { + "name": "threshold", + "type": "uint32" + }, + { + "name": "keys", + "type": "key_weight[]" + }, + { + "name": "accounts", + "type": "permission_level_weight[]" + }, + { + "name": "waits", + "type": "wait_weight[]" + } + ] + }, + { + "name": "canceldelay", + "base": "", + "fields": [ + { + "name": "canceling_auth", + "type": "permission_level" + }, + { + "name": "trx_id", + "type": "checksum256" + } + ] + }, + { + "name": "deleteauth", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "permission", + "type": "name" + } + ] + }, + { + "name": "key_weight", + "base": "", + "fields": [ + { + "name": "key", + "type": "public_key" + }, + { + "name": "weight", + "type": "uint16" + } + ] + }, + { + "name": "linkauth", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "code", + "type": "name" + }, + { + "name": "type", + "type": "name" + }, + { + "name": "requirement", + "type": "name" + } + ] + }, + { + "name": "newaccount", + "base": "", + "fields": [ + { + "name": "creator", + "type": "name" + }, + { + "name": "name", + "type": "name" + }, + { + "name": "owner", + "type": "authority" + }, + { + "name": "active", + "type": "authority" + } + ] + }, + { + "name": "onerror", + "base": "", + "fields": [ + { + "name": "sender_id", + "type": "uint128" + }, + { + "name": "sent_trx", + "type": "bytes" + } + ] + }, + { + "name": "permission_level", + "base": "", + "fields": [ + { + "name": "actor", + "type": "name" + }, + { + "name": "permission", + "type": "name" + } + ] + }, + { + "name": "permission_level_weight", + "base": "", + "fields": [ + { + "name": "permission", + "type": "permission_level" + }, + { + "name": "weight", + "type": "uint16" + } + ] + }, + { + "name": "reqactivated", + "base": "", + "fields": [ + { + "name": "feature_digest", + "type": "checksum256" + } + ] + }, + { + "name": "setabi", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "abi", + "type": "bytes" + } + ] + }, + { + "name": "setcode", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "vmtype", + "type": "uint8" + }, + { + "name": "vmversion", + "type": "uint8" + }, + { + "name": "code", + "type": "bytes" + } + ] + }, + { + "name": "unlinkauth", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "code", + "type": "name" + }, + { + "name": "type", + "type": "name" + } + ] + }, + { + "name": "updateauth", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "permission", + "type": "name" + }, + { + "name": "parent", + "type": "name" + }, + { + "name": "auth", + "type": "authority" + } + ] + }, + { + "name": "wait_weight", + "base": "", + "fields": [ + { + "name": "wait_sec", + "type": "uint32" + }, + { + "name": "weight", + "type": "uint16" + } + ] + } + ], + "actions": [ + { + "name": "activate", + "type": "activate", + "ricardian_contract": "" + }, + { + "name": "canceldelay", + "type": "canceldelay", + "ricardian_contract": "" + }, + { + "name": "deleteauth", + "type": "deleteauth", + "ricardian_contract": "" + }, + { + "name": "linkauth", + "type": "linkauth", + "ricardian_contract": "" + }, + { + "name": "newaccount", + "type": "newaccount", + "ricardian_contract": "" + }, + { + "name": "onerror", + "type": "onerror", + "ricardian_contract": "" + }, + { + "name": "reqactivated", + "type": "reqactivated", + "ricardian_contract": "" + }, + { + "name": "setabi", + "type": "setabi", + "ricardian_contract": "" + }, + { + "name": "setcode", + "type": "setcode", + "ricardian_contract": "" + }, + { + "name": "unlinkauth", + "type": "unlinkauth", + "ricardian_contract": "" + }, + { + "name": "updateauth", + "type": "updateauth", + "ricardian_contract": "" + } + ], + "tables": [], + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/unittests/contracts/eosio.boot/eosio.boot.cpp b/unittests/contracts/eosio.boot/eosio.boot.cpp new file mode 100644 index 0000000000..33c5f91ea2 --- /dev/null +++ b/unittests/contracts/eosio.boot/eosio.boot.cpp @@ -0,0 +1,19 @@ +#include "eosio.boot.hpp" +#include + +namespace eosioboot { + +void boot::onerror( ignore, ignore> ) { + check( false, "the onerror action cannot be called directly" ); +} + +void boot::activate( const eosio::checksum256& feature_digest ) { + require_auth( get_self() ); + eosio::preactivate_feature( feature_digest ); +} + +void boot::reqactivated( const eosio::checksum256& feature_digest ) { + check( eosio::is_feature_activated( feature_digest ), "protocol feature is not activated" ); +} + +} diff --git a/unittests/contracts/eosio.boot/eosio.boot.hpp b/unittests/contracts/eosio.boot/eosio.boot.hpp new file mode 100644 index 0000000000..422c2e2df6 --- /dev/null +++ b/unittests/contracts/eosio.boot/eosio.boot.hpp @@ -0,0 +1,260 @@ +#pragma once + +#include +#include + +namespace eosioboot { + + using eosio::action_wrapper; + using eosio::check; + using eosio::checksum256; + using eosio::ignore; + using eosio::name; + using eosio::permission_level; + using eosio::public_key; + + /** + * A weighted permission. + * + * @details Defines a weighted permission, that is a permission which has a weight associated. + * A permission is defined by an account name plus a permission name. The weight is going to be + * used against a threshold, if the weight is equal or greater than the threshold set then authorization + * will pass. + */ + struct permission_level_weight { + permission_level permission; + uint16_t weight; + + // explicit serialization macro is not necessary, used here only to improve compilation time + EOSLIB_SERIALIZE( permission_level_weight, (permission)(weight) ) + }; + + /** + * Weighted key. + * + * @details A weighted key is defined by a public key and an associated weight. + */ + struct key_weight { + eosio::public_key key; + uint16_t weight; + + // explicit serialization macro is not necessary, used here only to improve compilation time + EOSLIB_SERIALIZE( key_weight, (key)(weight) ) + }; + + /** + * Wait weight. + * + * @details A wait weight is defined by a number of seconds to wait for and a weight. + */ + struct wait_weight { + uint32_t wait_sec; + uint16_t weight; + + // explicit serialization macro is not necessary, used here only to improve compilation time + EOSLIB_SERIALIZE( wait_weight, (wait_sec)(weight) ) + }; + + /** + * Blockchain authority. + * + * @details An authority is defined by: + * - a vector of key_weights (a key_weight is a public key plus a weight), + * - a vector of permission_level_weights, (a permission_level is an account name plus a permission name) + * - a vector of wait_weights (a wait_weight is defined by a number of seconds to wait and a weight) + * - a threshold value + */ + struct authority { + uint32_t threshold = 0; + std::vector keys; + std::vector accounts; + std::vector waits; + + // explicit serialization macro is not necessary, used here only to improve compilation time + EOSLIB_SERIALIZE( authority, (threshold)(keys)(accounts)(waits) ) + }; + + /** + * @defgroup eosioboot eosio.boot + * @ingroup eosiocontracts + * + * eosio.boot is a extremely minimalistic system contract that only supports the native actions and an + * activate action that allows activating desired protocol features prior to deploying a system contract + * with more features such as eosio.bios or eosio.system. + * + * @{ + */ + class [[eosio::contract("eosio.boot")]] boot : public eosio::contract { + public: + using contract::contract; + /** + * @{ + * These actions map one-on-one with the ones defined in + * [Native Action Handlers](@ref native_action_handlers) section. + * They are present here so they can show up in the abi file and thus user can send them + * to this contract, but they have no specific implementation at this contract level, + * they will execute the implementation at the core level and nothing else. + */ + /** + * New account action + * + * @details Creates a new account. + * + * @param creator - the creator of the account + * @param name - the name of the new account + * @param owner - the authority for the owner permission of the new account + * @param active - the authority for the active permission of the new account + */ + [[eosio::action]] + void newaccount( name creator, + name name, + ignore owner, + ignore active) {} + /** + * Update authorization action. + * + * @details Updates pemission for an account. + * + * @param account - the account for which the permission is updated, + * @param pemission - the permission name which is updated, + * @param parem - the parent of the permission which is updated, + * @param aut - the json describing the permission authorization. + */ + [[eosio::action]] + void updateauth( ignore account, + ignore permission, + ignore parent, + ignore auth ) {} + + /** + * Delete authorization action. + * + * @details Deletes the authorization for an account's permision. + * + * @param account - the account for which the permission authorization is deleted, + * @param permission - the permission name been deleted. + */ + [[eosio::action]] + void deleteauth( ignore account, + ignore permission ) {} + + /** + * Link authorization action. + * + * @details Assigns a specific action from a contract to a permission you have created. Five system + * actions can not be linked `updateauth`, `deleteauth`, `linkauth`, `unlinkauth`, and `canceldelay`. + * This is useful because when doing authorization checks, the EOSIO based blockchain starts with the + * action needed to be authorized (and the contract belonging to), and looks up which permission + * is needed to pass authorization validation. If a link is set, that permission is used for authoraization + * validation otherwise then active is the default, with the exception of `eosio.any`. + * `eosio.any` is an implicit permission which exists on every account; you can link actions to `eosio.any` + * and that will make it so linked actions are accessible to any permissions defined for the account. + * + * @param account - the permission's owner to be linked and the payer of the RAM needed to store this link, + * @param code - the owner of the action to be linked, + * @param type - the action to be linked, + * @param requirement - the permission to be linked. + */ + [[eosio::action]] + void linkauth( ignore account, + ignore code, + ignore type, + ignore requirement ) {} + + /** + * Unlink authorization action. + * + * @details It's doing the reverse of linkauth action, by unlinking the given action. + * + * @param account - the owner of the permission to be unlinked and the receiver of the freed RAM, + * @param code - the owner of the action to be unlinked, + * @param type - the action to be unlinked. + */ + [[eosio::action]] + void unlinkauth( ignore account, + ignore code, + ignore type ) {} + + /** + * Cancel delay action. + * + * @details Cancels a deferred transaction. + * + * @param canceling_auth - the permission that authorizes this action, + * @param trx_id - the deferred transaction id to be cancelled. + */ + [[eosio::action]] + void canceldelay( ignore canceling_auth, ignore trx_id ) {} + + /** + * Set code action. + * + * @details Sets the contract code for an account. + * + * @param account - the account for which to set the contract code. + * @param vmtype - reserved, set it to zero. + * @param vmversion - reserved, set it to zero. + * @param code - the code content to be set, in the form of a blob binary.. + */ + [[eosio::action]] + void setcode( name account, uint8_t vmtype, uint8_t vmversion, const std::vector& code ) {} + + /** + * Set abi for contract. + * + * @details Set the abi for contract identified by `account` name. + * + * @param account - the name of the account to set the abi for + * @param abi - the abi hash represented as a vector of characters + */ + [[eosio::action]] + void setabi( name account, const std::vector& abi ) {} + + /** @}*/ + + /** + * On error action. + * + * @details Notification of this action is delivered to the sender of a deferred transaction + * when an objective error occurs while executing the deferred transaction. + * This action is not meant to be called directly. + * + * @param sender_id - the id for the deferred transaction chosen by the sender, + * @param sent_trx - the deferred transaction that failed. + */ + [[eosio::action]] + void onerror( ignore sender_id, ignore> sent_trx ); + + /** + * Activates a protocol feature. + * + * @details Activates a protocol feature + * + * @param feature_digest - hash of the protocol feature to activate. + */ + [[eosio::action]] + void activate( const eosio::checksum256& feature_digest ); + + /** + * Asserts that a protocol feature has been activated. + * + * @details Asserts that a protocol feature has been activated + * + * @param feature_digest - hash of the protocol feature to check for activation. + */ + [[eosio::action]] + void reqactivated( const eosio::checksum256& feature_digest ); + + using newaccount_action = action_wrapper<"newaccount"_n, &boot::newaccount>; + using updateauth_action = action_wrapper<"updateauth"_n, &boot::updateauth>; + using deleteauth_action = action_wrapper<"deleteauth"_n, &boot::deleteauth>; + using linkauth_action = action_wrapper<"linkauth"_n, &boot::linkauth>; + using unlinkauth_action = action_wrapper<"unlinkauth"_n, &boot::unlinkauth>; + using canceldelay_action = action_wrapper<"canceldelay"_n, &boot::canceldelay>; + using setcode_action = action_wrapper<"setcode"_n, &boot::setcode>; + using setabi_action = action_wrapper<"setabi"_n, &boot::setabi>; + using activate_action = action_wrapper<"activate"_n, &boot::activate>; + using reqactivated_action = action_wrapper<"reqactivated"_n, &boot::reqactivated>; + }; + /** @}*/ // end of @defgroup eosioboot eosio.boot +} /// namespace eosioboot diff --git a/unittests/contracts/eosio.boot/eosio.boot.wasm b/unittests/contracts/eosio.boot/eosio.boot.wasm new file mode 100755 index 0000000000..0da4b8c983 Binary files /dev/null and b/unittests/contracts/eosio.boot/eosio.boot.wasm differ