Fix signing of eth transaction. Calculate v value

This commit is contained in:
Vlad Dobromyslov 2022-08-22 16:02:58 +03:00
parent adc6743ef0
commit 6c2bf868c5
5 changed files with 88 additions and 86 deletions

View file

@ -4,6 +4,8 @@
#include <boost/algorithm/hex.hpp> #include <boost/algorithm/hex.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <graphene/peerplays_sidechain/ethereum/utils.hpp>
namespace graphene { namespace peerplays_sidechain { namespace ethereum { namespace graphene { namespace peerplays_sidechain { namespace ethereum {
//! base_encoder //! base_encoder
@ -71,9 +73,9 @@ std::string rlp_encoder::encode_length(int len, int offset)
} }
else else
{ {
const std::string hexLength = int2Hex(len); const std::string hexLength = to_hex(len);
const int lLength = hexLength.size()/2; const int lLength = hexLength.size()/2;
const std::string fByte = int2Hex(offset+55+lLength); const std::string fByte = to_hex(offset+55+lLength);
return hex2bytes(fByte+hexLength); return hex2bytes(fByte+hexLength);
} }
} }
@ -94,16 +96,6 @@ std::string rlp_encoder::encode_rlp(const std::string& s)
return encode_length(s.size(), 128) + s; return encode_length(s.size(), 128) + s;
} }
std::string rlp_encoder::int2Hex(int n)
{
std::stringstream stream;
stream << std::hex << n;
std::string result( stream.str() );
if(result.size() % 2)
result = "0"+result;
return result;
}
int rlp_encoder::char2int(char input) int rlp_encoder::char2int(char input)
{ {
if(input >= '0' && input <= '9') if(input >= '0' && input <= '9')

View file

@ -4,7 +4,7 @@
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <secp256k1.h> #include <secp256k1_recovery.h>
#include <sha3/sha3.h> #include <sha3/sha3.h>
#include <fc/crypto/elliptic.hpp> #include <fc/crypto/elliptic.hpp>
@ -18,36 +18,6 @@
namespace graphene { namespace peerplays_sidechain { namespace ethereum { namespace graphene { namespace peerplays_sidechain { namespace ethereum {
namespace
{
int is_even(char last_char)
{
switch (last_char)
{
case '0':
return 1;
case '2':
return 1;
case '4':
return 1;
case '6':
return 1;
case '8':
return 1;
case 'A':
return 1;
case 'C':
return 1;
case 'E':
return 1;
default:
return -1;
}
}
}
const secp256k1_context *eth_context() { const secp256k1_context *eth_context() {
static secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); static secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
return ctx; return ctx;
@ -107,12 +77,13 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const
const bytes priv_key = parse_hex(private_key); const bytes priv_key = parse_hex(private_key);
secp256k1_ecdsa_signature sign; int recid = 0;
FC_ASSERT(secp256k1_ecdsa_sign(eth_context(), &sign, (const unsigned char *)hash.data(), (const unsigned char *)priv_key.data(), secp256k1_nonce_function_rfc6979, nullptr)); secp256k1_ecdsa_recoverable_signature sig;
FC_ASSERT(secp256k1_ecdsa_sign_recoverable(eth_context(), &sig, (const unsigned char *)hash.data(), (const unsigned char *)priv_key.data(), NULL, NULL));
fc::ecc::compact_signature result; fc::ecc::compact_signature result;
FC_ASSERT(secp256k1_ecdsa_signature_serialize_compact(eth_context(), (unsigned char*) result.begin() + 1, &sign)); FC_ASSERT(secp256k1_ecdsa_recoverable_signature_serialize_compact(eth_context(), (unsigned char *)result.begin() + 1, &recid, &sig));
bytes v = bytes{char(recid + from_hex<int>(chain_id) * 2 + 35)};
bytes r; bytes r;
for(int i = 1; i < 33; i++) for(int i = 1; i < 33; i++)
r.emplace_back((char) result.at(i)); r.emplace_back((char) result.at(i));
@ -120,12 +91,6 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const
for(int i = 33; i < 65; i++) for(int i = 33; i < 65; i++)
s.emplace_back((char) result.at(i)); s.emplace_back((char) result.at(i));
bytes v;
if(is_even(r.back()))
v = {37};
else
v = {38};
tr.v = fc::to_hex((char *)&v[0], v.size()); tr.v = fc::to_hex((char *)&v[0], v.size());
tr.r = fc::to_hex((char *)&r[0], r.size()); tr.r = fc::to_hex((char *)&r[0], r.size());
tr.s = fc::to_hex((char *)&s[0], s.size()); tr.s = fc::to_hex((char *)&s[0], s.size());
@ -136,13 +101,13 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const
std::string raw_transaction::serialize() const std::string raw_transaction::serialize() const
{ {
rlp_encoder encoder; rlp_encoder encoder;
const std::string serialized = encoder.encode(nonce) + const std::string serialized = encoder.encode(remove_0x(nonce)) +
encoder.encode(gas_price) + encoder.encode(remove_0x(gas_price)) +
encoder.encode(gas_limit) + encoder.encode(remove_0x(gas_limit)) +
encoder.encode(to) + encoder.encode(remove_0x(to)) +
encoder.encode(value) + encoder.encode(remove_0x(value)) +
encoder.encode(data) + encoder.encode(remove_0x(data)) +
encoder.encode(chain_id) + encoder.encode(remove_0x(chain_id)) +
encoder.encode("") + encoder.encode("") +
encoder.encode(""); encoder.encode("");
@ -155,13 +120,13 @@ void raw_transaction::deserialize(const std::string& raw_tx)
const auto rlp_array = decoder.decode(raw_tx); const auto rlp_array = decoder.decode(raw_tx);
FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format"); FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format");
nonce = rlp_array.at(0); nonce = add_0x(rlp_array.at(0));
gas_price = rlp_array.at(1); gas_price = add_0x(rlp_array.at(1));
gas_limit = rlp_array.at(2); gas_limit = add_0x(rlp_array.at(2));
to = rlp_array.at(3); to = add_0x(rlp_array.at(3));
value = rlp_array.at(4); value = add_0x(rlp_array.at(4));
data = rlp_array.at(5); data = add_0x(rlp_array.at(5));
chain_id = rlp_array.at(6); chain_id = add_0x(rlp_array.at(6));
} }
//! signed_transaction //! signed_transaction
@ -169,15 +134,15 @@ void raw_transaction::deserialize(const std::string& raw_tx)
std::string signed_transaction::serialize() const std::string signed_transaction::serialize() const
{ {
rlp_encoder encoder; rlp_encoder encoder;
const std::string serialized = encoder.encode(nonce) + const std::string serialized = encoder.encode(remove_0x(nonce)) +
encoder.encode(gas_price) + encoder.encode(remove_0x(gas_price)) +
encoder.encode(gas_limit) + encoder.encode(remove_0x(gas_limit)) +
encoder.encode(to) + encoder.encode(remove_0x(to)) +
encoder.encode(value) + encoder.encode(remove_0x(value)) +
encoder.encode(data) + encoder.encode(remove_0x(data)) +
encoder.encode(v) + encoder.encode(remove_0x(v)) +
encoder.encode(r) + encoder.encode(remove_0x(r)) +
encoder.encode(s); encoder.encode(remove_0x(s));
return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized );
} }
@ -188,15 +153,15 @@ void signed_transaction::deserialize(const std::string& raw_tx)
const auto rlp_array = decoder.decode(raw_tx); const auto rlp_array = decoder.decode(raw_tx);
FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format"); FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format");
nonce = rlp_array.at(0); nonce = add_0x(rlp_array.at(0));
gas_price = rlp_array.at(1); gas_price = add_0x(rlp_array.at(1));
gas_limit = rlp_array.at(2); gas_limit = add_0x(rlp_array.at(2));
to = rlp_array.at(3); to = add_0x(rlp_array.at(3));
value = rlp_array.at(4); value = add_0x(rlp_array.at(4));
data = rlp_array.at(5); data = add_0x(rlp_array.at(5));
v = rlp_array.at(6); v = add_0x(rlp_array.at(6));
r = rlp_array.at(7); r = add_0x(rlp_array.at(7));
s = rlp_array.at(8); s = add_0x(rlp_array.at(8));
} }
}}} // namespace graphene::peerplays_sidechain::ethereum }}} // namespace graphene::peerplays_sidechain::ethereum

View file

@ -34,4 +34,24 @@ std::string uchar2Hex(unsigned char n)
return dest; return dest;
} }
std::string add_0x(const std::string& s)
{
if(s.size() > 1) {
if (s.substr(0, 2) == "0x")
return s;
}
return "0x" + s;
}
std::string remove_0x(const std::string& s)
{
if(s.size() > 1) {
if (s.substr(0, 2) == "0x")
return s.substr(2);
}
return s;
}
}}} // namespace graphene::peerplays_sidechain::ethereum }}} // namespace graphene::peerplays_sidechain::ethereum

View file

@ -35,7 +35,6 @@ public:
private: private:
static std::string encode_rlp(const std::string& s); static std::string encode_rlp(const std::string& s);
static std::string int2Hex(int n);
static int char2int(char input); static int char2int(char input);
static void hex2bin(const char* src, char* target); static void hex2bin(const char* src, char* target);
}; };

View file

@ -10,4 +10,30 @@ std::string bytes2hex(const std::string& s);
std::string uchar2Hex(unsigned char n); std::string uchar2Hex(unsigned char n);
std::string add_0x(const std::string& s);
std::string remove_0x(const std::string& s);
template<typename T>
std::string to_hex( const T& val )
{
std::stringstream stream;
stream << std::hex << val;
std::string result( stream.str() );
if(result.size() % 2)
result = "0"+result;
return result;
}
template<typename T>
T from_hex( const std::string& s )
{
T val;
std::stringstream stream;
stream << std::hex << s;
stream >> val;
return val;
}
}}} // namespace graphene::peerplays_sidechain::ethereum }}} // namespace graphene::peerplays_sidechain::ethereum