Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

require names be valid Antelope names when parsing from JSON #37

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

spoonincode
Copy link
Member

Prior to this change, when converting from JSON any name that was invalid (such as having longer than 13 characters, a disallowed character, etc) would be silently transformed in to a valid name by way of a hash.

This results in surprising behavior at odds with nodeos where if, for example, serializing the following JSON to an eosio.token transfer,

{"from":"bob bob bob","to":"carol","quantity":"2.0000 EOS","memo":"sup"}

will succeed. But with the invalid bob bob bob name being replaced with some 64-bit hash value.

This PR now enforces that all names be valid Antelope names when converting from JSON. The above JSON will fail to serialize. This new behavior is generally not expected to cause any problems nor need for any changes by code utilizing abieos because the prior silent hashing behavior was never something standardized in the Antelope ecosystem, including nodeos and cdt.

However, there is one rare use case affected: consuming state_history's JSON ABI that is sent over state_history's websocket. This JSON ABI has table names that are not valid names, such as contract_index64.

There is no way to access old behavior via abieos' C interface.

For C++, abieos retains the old behavior via abi_def_nonstrict_table_name and this can be used to handle state_history's ABI. A C++ state_history client that uses the JSON ABI sent over the websocket might start with something similar to,

    eosio::abi abi;

    boost::beast::websocket::stream<boost::asio::ip::tcp::socket> stream(ctx);
    boost::asio::connect(stream.next_layer(), resolver.resolve("127.0.0.1", "8080"));
    stream.handshake(statehistory_server, "/");

    boost::beast::flat_buffer abi_buffer;
    stream.read(abi_buffer);
    std::string abi_string((const char*)abi_buffer.data().data(), abi_buffer.data().size());
    eosio::json_token_stream token_stream(abi_string.data());
    eosio::abi_def abidef = eosio::from_json<eosio::abi_def>(token_stream);
    eosio::convert(abidef, abi);

simply change the from_json<> line to,

    eosio::abi_def_nonstrict_table_name abidef = eosio::from_json<eosio::abi_def_nonstrict_table_name>(token_stream);

and this ABI will load as it did before.

To be clear, this issue arises only when consuming the JSON ABI from the websocket. Simply using the types in ship_protocol.hpp (which is oftentimes what a C++ state_history client does) will not be affected and no code changes are needed in such a case.

Closes #31

from_json_skip_value(stream);
});
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am disappointed with how this turned out; the code just mostly just a copy paste job from existing struct & vector from_json but it's still a copy paste job.

Normally how I'd want to handle this is by doing something like

template<typename TableNameType>
struct abi_def_template { /* ... */ };
using abi_def = abi_def_template<eosio::name>;
using abi_def_nonstrict_table_name = abi_def_template<eosio::hashed_name>;

but the problem is this won't allow abi_def_nonstrict_table_name to be passed off to eosio::convert(). I could go and make eosio::convert() take a templated abi_def_template but I was concerned the changes would be too sprawling vs something isolated here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

consider undoing murmur hash of invalid name when reading name from JSON
1 participant