peerplays_migrated/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp
Vlad Dobromyslov ab7bb9e633 clang-format
2022-08-26 11:09:55 +03:00

158 lines
5.5 KiB
C++

#include <graphene/peerplays_sidechain/ethereum/transaction.hpp>
#include <boost/algorithm/hex.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <secp256k1_recovery.h>
#include <sha3/sha3.h>
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/hex.hpp>
#include <graphene/peerplays_sidechain/ethereum/decoders.hpp>
#include <graphene/peerplays_sidechain/ethereum/encoders.hpp>
#include <graphene/peerplays_sidechain/ethereum/types.hpp>
#include <graphene/peerplays_sidechain/ethereum/utils.hpp>
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
const secp256k1_context *eth_context() {
static secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
return ctx;
}
//! transaction
const transaction &transaction::sign(const std::string &private_key) const {
return *this;
}
std::string transaction::serialize() const {
boost::property_tree::ptree pt;
pt.put("from", from);
pt.put("to", to);
pt.put("data", data);
std::stringstream ss;
boost::property_tree::json_parser::write_json(ss, pt);
return ss.str();
}
void transaction::deserialize(const std::string &raw_tx) {
std::stringstream ss_tx(raw_tx);
boost::property_tree::ptree tx_json;
boost::property_tree::read_json(ss_tx, tx_json);
if (tx_json.count("from"))
from = tx_json.get<std::string>("from");
if (tx_json.count("to"))
to = tx_json.get<std::string>("to");
if (tx_json.count("data"))
data = tx_json.get<std::string>("data");
}
//! raw_transaction
signed_transaction raw_transaction::sign(const std::string &private_key) const {
//! Prepare signed transaction
signed_transaction tr;
tr.nonce = nonce;
tr.gas_price = gas_price;
tr.gas_limit = gas_limit;
tr.to = to;
tr.value = value;
tr.data = data;
//! Calculate keccak hash of transaction
bytes hash;
hash.resize(32);
const auto transaction_string = boost::algorithm::unhex(remove_0x(serialize()));
keccak_256((const unsigned char *)transaction_string.data(), transaction_string.size(), (unsigned char *)hash.data());
const bytes priv_key = parse_hex(private_key);
int recid = 0;
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_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;
for (int i = 1; i < 33; i++)
r.emplace_back((char)result.at(i));
bytes s;
for (int i = 33; i < 65; i++)
s.emplace_back((char)result.at(i));
tr.v = fc::to_hex((char *)&v[0], v.size());
tr.r = fc::to_hex((char *)&r[0], r.size());
tr.s = fc::to_hex((char *)&s[0], s.size());
return tr;
}
std::string raw_transaction::serialize() const {
rlp_encoder encoder;
const std::string serialized = encoder.encode(remove_0x(nonce)) +
encoder.encode(remove_0x(gas_price)) +
encoder.encode(remove_0x(gas_limit)) +
encoder.encode(remove_0x(to)) +
encoder.encode(remove_0x(value)) +
encoder.encode(remove_0x(data)) +
encoder.encode(remove_0x(chain_id)) +
encoder.encode("") +
encoder.encode("");
return add_0x(bytes2hex(encoder.encode_length(serialized.size(), 192) + serialized));
}
void raw_transaction::deserialize(const std::string &raw_tx) {
rlp_decoder decoder;
const auto rlp_array = decoder.decode(remove_0x(raw_tx));
FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format");
nonce = add_0x(rlp_array.at(0));
gas_price = add_0x(rlp_array.at(1));
gas_limit = add_0x(rlp_array.at(2));
to = add_0x(rlp_array.at(3));
value = add_0x(rlp_array.at(4));
data = add_0x(rlp_array.at(5));
chain_id = add_0x(rlp_array.at(6));
}
//! signed_transaction
std::string signed_transaction::serialize() const {
rlp_encoder encoder;
const std::string serialized = encoder.encode(remove_0x(nonce)) +
encoder.encode(remove_0x(gas_price)) +
encoder.encode(remove_0x(gas_limit)) +
encoder.encode(remove_0x(to)) +
encoder.encode(remove_0x(value)) +
encoder.encode(remove_0x(data)) +
encoder.encode(remove_0x(v)) +
encoder.encode(remove_0x(r)) +
encoder.encode(remove_0x(s));
return add_0x(bytes2hex(encoder.encode_length(serialized.size(), 192) + serialized));
}
void signed_transaction::deserialize(const std::string &raw_tx) {
rlp_decoder decoder;
const auto rlp_array = decoder.decode(remove_0x(raw_tx));
FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format");
nonce = add_0x(rlp_array.at(0));
gas_price = add_0x(rlp_array.at(1));
gas_limit = add_0x(rlp_array.at(2));
to = add_0x(rlp_array.at(3));
value = add_0x(rlp_array.at(4));
data = add_0x(rlp_array.at(5));
v = add_0x(rlp_array.at(6));
r = add_0x(rlp_array.at(7));
s = add_0x(rlp_array.at(8));
}
}}} // namespace graphene::peerplays_sidechain::ethereum