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

[WIP][RPC] RingCT output overhaul #688

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
4 changes: 3 additions & 1 deletion src/core_io.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -36,6 +37,7 @@ std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
std::string SighashToStr(unsigned char sighash_type);
mimirmim marked this conversation as resolved.
Show resolved Hide resolved
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address);
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, const std::vector<std::vector<COutPoint>>& vTxRingCtInputs, UniValue& entry, bool include_hex = true, int serialize_flags = 0);
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0);
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,const std::vector<std::vector<COutPoint>>& vTxRingCtInputs, bool include_hex = true, int serialize_flags = 0);

#endif // BITCOIN_CORE_IO_H
95 changes: 93 additions & 2 deletions src/core_write.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -257,7 +258,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
out.pushKV("addresses", a);
mimirmim marked this conversation as resolved.
Show resolved Hide resolved
}

void TxToUniv(const CTransaction& tx, const uint256& hashBlock, const std::vector<std::vector<COutPoint>>& vTxRingCtInputs, UniValue& entry, bool include_hex, int serialize_flags)
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
{
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
Expand All @@ -267,6 +268,88 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, const std::vecto
entry.pushKV("weight", GetTransactionWeight(tx));
entry.pushKV("locktime", (int64_t)tx.nLockTime);

UniValue vin(UniValue::VARR);
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const CTxIn& txin = tx.vin[i];
UniValue in(UniValue::VOBJ);
if (tx.IsCoinBase())
in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
if (txin.IsAnonInput()) {
in.pushKV("type", "anon");
uint32_t nSigInputs, nSigRingSize;
txin.GetAnonInfo(nSigInputs, nSigRingSize);
in.pushKV("num_inputs", (int) nSigInputs);
in.pushKV("ring_size", (int) nSigRingSize);
in.pushKV("ringct_inputs", "To see the RingCT inputs, you must run the core library!");

const std::vector<uint8_t> vKeyImages = txin.scriptData.stack[0];
UniValue arrKeyImages(UniValue::VARR);
for (unsigned int k = 0; k < nSigInputs; k++) {
UniValue objKeyImage(UniValue::VOBJ);
objKeyImage.pushKV(std::to_string(k), HexStr(&vKeyImages[k*33], &vKeyImages[(k*33)+33])); // TODO: add in constant
arrKeyImages.push_back(objKeyImage);
}
in.pushKV("key_images", arrKeyImages);
} else {
in.pushKV("txid", txin.prevout.hash.GetHex());
if (txin.IsZerocoinSpend()) {
in.pushKV("type", "zerocoinspend");
in.pushKV("denomination", FormatMoney(txin.GetZerocoinSpent()));
std::vector<char, zero_after_free_allocator<char> > dataTxIn;
dataTxIn.insert(dataTxIn.end(), txin.scriptSig.begin() + 4, txin.scriptSig.end());
CDataStream serializedCoinSpend(dataTxIn, SER_NETWORK, PROTOCOL_VERSION);
libzerocoin::CoinSpend spend(Params().Zerocoin_Params(), serializedCoinSpend);
in.pushKV("serial", spend.getCoinSerialNumber().GetHex());
if (spend.getVersion() >= 4) {
in.pushKV("pubcoin", spend.getPubcoinValue().GetHex());
}
}
in.pushKV("vout", (int64_t)txin.prevout.n);
UniValue o(UniValue::VOBJ);
o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
in.pushKV("scriptSig", o);
if (!tx.vin[i].scriptWitness.IsNull()) {
UniValue txinwitness(UniValue::VARR);
for (const auto& item : tx.vin[i].scriptWitness.stack) {
txinwitness.push_back(HexStr(item.begin(), item.end()));
}
in.pushKV("txinwitness", txinwitness);
}
}
in.pushKV("sequence", (int64_t)txin.nSequence);
vin.push_back(in);
}
entry.pushKV("vin", vin);

UniValue vout(UniValue::VARR);
auto txid = tx.GetHash();
for (unsigned int i = 0; i < tx.vpout.size(); i++) {
const auto& pout = tx.vpout[i];
UniValue out(UniValue::VOBJ);
OutputToJSON(txid, i, pout.get(), out, tx.IsCoinBase());
vout.push_back(out);
}

entry.pushKV("vout", vout);

if (!hashBlock.IsNull())
entry.pushKV("blockhash", hashBlock.GetHex());

if (include_hex) {
entry.pushKV("hex", EncodeHexTx(tx, serialize_flags)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
}
}

void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, const std::vector<std::vector<COutPoint>>& vTxRingCtInputs, bool include_hex, int serialize_flags) {
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
entry.pushKV("version", tx.nVersion);
entry.pushKV("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
entry.pushKV("weight", GetTransactionWeight(tx));
entry.pushKV("locktime", (int64_t)tx.nLockTime);

UniValue vin(UniValue::VARR);
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const CTxIn& txin = tx.vin[i];
Expand All @@ -280,7 +363,6 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, const std::vecto
in.pushKV("num_inputs", (int) nSigInputs);
in.pushKV("ring_size", (int) nSigRingSize);

//Add ring ct inputs
if (vTxRingCtInputs.size() > i) {
std::vector<COutPoint> vRingCtInputs = vTxRingCtInputs[i];
UniValue arrRing(UniValue::VARR);
Expand All @@ -292,6 +374,15 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, const std::vecto
}
in.pushKV("ringct_inputs", arrRing);
}

const std::vector<uint8_t> vKeyImages = txin.scriptData.stack[0];
UniValue arrKeyImages(UniValue::VARR);
for (unsigned int k = 0; k < nSigInputs; k++) {
UniValue objKeyImage(UniValue::VOBJ);
objKeyImage.pushKV(std::to_string(k), HexStr(&vKeyImages[k*33], &vKeyImages[(k*33)+33])); // TODO: add in constant
arrKeyImages.push_back(objKeyImage);
}
in.pushKV("key_images", arrKeyImages);
} else {
in.pushKV("txid", txin.prevout.hash.GetHex());
if (txin.IsZerocoinSpend()) {
Expand Down
3 changes: 2 additions & 1 deletion src/rest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -380,7 +381,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)

mimirmim marked this conversation as resolved.
Show resolved Hide resolved
case RetFormat::JSON: {
UniValue objTx(UniValue::VOBJ);
TxToUniv(*tx, hashBlock, {{}}, objTx);
TxToUniv(*tx, hashBlock, objTx);
std::string strJSON = objTx.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON);
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
UniValue objTx(UniValue::VOBJ);
std::vector<std::vector<COutPoint> > vInputs;
GetRingCtInputs(tx->vin[0], vInputs);
TxToUniv(*tx, uint256(), vInputs, objTx, true, RPCSerializationFlags());
TxToUniv(*tx, uint256(), objTx, vInputs, true, RPCSerializationFlags());
txs.push_back(objTx);
}
else
Expand Down
17 changes: 10 additions & 7 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -40,14 +41,15 @@
#include <univalue.h>
mimirmim marked this conversation as resolved.
Show resolved Hide resolved


static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, const std::vector<std::vector<COutPoint>>& vTxRingCtInputs)
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
//
// Blockchain contextual information (confirmations and blocktime) is not
// available to code in bitcoin-common, so we query them here and push the
// data into the returned UniValue.
TxToUniv(tx, uint256(), vTxRingCtInputs, entry, true, RPCSerializationFlags());
const std::vector<std::vector<COutPoint>>& vTxRingCtInputs = GetTxRingCtInputs(tx);
TxToUniv(tx, uint256(), entry, vTxRingCtInputs, true, RPCSerializationFlags());

if (!hashBlock.IsNull()) {
LOCK(cs_main);
Expand Down Expand Up @@ -201,10 +203,9 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
}

//Get ringct inputs
std::vector<std::vector<COutPoint> > vTxRingCtInputs = GetTxRingCtInputs(tx);
UniValue result(UniValue::VOBJ);
if (blockindex) result.pushKV("in_active_chain", in_active_chain);
TxToJSON(*tx, hash_block, result, vTxRingCtInputs);
TxToJSON(*tx, hash_block, result);
return result;
}

Expand Down Expand Up @@ -581,7 +582,9 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
}

UniValue result(UniValue::VOBJ);
TxToUniv(CTransaction(std::move(mtx)), uint256(), {{}}, result, false);
CTransaction tx = std::move(mtx);
std::vector<std::vector<COutPoint>> vTxRingCtInputs = GetTxRingCtInputs(tx);
TxToUniv(tx, uint256(), result, vTxRingCtInputs, false);

return result;
}
Expand Down Expand Up @@ -1425,7 +1428,7 @@ UniValue decodepsbt(const JSONRPCRequest& request)

// Add the decoded tx
UniValue tx_univ(UniValue::VOBJ);
TxToUniv(CTransaction(*psbtx.tx), uint256(), {{}}, tx_univ, false);
TxToUniv(CTransaction(*psbtx.tx), uint256(), tx_univ, false);
result.pushKV("tx", tx_univ);

// Unknown data
Expand Down Expand Up @@ -1457,7 +1460,7 @@ UniValue decodepsbt(const JSONRPCRequest& request)
in.pushKV("witness_utxo", out);
} else if (input.non_witness_utxo) {
UniValue non_wit(UniValue::VOBJ);
TxToUniv(*input.non_witness_utxo, uint256(), {{}}, non_wit, false);
TxToUniv(*input.non_witness_utxo, uint256(), non_wit, false);
in.pushKV("non_witness_utxo", non_wit);
total_in += input.non_witness_utxo->vpout[psbtx.tx->vin[i].prevout.n]->GetValue();
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/veil-tx.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -719,7 +720,7 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command,
static void OutputTxJSON(const CTransaction& tx)
mimirmim marked this conversation as resolved.
Show resolved Hide resolved
{
UniValue entry(UniValue::VOBJ);
TxToUniv(tx, uint256(), {{}}, entry);
TxToUniv(tx, uint256(), entry);

std::string jsonOutput = entry.write(4);
fprintf(stdout, "%s\n", jsonOutput.c_str());
Expand Down
5 changes: 3 additions & 2 deletions src/veil/ringct/anon.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2017-2019 The Particl developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -296,10 +297,10 @@ bool RollBackRCTIndex(int64_t nLastValidRCTOutput, int64_t nExpectErase, std::se
return true;
mimirmim marked this conversation as resolved.
Show resolved Hide resolved
}

std::vector<std::vector<COutPoint>> GetTxRingCtInputs(const CTransactionRef ptx)
std::vector<std::vector<COutPoint>> GetTxRingCtInputs(const CTransaction& tx)
{
std::vector<std::vector<COutPoint> > vTxRingCtInputs;
for (const CTxIn& txin : ptx->vin) {
for (const CTxIn& txin : tx.vin) {
if (txin.IsAnonInput()) {
std::vector<COutPoint> vInputs = GetRingCtInputs(txin);
vTxRingCtInputs.emplace_back(vInputs);
Expand Down
3 changes: 2 additions & 1 deletion src/veil/ringct/anon.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2017-2019 The Particl developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef VEIL_ANON_H
Expand Down Expand Up @@ -31,7 +32,7 @@ bool RewindToCheckpoint(int nCheckPointHeight, int &nBlocks, std::string &sError

mimirmim marked this conversation as resolved.
Show resolved Hide resolved
std::vector<COutPoint> GetRingCtInputs(const CTxIn& txin);
bool GetRingCtInputs(const CTxIn& txin, std::vector<std::vector<COutPoint> >& vInputs);
std::vector<std::vector<COutPoint>> GetTxRingCtInputs(const CTransactionRef ptx);
std::vector<std::vector<COutPoint>> GetTxRingCtInputs(const CTransaction& tx);


#endif //VEIL_ANON_H
3 changes: 2 additions & 1 deletion src/veil/ringct/rpcanonwallet.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2017-2019 The Particl Core developers
// Copyright (c) 2019 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -1902,7 +1903,7 @@ static UniValue verifyrawtransaction(const JSONRPCRequest &request)

mimirmim marked this conversation as resolved.
Show resolved Hide resolved
if (!request.params[2].isNull() && request.params[2].get_bool()) {
UniValue txn(UniValue::VOBJ);
TxToUniv(CTransaction(std::move(mtx)), uint256(), {{}}, txn, false);
TxToUniv(CTransaction(std::move(mtx)), uint256(), txn, false);
result.pushKV("txn", txn);
}

Expand Down
Loading