diff --git a/libraries/fc/include/fc/io/json.hpp b/libraries/fc/include/fc/io/json.hpp index 8a46d134fe..c26b5cb55a 100644 --- a/libraries/fc/include/fc/io/json.hpp +++ b/libraries/fc/include/fc/io/json.hpp @@ -2,6 +2,8 @@ #include #include +#define JSON_MAX_RECURSION_DEPTH (200) + namespace fc { class ostream; @@ -28,19 +30,19 @@ namespace fc legacy_generator = 1 }; - static ostream& to_stream( ostream& out, const fc::string&); + static ostream& to_stream( ostream& out, const fc::string& ); static ostream& to_stream( ostream& out, const variant& v, output_formatting format = stringify_large_ints_and_doubles ); static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles ); static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles ); - static variant from_stream( buffered_istream& in, parse_type ptype = legacy_parser ); + static variant from_stream( buffered_istream& in, parse_type ptype = legacy_parser, uint32_t depth = 0 ); - static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser ); - static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser ); + static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser, uint32_t depth = 0 ); + static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser, uint32_t depth = 0 ); static string to_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles ); static string to_pretty_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles ); - static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser ); + static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser, uint32_t depth = 0 ); template static void save_to_file( const T& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles ) @@ -49,28 +51,29 @@ namespace fc } static void save_to_file( const variant& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles ); - static variant from_file( const fc::path& p, parse_type ptype = legacy_parser ); + static variant from_file( const fc::path& p, parse_type ptype = legacy_parser, uint32_t depth = 0 ); template - static T from_file( const fc::path& p, parse_type ptype = legacy_parser ) + static T from_file( const fc::path& p, parse_type ptype = legacy_parser, uint32_t depth = 0 ) { - return json::from_file(p, ptype).as(); + depth++; + return json::from_file( p, ptype, depth ).as(); } template - static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles ) + static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles ) { return to_string( variant(v), format ); } template - static string to_pretty_string( const T& v, output_formatting format = stringify_large_ints_and_doubles ) + static string to_pretty_string( const T& v, output_formatting format = stringify_large_ints_and_doubles ) { return to_pretty_string( variant(v), format ); } template - static void save_to_file( const T& v, const std::string& p, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles ) + static void save_to_file( const T& v, const std::string& p, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles ) { save_to_file( variant(v), fc::path(p), pretty ); } diff --git a/libraries/fc/include/fc/io/json_relaxed.hpp b/libraries/fc/include/fc/io/json_relaxed.hpp index e4876f259b..f4c3f8c244 100644 --- a/libraries/fc/include/fc/io/json_relaxed.hpp +++ b/libraries/fc/include/fc/io/json_relaxed.hpp @@ -21,11 +21,12 @@ namespace fc { namespace json_relaxed { template - variant variant_from_stream( T& in ); + variant variant_from_stream( T& in, uint32_t depth ); template - fc::string tokenFromStream( T& in ) + fc::string tokenFromStream( T& in, uint32_t depth ) { + depth++; fc::stringstream token; try { @@ -36,7 +37,7 @@ namespace fc { namespace json_relaxed switch( c = in.peek() ) { case '\\': - token << parseEscape( in ); + token << parseEscape( in, depth ); break; case '\t': case ' ': @@ -81,8 +82,9 @@ namespace fc { namespace json_relaxed } template - fc::string quoteStringFromStream( T& in ) + fc::string quoteStringFromStream( T& in, uint32_t depth = 0 ) { + depth++; fc::stringstream token; try { @@ -140,7 +142,7 @@ namespace fc { namespace json_relaxed FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOF in string '${token}'", ("token", token.str() ) ); else if( allow_escape && (c == '\\') ) - token << parseEscape( in ); + token << parseEscape( in, depth ); else { in.get(); @@ -163,7 +165,7 @@ namespace fc { namespace json_relaxed FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOF in string '${token}'", ("token", token.str() ) ); else if( allow_escape && (c == '\\') ) - token << parseEscape( in ); + token << parseEscape( in, depth ); else if( (c == '\r') | (c == '\n') ) FC_THROW_EXCEPTION( parse_error_exception, "unexpected EOL in string '${token}'", ("token", token.str() ) ); @@ -179,10 +181,11 @@ namespace fc { namespace json_relaxed } template - fc::string stringFromStream( T& in ) + fc::string stringFromStream( T& in, uint32_t depth = 0 ) { try { + depth++; char c = in.peek(), c2; switch( c ) @@ -192,7 +195,7 @@ namespace fc { namespace json_relaxed FC_THROW_EXCEPTION( parse_error_exception, "expected: '\"' at beginning of string, got '\''" ); // falls through case '"': - return quoteStringFromStream( in ); + return quoteStringFromStream( in, depth ); case 'r': if( strict ) FC_THROW_EXCEPTION( parse_error_exception, "raw strings not supported in strict mode" ); @@ -205,11 +208,11 @@ namespace fc { namespace json_relaxed case '\'': if( strict ) FC_THROW_EXCEPTION( parse_error_exception, "raw strings not supported in strict mode" ); - return quoteStringFromStream( in ); + return quoteStringFromStream( in, depth ); default: if( strict ) FC_THROW_EXCEPTION( parse_error_exception, "unquoted strings not supported in strict mode" ); - return c+tokenFromStream( in ); + return c+tokenFromStream( in, depth ); } break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': @@ -225,7 +228,7 @@ namespace fc { namespace json_relaxed case '_': case '-': case '.': case '+': case '/': if( strict ) FC_THROW_EXCEPTION( parse_error_exception, "unquoted strings not supported in strict mode" ); - return tokenFromStream( in ); + return tokenFromStream( in, depth ); default: FC_THROW_EXCEPTION( parse_error_exception, "expected: string" ); } @@ -343,7 +346,7 @@ namespace fc { namespace json_relaxed } template - fc::variant parseNumberOrStr( const fc::string& token ) + fc::variant parseNumberOrStr( const fc::string& token, uint32_t depth = 0 ) { try { //ilog( (token) ); size_t i = 0, n = token.length(); @@ -562,8 +565,10 @@ namespace fc { namespace json_relaxed } FC_CAPTURE_AND_RETHROW( (token) ) } template - variant_object objectFromStream( T& in ) + variant_object objectFromStream( T& in, uint32_t depth = 0 ) { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); mutable_variant_object obj; try { @@ -573,7 +578,7 @@ namespace fc { namespace json_relaxed "Expected '{', but read '${char}'", ("char",string(&c, &c + 1)) ); in.get(); - skip_white_space(in); + skip_white_space( in, depth ); while( in.peek() != '}' ) { if( in.peek() == ',' ) @@ -581,19 +586,19 @@ namespace fc { namespace json_relaxed in.get(); continue; } - if( skip_white_space(in) ) continue; - string key = json_relaxed::stringFromStream( in ); - skip_white_space(in); + if( skip_white_space( in, depth ) ) continue; + string key = json_relaxed::stringFromStream( in, depth ); + skip_white_space( in, depth ); if( in.peek() != ':' ) { FC_THROW_EXCEPTION( parse_error_exception, "Expected ':' after key \"${key}\"", ("key", key) ); } in.get(); - auto val = json_relaxed::variant_from_stream( in ); + auto val = json_relaxed::variant_from_stream( in, depth ); obj(std::move(key),std::move(val)); - skip_white_space(in); + skip_white_space( in, depth ); } if( in.peek() == '}' ) { @@ -613,15 +618,17 @@ namespace fc { namespace json_relaxed } template - variants arrayFromStream( T& in ) + variants arrayFromStream( T& in, uint32_t depth = 0 ) { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); variants ar; try { if( in.peek() != '[' ) FC_THROW_EXCEPTION( parse_error_exception, "Expected '['" ); in.get(); - skip_white_space(in); + skip_white_space( in, depth ); while( in.peek() != ']' ) { @@ -630,9 +637,9 @@ namespace fc { namespace json_relaxed in.get(); continue; } - if( skip_white_space(in) ) continue; - ar.push_back( json_relaxed::variant_from_stream(in) ); - skip_white_space(in); + if( skip_white_space( in, depth ) ) continue; + ar.push_back( json_relaxed::variant_from_stream( in, depth ) ); + skip_white_space( in, depth ); } if( in.peek() != ']' ) FC_THROW_EXCEPTION( parse_error_exception, "Expected ']' after parsing ${variant}", @@ -645,19 +652,21 @@ namespace fc { namespace json_relaxed } template - variant numberFromStream( T& in ) + variant numberFromStream( T& in, uint32_t depth = 0 ) { try { - fc::string token = tokenFromStream(in); - variant result = json_relaxed::parseNumberOrStr( token ); + depth++; + fc::string token = tokenFromStream( in, depth ); + variant result = json_relaxed::parseNumberOrStr( token, depth ); if( strict && !(result.is_int64() || result.is_uint64() || result.is_double()) ) FC_THROW_EXCEPTION( parse_error_exception, "expected: number" ); return result; } FC_CAPTURE_AND_RETHROW() } template - variant wordFromStream( T& in ) + variant wordFromStream( T& in, uint32_t depth = 0 ) { - fc::string token = tokenFromStream(in); + depth++; + fc::string token = tokenFromStream( in, depth ); FC_ASSERT( token.length() > 0 ); @@ -686,9 +695,11 @@ namespace fc { namespace json_relaxed } template - variant variant_from_stream( T& in ) + variant variant_from_stream( T& in, uint32_t depth ) { - skip_white_space(in); + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); + skip_white_space( in, depth ); variant var; while( signed char c = in.peek() ) { @@ -701,11 +712,11 @@ namespace fc { namespace json_relaxed in.get(); continue; case '"': - return json_relaxed::stringFromStream( in ); + return json_relaxed::stringFromStream( in, depth ); case '{': - return json_relaxed::objectFromStream( in ); + return json_relaxed::objectFromStream( in, depth ); case '[': - return json_relaxed::arrayFromStream( in ); + return json_relaxed::arrayFromStream( in, depth ); case '-': case '+': case '.': @@ -719,7 +730,7 @@ namespace fc { namespace json_relaxed case '7': case '8': case '9': - return json_relaxed::numberFromStream( in ); + return json_relaxed::numberFromStream( in, depth ); // null, true, false, or 'warning' / string case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': @@ -730,13 +741,13 @@ namespace fc { namespace json_relaxed case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case '/': - return json_relaxed::wordFromStream( in ); + return json_relaxed::wordFromStream( in, depth ); case 0x04: // ^D end of transmission case EOF: FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" ); default: FC_THROW_EXCEPTION( parse_error_exception, "Unexpected char '${c}' in \"${s}\"", - ("c", c)("s", stringFromToken(in)) ); + ("c", c)("s", stringFromToken( in, depth )) ); } } return variant(); diff --git a/libraries/fc/src/io/json.cpp b/libraries/fc/src/io/json.cpp index 288f40d763..b3c27933f9 100644 --- a/libraries/fc/src/io/json.cpp +++ b/libraries/fc/src/io/json.cpp @@ -15,16 +15,16 @@ namespace fc { // forward declarations of provided functions - template variant variant_from_stream( T& in ); - template char parseEscape( T& in ); - template fc::string stringFromStream( T& in ); - template bool skip_white_space( T& in ); - template fc::string stringFromToken( T& in ); - template variant_object objectFromStream( T& in ); - template variants arrayFromStream( T& in ); - template variant number_from_stream( T& in ); - template variant token_from_stream( T& in ); - void escape_string( const string& str, ostream& os ); + template variant variant_from_stream( T& in, uint32_t depth = 0 ); + template char parseEscape( T& in, uint32_t depth = 0 ); + template fc::string stringFromStream( T& in, uint32_t depth = 0 ); + template bool skip_white_space( T& in, uint32_t depth = 0 ); + template fc::string stringFromToken( T& in, uint32_t depth = 0 ); + template variant_object objectFromStream( T& in, uint32_t depth = 0 ); + template variants arrayFromStream( T& in, uint32_t depth = 0 ); + template variant number_from_stream( T& in, uint32_t depth = 0 ); + template variant token_from_stream( T& in, uint32_t depth = 0 ); + void escape_string( const string& str, ostream& os, uint32_t depth = 0 ); template void to_stream( T& os, const variants& a, json::output_formatting format ); template void to_stream( T& os, const variant_object& o, json::output_formatting format ); template void to_stream( T& os, const variant& v, json::output_formatting format ); @@ -36,7 +36,7 @@ namespace fc namespace fc { template - char parseEscape( T& in ) + char parseEscape( T& in, uint32_t ) { if( in.peek() == '\\' ) { @@ -65,7 +65,7 @@ namespace fc } template - bool skip_white_space( T& in ) + bool skip_white_space( T& in, uint32_t ) { bool skipped = false; while( true ) @@ -86,7 +86,7 @@ namespace fc } template - fc::string stringFromStream( T& in ) + fc::string stringFromStream( T& in, uint32_t depth ) { fc::stringstream token; try @@ -104,7 +104,7 @@ namespace fc switch( c = in.peek() ) { case '\\': - token << parseEscape( in ); + token << parseEscape( in, depth ); break; case 0x04: FC_THROW_EXCEPTION( parse_error_exception, "EOF before closing '\"' in string '${token}'", @@ -123,7 +123,7 @@ namespace fc ("token", token.str() ) ); } template - fc::string stringFromToken( T& in ) + fc::string stringFromToken( T& in, uint32_t depth ) { fc::stringstream token; try @@ -135,7 +135,7 @@ namespace fc switch( c = in.peek() ) { case '\\': - token << parseEscape( in ); + token << parseEscape( in, depth ); break; case '\t': case ' ': @@ -168,8 +168,10 @@ namespace fc } template - variant_object objectFromStream( T& in ) + variant_object objectFromStream( T& in, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); mutable_variant_object obj; try { @@ -179,7 +181,7 @@ namespace fc "Expected '{', but read '${char}'", ("char",string(&c, &c + 1)) ); in.get(); - skip_white_space(in); + skip_white_space( in, depth ); while( in.peek() != '}' ) { if( in.peek() == ',' ) @@ -187,19 +189,19 @@ namespace fc in.get(); continue; } - if( skip_white_space(in) ) continue; - string key = stringFromStream( in ); - skip_white_space(in); + if( skip_white_space( in, depth ) ) continue; + string key = stringFromStream( in, depth ); + skip_white_space( in, depth ); if( in.peek() != ':' ) { FC_THROW_EXCEPTION( parse_error_exception, "Expected ':' after key \"${key}\"", ("key", key) ); } in.get(); - auto val = variant_from_stream( in ); + auto val = variant_from_stream( in, depth ); obj(std::move(key),std::move(val)); - skip_white_space(in); + skip_white_space( in, depth ); } if( in.peek() == '}' ) { @@ -219,15 +221,17 @@ namespace fc } template - variants arrayFromStream( T& in ) + variants arrayFromStream( T& in, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); variants ar; try { if( in.peek() != '[' ) FC_THROW_EXCEPTION( parse_error_exception, "Expected '['" ); in.get(); - skip_white_space(in); + skip_white_space( in, depth ); while( in.peek() != ']' ) { @@ -236,9 +240,9 @@ namespace fc in.get(); continue; } - if( skip_white_space(in) ) continue; - ar.push_back( variant_from_stream(in) ); - skip_white_space(in); + if( skip_white_space( in, depth ) ) continue; + ar.push_back( variant_from_stream( in, depth ) ); + skip_white_space( in, depth ); } if( in.peek() != ']' ) FC_THROW_EXCEPTION( parse_error_exception, "Expected ']' after parsing ${variant}", @@ -251,8 +255,9 @@ namespace fc } template - variant number_from_stream( T& in ) + variant number_from_stream( T& in, uint32_t depth ) { + depth++; fc::stringstream ss; bool dot = false; @@ -291,7 +296,7 @@ namespace fc default: if( isalnum( c ) ) { - return ss.str() + stringFromToken( in ); + return ss.str() + stringFromToken( in, depth ); } done = true; break; @@ -314,8 +319,9 @@ namespace fc return to_uint64(str); } template - variant token_from_stream( T& in ) + variant token_from_stream( T& in, uint32_t depth ) { + depth++; std::stringstream ss; ss.exceptions( std::ifstream::badbit ); bool received_eof = false; @@ -379,16 +385,18 @@ namespace fc // make out ("falfe") // A strict JSON parser would signal this as an error, but we // will just treat the malformed token as an un-quoted string. - return str + stringFromToken(in);; + return str + stringFromToken( in, depth ); } } } template - variant variant_from_stream( T& in ) + variant variant_from_stream( T& in, uint32_t depth ) { - skip_white_space(in); + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); + skip_white_space( in, depth ); variant var; while( true ) { @@ -402,11 +410,11 @@ namespace fc in.get(); continue; case '"': - return stringFromStream( in ); + return stringFromStream( in, depth ); case '{': - return objectFromStream( in ); + return objectFromStream( in, depth ); case '[': - return arrayFromStream( in ); + return arrayFromStream( in, depth ); case '-': case '.': case '0': @@ -419,19 +427,19 @@ namespace fc case '7': case '8': case '9': - return number_from_stream( in ); + return number_from_stream( in, depth ); // null, true, false, or 'warning' / string case 'n': case 't': case 'f': - return token_from_stream( in ); + return token_from_stream( in, depth ); case 0x04: // ^D end of transmission case EOF: case 0: FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" ); default: FC_THROW_EXCEPTION( parse_error_exception, "Unexpected char '${c}' in \"${s}\"", - ("c", c)("s", stringFromToken(in)) ); + ("c", c)("s", stringFromToken( in, depth )) ); } } return variant(); @@ -457,8 +465,10 @@ namespace fc } } - variant json::from_string( const std::string& utf8_str, parse_type ptype ) + variant json::from_string( const std::string& utf8_str, parse_type ptype, uint32_t depth ) { try { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); check_string_depth( utf8_str ); fc::stringstream in( utf8_str ); @@ -466,20 +476,22 @@ namespace fc switch( ptype ) { case legacy_parser: - return variant_from_stream( in ); + return variant_from_stream( in, depth ); case legacy_parser_with_string_doubles: - return variant_from_stream( in ); + return variant_from_stream( in, depth ); case strict_parser: - return json_relaxed::variant_from_stream( in ); + return json_relaxed::variant_from_stream( in, depth ); case relaxed_parser: - return json_relaxed::variant_from_stream( in ); + return json_relaxed::variant_from_stream( in, depth ); default: FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) ); } } FC_RETHROW_EXCEPTIONS( warn, "", ("str",utf8_str) ) } - variants json::variants_from_string( const std::string& utf8_str, parse_type ptype ) + variants json::variants_from_string( const std::string& utf8_str, parse_type ptype, uint32_t depth ) { try { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); check_string_depth( utf8_str ); variants result; fc::stringstream in( utf8_str ); @@ -488,7 +500,7 @@ namespace fc while( true ) { // result.push_back( variant_from_stream( in )); - result.push_back(json_relaxed::variant_from_stream( in )); + result.push_back(json_relaxed::variant_from_stream( in, depth )); } } catch ( const fc::eof_exception& ){} return result; @@ -511,7 +523,7 @@ namespace fc * * All other characters are printed as UTF8. */ - void escape_string( const string& str, ostream& os ) + void escape_string( const string& str, ostream& os, uint32_t ) { os << '"'; for( auto itr = str.begin(); itr != str.end(); ++itr ) @@ -796,7 +808,7 @@ namespace fc fc::to_stream( o, v, format ); } } - variant json::from_file( const fc::path& p, parse_type ptype ) + variant json::from_file( const fc::path& p, parse_type ptype, uint32_t depth ) { //auto tmp = std::make_shared( p, ifstream::binary ); //auto tmp = std::make_shared( p.generic_string().c_str(), std::ios::binary ); @@ -805,29 +817,31 @@ namespace fc switch( ptype ) { case legacy_parser: - return variant_from_stream( bi ); + return variant_from_stream( bi, depth ); case legacy_parser_with_string_doubles: - return variant_from_stream( bi ); + return variant_from_stream( bi, depth ); case strict_parser: - return json_relaxed::variant_from_stream( bi ); + return json_relaxed::variant_from_stream( bi, depth ); case relaxed_parser: - return json_relaxed::variant_from_stream( bi ); + return json_relaxed::variant_from_stream( bi, depth ); default: FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) ); } } - variant json::from_stream( buffered_istream& in, parse_type ptype ) + variant json::from_stream( buffered_istream& in, parse_type ptype, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= JSON_MAX_RECURSION_DEPTH ); switch( ptype ) { case legacy_parser: - return variant_from_stream( in ); + return variant_from_stream( in, depth ); case legacy_parser_with_string_doubles: - return variant_from_stream( in ); + return variant_from_stream( in, depth ); case strict_parser: - return json_relaxed::variant_from_stream( in ); + return json_relaxed::variant_from_stream( in, depth ); case relaxed_parser: - return json_relaxed::variant_from_stream( in ); + return json_relaxed::variant_from_stream( in, depth ); default: FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) ); } @@ -849,23 +863,23 @@ namespace fc return out; } - bool json::is_valid( const std::string& utf8_str, parse_type ptype ) + bool json::is_valid( const std::string& utf8_str, parse_type ptype, uint32_t depth ) { if( utf8_str.size() == 0 ) return false; fc::stringstream in( utf8_str ); switch( ptype ) { case legacy_parser: - variant_from_stream( in ); + variant_from_stream( in, depth ); break; case legacy_parser_with_string_doubles: - variant_from_stream( in ); + variant_from_stream( in, depth ); break; case strict_parser: - json_relaxed::variant_from_stream( in ); + json_relaxed::variant_from_stream( in, depth ); break; case relaxed_parser: - json_relaxed::variant_from_stream( in ); + json_relaxed::variant_from_stream( in, depth ); break; default: FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) ); diff --git a/libraries/protocol/include/steem/protocol/config.hpp b/libraries/protocol/include/steem/protocol/config.hpp index cc623436fb..29f131641a 100644 --- a/libraries/protocol/include/steem/protocol/config.hpp +++ b/libraries/protocol/include/steem/protocol/config.hpp @@ -43,7 +43,7 @@ #else // IS LIVE STEEM NETWORK -#define STEEM_BLOCKCHAIN_VERSION ( version(0, 20, 8) ) +#define STEEM_BLOCKCHAIN_VERSION ( version(0, 20, 9) ) #define STEEM_INIT_PUBLIC_KEY_STR "STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX" #define STEEM_CHAIN_ID fc::sha256()