Merge pull request #365 from AntelopeIO/merge_main_july_14

SC: [5.0 --> sync_call] Merge from main
This commit is contained in:
Lin Huang
2025-07-15 17:42:48 -04:00
committed by GitHub
23 changed files with 498 additions and 43 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"antelope-spring-dev":{
"target":"sync_call",
"target":"release/2.0",
"prerelease":false
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.5...4.0)
# Sanity check our source directory to make sure that we are not trying to
# generate an in-source build, and to make
+225
View File
@@ -0,0 +1,225 @@
#pragma once
#include "serialize.hpp"
#include "print.hpp"
#include "check.hpp"
#include "varint.hpp"
#include <vector>
namespace eosio {
// -------------------------------------------------------------------------------
// see https://github.com/AntelopeIO/spring/wiki/ABI-1.3:-bitset-type
// -------------------------------------------------------------------------------
// stores a bitset in a std::vector<uint8_t>
//
// - bits 0-7 in first byte, 8-15 in second, ...
// - least significant bit of byte 0 is bit 0 of bitset.
// - unused bits must be zero.
// ---------------------------------------------------------------------------------
struct bitset {
using buffer_type = std::vector<uint8_t>;
using size_type = uint32_t;
static constexpr size_type bits_per_block = 8;
static constexpr size_type npos = static_cast<size_type>(-1);
static constexpr size_type calc_num_blocks(size_type num_bits) {
return (num_bits + bits_per_block - 1) / bits_per_block;
}
static size_type block_index(size_type pos) noexcept { return pos / bits_per_block; }
static uint8_t bit_index(size_type pos) noexcept { return static_cast<uint8_t>(pos % bits_per_block); }
static uint8_t bit_mask(size_type pos) noexcept { return uint8_t(1) << bit_index(pos); }
size_type size() const { return m_num_bits; }
size_type num_blocks() const {
assert(m_bits.size() == calc_num_blocks(m_num_bits));
return m_bits.size();
}
void resize(size_type num_bits) {
m_bits.resize(calc_num_blocks(num_bits), 0);
m_num_bits = num_bits;
zero_unused_bits();
}
void set(size_type pos) {
assert(pos < m_num_bits);
m_bits[block_index(pos)] |= bit_mask(pos);
}
void clear(size_type pos) {
assert(pos < m_num_bits);
m_bits[block_index(pos)] &= ~bit_mask(pos);
}
bool test(size_type pos) const {
return (*this)[pos];
}
bool operator[](size_type pos) const {
assert(pos < m_num_bits);
return !!(m_bits[block_index(pos)] & bit_mask(pos));
}
void flip(size_type pos) {
assert(pos < m_num_bits);
if (test(pos))
clear(pos);
else
set(pos);
}
void flip() {
for (auto& byte : m_bits)
byte = ~byte;
zero_unused_bits();
}
bool all() const {
auto sz = size();
for (size_t i=0; i<sz; ++i)
if (!test(i))
return false;
return true;
}
bool none() const {
for (auto& byte : m_bits)
if (byte)
return false;
return true;
}
void zero_all_bits() {
for (auto& byte : m_bits)
byte = 0;
}
bitset operator|=(const bitset& o) {
assert(size() == o.size());
for (size_t i=0; i<m_bits.size(); ++i)
m_bits[i] |= o.m_bits[i];
return *this;
}
void zero_unused_bits() {
assert (m_bits.size() == calc_num_blocks(m_num_bits));
// if != 0 this is the number of bits used in the last block
const size_type extra_bits = bit_index(size());
if (extra_bits != 0)
m_bits.back() &= (uint8_t(1) << extra_bits) - 1;
}
bool unused_bits_zeroed() const {
// if != 0 this is the number of bits used in the last block
const size_type extra_bits = bit_index(size());
return extra_bits == 0 || (m_bits.back() & ~((uint8_t(1) << extra_bits) - 1)) == 0;
}
friend auto operator<(const bitset& a, const bitset& b) {
return std::tuple(a.m_num_bits, a.m_bits) < std::tuple(b.m_num_bits, b.m_bits);
}
friend bool operator==(const bitset& a, const bitset& b) {
return std::tuple(a.m_num_bits, a.m_bits) == std::tuple(b.m_num_bits, b.m_bits);
}
uint8_t& byte(size_t i) {
assert(i < m_bits.size());
return m_bits[i];
}
const uint8_t& byte(size_t i) const {
assert(i < m_bits.size());
return m_bits[i];
}
std::string to_string() const {
std::string res;
res.resize(size());
size_t idx = 0;
for (auto i = size(); i-- > 0;)
res[idx++] = (*this)[i] ? '1' : '0';
return res;
}
static bitset from_string(std::string_view s) {
bitset bs;
auto num_bits = s.size();
bs.resize(num_bits);
for (size_t i = 0; i < num_bits; ++i) {
switch (s[i]) {
case '0':
break; // nothing to do, all bits initially 0
case '1':
bs.set(num_bits - i - 1); // high bitset indexes come first in the JSON representation
break;
default:
eosio::check(false, "unexpected character in bitset string representation");
break;
}
}
assert(bs.unused_bits_zeroed());
return bs;
}
void print() const {
auto s = to_string();
if (!s.empty())
printl(s.data(), s.size());
}
// binary representation
// ---------------------
// The bitset first encodes the number of bits it contains as a varint, then encodes
// (size+8-1)/8 bytes into the stream. The first byte represents bits 0-7, the next 8-15,
// and so on; i.e. LSB first.
// Within a byte, the least significant bit stores the smaller bitset index.
// Unused bits should be written as 0.
//
// This matches the storage scheme of bitset above
// ---------------------------------------------------------------------------------------
template <typename DataStream>
friend DataStream& operator>>(DataStream& stream, bitset& obj) {
unsigned_int num_bits(0);
stream >> num_bits;
obj.resize(num_bits.value);
if (obj.size() > 0) {
auto num_blocks = bitset::calc_num_blocks(obj.size());
for (size_t i = 0; i < num_blocks; ++i)
stream >> obj.byte(i);
obj.zero_unused_bits();
assert(obj.unused_bits_zeroed());
}
return stream;
}
template <typename DataStream>
friend DataStream& operator<<(DataStream& stream, const bitset& obj) {
unsigned_int num_bits(obj.size());
stream << num_bits;
if (obj.size() > 0) {
auto num_blocks = bitset::calc_num_blocks(obj.size());
assert(num_blocks >= 1);
for (size_t i = 0; i < num_blocks; ++i)
stream << obj.byte(i);
}
return stream;
}
private:
size_type m_num_bits{0}; // members order matters for comparison operators
buffer_type m_bits; // must be after `m_num_bits`
};
constexpr const char* get_type_name(bitset*) { return "bitset"; }
} // namespace eosio
+1 -1
View File
@@ -32,7 +32,7 @@ if (spring_FOUND)
CDTIntegrationTests
SOURCE_DIR "${CMAKE_SOURCE_DIR}/tests/integration"
BINARY_DIR "${CMAKE_BINARY_DIR}/tests/integration"
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${TEST_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_FRAMEWORK_PATH=${TEST_FRAMEWORK_PATH} -DCMAKE_MODULE_PATH=${TEST_MODULE_PATH} -Deosio_DIR=${eosio_DIR} -DLLVM_DIR=${LLVM_DIR} -DBOOST_ROOT=${BOOST_ROOT}
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${TEST_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_FRAMEWORK_PATH=${TEST_FRAMEWORK_PATH} -DCMAKE_MODULE_PATH=${TEST_MODULE_PATH} -Dspring_DIR=${spring_DIR} -Deosio_DIR=${eosio_DIR} -DLLVM_DIR=${LLVM_DIR} -DBOOST_ROOT=${BOOST_ROOT}
UPDATE_COMMAND ""
PATCH_COMMAND ""
TEST_COMMAND ""
+97
View File
@@ -0,0 +1,97 @@
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/abi_serializer.hpp>
#include <fc/variant_object.hpp>
#include <contracts.hpp>
using namespace eosio;
using namespace eosio::testing;
using namespace eosio::chain;
using namespace eosio::testing;
using namespace fc;
using mvo = fc::mutable_variant_object;
BOOST_AUTO_TEST_SUITE(array_tests)
BOOST_FIXTURE_TEST_CASE( std_array_param, tester ) try {
/* ----------- testpa action tests --------------------------------------------------
[[eosio::action]]
void testpa(std::array<int,4> input){
std::array<int,4> arr = input;
for(int i = 0; i < 4; ++i){
eosio::cout << arr[i] << " ";
}
eosio::cout << "\n";
}
-------------------------------------------------------------------------------------- */
create_accounts( { "test"_n } );
produce_block();
set_code( "test"_n, contracts::array_tests_wasm() );
set_abi( "test"_n, contracts::array_tests_abi().data() );
produce_blocks();
auto trace = push_action("test"_n, "testpa"_n, "test"_n, mvo()("input", {1,2,3,4}));
auto& con = trace->action_traces[0].console;
BOOST_REQUIRE_EQUAL(con, std::string("1 2 3 4 \n"));
produce_block();
// size should be correct
// ----------------------
BOOST_CHECK_EXCEPTION( push_action("test"_n, "testpa"_n, "test"_n, mvo()("input", {1,2,3})),
pack_exception,
fc_exception_message_starts_with("Incorrect number of values provided (4) for fixed-size (3) array type"));
produce_block();
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( std_array_return_value, tester ) try {
/* ----------- testre action tests --------------------------------------------------
[[eosio::action]]
std::array<int,4> testre(std::array<int,4> input){
std::array<int,4> arr = input;
for(auto & v : arr) v += 1;
return arr;
}
-------------------------------------------------------------------------------------- */
create_accounts( { "test"_n } );
produce_block();
set_code( "test"_n, contracts::array_tests_wasm() );
set_abi( "test"_n, contracts::array_tests_abi().data() );
produce_blocks();
auto trace = push_action("test"_n, "testre"_n, "test"_n, mvo()("input", {1, 2, 3, 4}));
auto& rv = trace->action_traces[0].return_value;
auto actual = fc::raw::unpack<std::array<int, 4>>(rv);
auto expected = std::array<int, 4>{2, 3, 4, 5};
BOOST_REQUIRE(actual == expected);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( std_vector_return_value, tester ) try {
/* ----------- testrev action tests --------------------------------------------------
[[eosio::action]]
std::vector<int> testrev(std::vector<int> input){
std::vector<int> vec = input;
for(auto & v : vec) v += 1;
return vec;
}
-------------------------------------------------------------------------------------- */
create_accounts( { "test"_n } );
produce_block();
set_code( "test"_n, contracts::array_tests_wasm() );
set_abi( "test"_n, contracts::array_tests_abi().data() );
produce_blocks();
auto trace = push_action("test"_n, "testrev"_n, "test"_n, mvo()("input", {1, 2, 3, 4}));
auto& rv = trace->action_traces[0].return_value;
auto actual = fc::raw::unpack<std::vector<int>>(rv);
auto expected = std::vector<int>{2, 3, 4, 5};
BOOST_REQUIRE(actual == expected);
} FC_LOG_AND_RETHROW()
BOOST_AUTO_TEST_SUITE_END()
+47
View File
@@ -0,0 +1,47 @@
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/abi_serializer.hpp>
#include <fc/variant_object.hpp>
#include <contracts.hpp>
#include "test_utils.hpp"
using namespace eosio;
using namespace eosio::testing;
using namespace eosio::chain;
using namespace eosio::testing;
using namespace fc;
using mvo = fc::mutable_variant_object;
BOOST_AUTO_TEST_SUITE(bitset_tests)
BOOST_FIXTURE_TEST_CASE( bitset_test, tester ) try {
create_accounts( { "test"_n } );
produce_block();
set_code( "test"_n, contracts::simple_wasm() );
set_abi( "test"_n, contracts::simple_abi().data() );
produce_blocks();
auto trx_trace = push_action("test"_n, "testbs"_n, "test"_n, mvo()("b", "0010"));
auto& act_trace = trx_trace->action_traces[0];
BOOST_REQUIRE_EQUAL(fc::raw::unpack<fc::bitset>(act_trace.return_value), fc::bitset{"1101"});
{
// because contract `simple_tests.cpp` uses the `bitset` type, the abi version should be 1.3 or greater
auto abi_version = extract_version_from_json_abi(contracts::simple_abi());
BOOST_REQUIRE(abi_version.is_valid());
BOOST_REQUIRE_LT(version_t(1,2), abi_version);
}
{
// check that abi version of minimal contract is still 1.2.
auto abi_version = extract_version_from_json_abi(contracts::malloc_tests_abi());
BOOST_REQUIRE(abi_version.is_valid());
BOOST_REQUIRE_EQUAL(version_t(1,2), abi_version);
}
} FC_LOG_AND_RETHROW()
BOOST_AUTO_TEST_SUITE_END()
+2
View File
@@ -3,6 +3,8 @@
namespace eosio::testing {
struct contracts {
static std::vector<uint8_t> array_tests_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/array_tests.wasm"); }
static std::vector<char> array_tests_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/array_tests.abi"); }
static std::vector<uint8_t> malloc_tests_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/malloc_tests.wasm"); }
static std::vector<char> malloc_tests_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/malloc_tests.abi"); }
static std::vector<uint8_t> old_malloc_tests_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/old_malloc_tests.wasm"); }
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
#include <string>
#include <cstring>
#include <string_view>
#include <vector>
#include <optional>
#include <charconv>
inline eosio::chain::version_t extract_version_from_json_abi(std::vector<char> abi) {
std::string_view sv(abi.data(), abi.size());
constexpr const char* pattern = R"("version": "eosio::abi/)";
if (auto pos = sv.find(pattern); pos != std::string_view::npos) {
return eosio::chain::version_t{sv.substr(pos + strlen(pattern))};
}
return {};
}
@@ -1,7 +1,7 @@
{
"tests" : [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected" : {
"abi-file" : "action_results_test.abi"
}
@@ -1,7 +1,7 @@
{
"tests": [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected": {
"abi-file": "aliased_type_variant_template_arg.abi"
}
@@ -1,7 +1,7 @@
{
"tests" : [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected" : {
"abi-file" : "nested_container.abi"
}
@@ -1,7 +1,7 @@
{
"tests" : [
{
"compile_flags" : ["--abi-version=1.2", "-R={cwd}"],
"compile_flags" : ["-R={cwd}"],
"expected" : {
"abi-file" : "ricardian_contract_test.abi"
}
@@ -1,7 +1,7 @@
{
"tests" : [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected" : {
"abi-file" : "singleton_contract.abi"
}
@@ -1,7 +1,7 @@
{
"tests": [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected": {
"abi-file": "struct_base_typedefd.abi"
}
@@ -1,7 +1,7 @@
{
"tests" : [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected" : {
"abi-file" : "tagged_number_test.abi"
}
@@ -1,7 +1,7 @@
{
"tests" : [
{
"compile_flags": ["--abi-version=1.2"],
"compile_flags": [],
"expected" : {
"abi-file" : "using_std_array.abi"
}
+11 -3
View File
@@ -65,8 +65,7 @@ class [[eosio::contract]] array_tests : public contract {
}
}
// test parameter using std::array
// not supported so far
// test parameter using std::array
[[eosio::action]]
void testpa(std::array<int,4> input){
std::array<int,4> arr = input;
@@ -76,7 +75,7 @@ class [[eosio::contract]] array_tests : public contract {
eosio::cout << "\n";
}
// test return using std::array, not supported so far
// test parameter and return value using std::array
[[eosio::action]]
// cleos -v push action eosio testre '[[1,2,3,4]]' -p eosio@active
std::array<int,4> testre(std::array<int,4> input){
@@ -85,6 +84,15 @@ class [[eosio::contract]] array_tests : public contract {
return arr;
}
// test return value using std::array
[[eosio::action]]
// cleos -v push action eosio testre2 '[[1,2,3,4]]' -p eosio@active
std::array<int,4> testre2(std::vector<int> input){
std::array<int,4> arr;
for(size_t i=0; i<4; ++i) arr[i] = input[i+1];
return arr;
}
// test return using std::vector
[[eosio::action]]
// cleos -v push action eosio testrev '[[1,2,3,4]]' -p eosio@active
@@ -1,5 +1,6 @@
#include <eosio/eosio.hpp>
#include <eosio/transaction.hpp>
#include <eosio/bitset.hpp>
#include "transfer.hpp"
@@ -61,6 +62,17 @@ class [[eosio::contract]] simple_tests : public contract {
t.send(nm.value, get_self());
}
[[eosio::action]]
eosio::bitset testbs(eosio::bitset b) {
for (size_t i=0; i<b.size(); ++i) {
if (b[i])
b.clear(i);
else
b.set(i);
}
return b;
}
[[eosio::on_notify("eosio.token::transfer")]]
void on_transfer(name from, name to, asset quant, std::string memo) {
check(get_first_receiver() == "eosio.token"_n, "should be eosio.token");
+9 -1
View File
@@ -64,7 +64,15 @@ void generate(const std::vector<std::string>& base_options, std::string input, s
abigen::get().set_contract_name(contract_name);
abigen::get().set_resource_dirs(resource_paths);
abigen::get().set_abi_version(std::get<0>(abi_version), std::get<1>(abi_version));
// We used to accept a command line option `--abi-version` which allowed a user to force an abi version
// to be generated.
// Since https://github.com/AntelopeIO/cdt/pull/360, this command line flag is ignored, and the abi
// version is generated according to the features used in the contract being compiled, starting from a
// base `1.2` version and up.
// ----------------------------------------------------------------------------------------------------
// abigen::get().set_abi_version(std::get<0>(abi_version), std::get<1>(abi_version));
abigen::get().set_suppress_ricardian_warning(suppress_ricardian_warning);
codegen::get().set_contract_name(contract_name);
codegen::get().set_warn_action_read_only(warn_action_read_only);
+25 -7
View File
@@ -69,16 +69,32 @@ struct abi_action_result {
bool operator<(const abi_action_result& ar) const { return name < ar.name; }
};
// The version when sync call was first introduced.
constexpr int abi_call_version_major = 1;
constexpr int abi_call_version_minor = 3;
constexpr int abi_call_version = abi_call_version_major * 10 + abi_call_version_minor;
struct version_t {
uint8_t major = 0;
uint8_t minor = 0;
version_t(uint8_t major, uint8_t minor)
: major(major)
, minor(minor) {}
friend bool operator<(const version_t& a, const version_t& b) {
return std::tie(a.major, a.minor) < std::tie(b.major, b.minor);
}
friend bool operator==(const version_t& a, const version_t& b) {
return std::tie(a.major, a.minor) == std::tie(b.major, b.minor);
}
void set_min(version_t o) {
if (*this < o)
*this = o;
}
std::string str() const { return std::to_string(major) + "." + std::to_string(minor); }
};
/// From eosio libraries/chain/include/eosio/chain/abi_def.hpp
struct abi {
int version_major = 1;
int version_minor = 1;
std::string version_string()const { return std::string("eosio::abi/")+std::to_string(version_major)+"."+std::to_string(version_minor); }
version_t version{1,2}; // base version is 1.2, add features (bitset, sync calls) push to 1.3
std::set<abi_struct> structs;
std::set<abi_typedef> typedefs;
std::set<abi_action> actions;
@@ -88,6 +104,8 @@ struct abi {
std::vector<abi_ricardian_clause_pair> ricardian_clauses;
std::vector<abi_error_message> error_messages;
std::set<abi_action_result> action_results;
std::string version_string() const { return std::string("eosio::abi/")+version.str(); }
};
inline void dump( const abi& abi ) {
+30 -13
View File
@@ -26,6 +26,7 @@
#include <sstream>
#include <memory>
#include <set>
#include <tuple>
#include <map>
#include <array>
#include <jsoncons/json.hpp>
@@ -36,7 +37,11 @@ using namespace eosio::cdt;
using jsoncons::json;
using jsoncons::ojson;
namespace eosio { namespace cdt {
namespace eosio::cdt {
const version_t bitset_min_version{1,3};
const version_t sync_calls_min_version{1,3};
class abigen : public generation_utils {
std::set<std::string> checked_actions;
public:
@@ -48,8 +53,7 @@ namespace eosio { namespace cdt {
}
void set_abi_version(int major, int minor) {
_abi.version_major = major;
_abi.version_minor = minor;
_abi.version = version_t{static_cast<uint8_t>(major), static_cast<uint8_t>(minor)};
}
void add_typedef( const clang::QualType& t ) {
@@ -146,6 +150,8 @@ namespace eosio { namespace cdt {
ret.type = decl->getName().str();
ret.id = to_hash_id(ret.name);
_abi.calls.insert(ret);
_abi.version.set_min(sync_calls_min_version);
}
void add_call( const clang::CXXMethodDecl* decl ) {
@@ -169,6 +175,8 @@ namespace eosio { namespace cdt {
ret.result_type = result_type;
}
_abi.calls.insert(ret);
_abi.version.set_min(sync_calls_min_version);
}
void add_tuple(const clang::QualType& type) {
@@ -191,7 +199,6 @@ namespace eosio { namespace cdt {
void add_pair(const clang::QualType& type) {
for (int i = 0; i < 2; ++i) {
clang::QualType ftype = std::get<clang::QualType>(get_template_argument(type, i));
std::string ty = translate_type(ftype);
add_type(ftype);
}
abi_struct pair;
@@ -521,7 +528,8 @@ namespace eosio { namespace cdt {
add_explicit_nested_type(t.getNonReferenceType());
return;
}
if (!is_builtin_type(translate_type(type))) {
auto type_str = translate_type(type);
if (!is_builtin_type(type_str)) {
if (is_aliasing(type)) {
add_typedef(type);
}
@@ -543,6 +551,13 @@ namespace eosio { namespace cdt {
}
else if (type.getTypePtr()->isRecordType())
add_struct(type.getTypePtr()->getAsCXXRecordDecl());
} else {
static std::unordered_map<std::string, version_t> versioned_types {
{ "bitset", bitset_min_version }
};
if (auto it = versioned_types.find(type_str); it != versioned_types.end())
_abi.version.set_min(it->second);
}
}
@@ -649,7 +664,9 @@ namespace eosio { namespace cdt {
ojson to_json() {
ojson o;
o["____comment"] = generate_json_comment();
o["version"] = _abi.version_string();
o["structs"] = ojson::array();
auto remove_suffix = [&]( std::string name ) {
int i = name.length()-1;
@@ -776,8 +793,7 @@ namespace eosio { namespace cdt {
for ( auto a : _abi.actions ) {
o["actions"].push_back(action_to_json( a ));
}
if (_abi.version_major > abi_call_version_major ||
_abi.version_major == abi_call_version_major && _abi.version_minor >= abi_call_version_minor) { // sync call
if (!_abi.calls.empty()) { // add calls section only when sync calls are used
o["calls"] = ojson::array();
for ( auto a : _abi.calls ) {
o["calls"].push_back(call_to_json( a ));
@@ -791,16 +807,17 @@ namespace eosio { namespace cdt {
for ( auto rc : _abi.ricardian_clauses ) {
o["ricardian_clauses"].push_back(clause_to_json( rc ));
}
o["variants"] = ojson::array();
for ( auto v : _abi.variants ) {
o["variants"].push_back(variant_to_json( v ));
}
o["abi_extensions"] = ojson::array();
if (_abi.version_major == 1 && _abi.version_minor >= 2) {
o["action_results"] = ojson::array();
for ( auto ar : _abi.action_results ) {
o["action_results"].push_back(action_result_to_json( ar ));
}
o["action_results"] = ojson::array();
for ( auto ar : _abi.action_results ) {
o["action_results"].push_back(action_result_to_json( ar ));
}
return o;
}
@@ -996,4 +1013,4 @@ namespace eosio { namespace cdt {
return std::make_unique<eosio_abigen_consumer>(&CI, file);
}
};
}} // ns eosio::cdt
} // ns eosio::cdt
+3 -2
View File
@@ -37,8 +37,9 @@ class ABIMerger {
if (std::stod(vers.substr(vers.size()-3))*10 >= 12) {
ret["action_results"] = merge_action_results(other);
}
if (std::stod(vers.substr(vers.size()-3))*10 >= abi_call_version) {
ret["calls"] = merge_calls(other);
auto it = abi.find("calls");
if (it != abi.object_range().end()) { // merge `calls` section only when it exists
ret["calls"] = merge_calls(other);
}
return ret;
}
+7 -6
View File
@@ -13,6 +13,7 @@
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <regex>
#include <utility>
#include <variant>
@@ -432,7 +433,7 @@ struct generation_utils {
}
std::string _translate_type( const std::string& t ) {
static std::map<std::string, std::string> translation_table =
static std::unordered_map<std::string, std::string> translation_table =
{
{"unsigned __int128", "uint128"},
{"__int128", "int128"},
@@ -484,11 +485,10 @@ struct generation_utils {
{"fixed_bytes_64", "checksum512"}
};
auto ret = translation_table[t];
if (auto it = translation_table.find(t); it != translation_table.end())
return it->second;
if (ret == "")
return t;
return ret;
return t;
}
inline std::string replace_in_name( std::string name ) {
@@ -776,7 +776,8 @@ struct generation_utils {
"symbol",
"symbol_code",
"asset",
"extended_asset"
"extended_asset",
"bitset"
};
return builtins.count(_translate_type(t)) >= 1;
}