mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-29 16:24:22 +00:00
Used hash of the first TxIn as namespace id. This ensures that the namespace id is unqiue.
TODO: verify that the TxIn is indeed the hash of the first TxIn.
This commit is contained in:
parent
7d80f78f4e
commit
e23a5a6fe8
@ -3,10 +3,12 @@
|
|||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <script/keva.h>
|
#include <script/keva.h>
|
||||||
|
#include <hash.h>
|
||||||
|
#include "base58.h"
|
||||||
|
|
||||||
#include <uint256.h>
|
const std::string CKevaScript::KEVA_DISPLAY_NAME_KEY = "_KEVA_NS_";
|
||||||
|
|
||||||
std::string CKevaScript::KEVA_DISPLAY_NAME_KEY = "_KEVA_NS_";
|
const unsigned char CKevaScript::NAMESPACE_PREFIX = 21; // 2 in base58
|
||||||
|
|
||||||
CKevaScript::CKevaScript (const CScript& script)
|
CKevaScript::CKevaScript (const CScript& script)
|
||||||
: op(OP_NOP), address(script)
|
: op(OP_NOP), address(script)
|
||||||
@ -85,3 +87,18 @@ CScript CKevaScript::buildKevaNamespace(const CScript& addr, const valtype& name
|
|||||||
return prefix + addr;
|
return prefix + addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CScript CKevaScript::replaceKevaNamespace(const CScript& oldScript, const uint256& txId, valtype& kaveNamespace)
|
||||||
|
{
|
||||||
|
CKevaScript kevaOp(oldScript);
|
||||||
|
if (!kevaOp.isNamespaceRegistration()) {
|
||||||
|
assert (false);
|
||||||
|
return CScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
const valtype& displayName = kevaOp.getOpNamespaceDisplayName();
|
||||||
|
kaveNamespace = ToByteVector(Hash160(ToByteVector(txId)));
|
||||||
|
kaveNamespace.insert(kaveNamespace.begin(), NAMESPACE_PREFIX);
|
||||||
|
//kaveNamespace = EncodeBase58(kaveNamespaceVal);
|
||||||
|
return CKevaScript::buildKevaNamespace(kevaOp.getAddress(), kaveNamespace, displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef H_BITCOIN_SCRIPT_KEVA
|
#ifndef H_BITCOIN_SCRIPT_KEVA
|
||||||
#define H_BITCOIN_SCRIPT_KEVA
|
#define H_BITCOIN_SCRIPT_KEVA
|
||||||
|
|
||||||
|
#include <uint256.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
|
|
||||||
class uint160;
|
class uint160;
|
||||||
@ -42,7 +43,9 @@ public:
|
|||||||
* The key pointing to the internal display name. This is the first
|
* The key pointing to the internal display name. This is the first
|
||||||
* key created when a namespace is registered.
|
* key created when a namespace is registered.
|
||||||
*/
|
*/
|
||||||
static std::string KEVA_DISPLAY_NAME_KEY;
|
static const std::string KEVA_DISPLAY_NAME_KEY;
|
||||||
|
|
||||||
|
static const unsigned char NAMESPACE_PREFIX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a script and determine whether it is a valid name script. Sets
|
* Parse a script and determine whether it is a valid name script. Sets
|
||||||
@ -234,6 +237,9 @@ public:
|
|||||||
static CScript buildKevaPut(const CScript& addr, const valtype& nameSpace,
|
static CScript buildKevaPut(const CScript& addr, const valtype& nameSpace,
|
||||||
const valtype& key, const valtype& value);
|
const valtype& key, const valtype& value);
|
||||||
|
|
||||||
|
|
||||||
|
static CScript replaceKevaNamespace(const CScript& oldScript, const uint256& txId, valtype& kaveNamespace);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // H_BITCOIN_SCRIPT_KEVA
|
#endif // H_BITCOIN_SCRIPT_KEVA
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
const unsigned char NAMESPACE_PREFIX = 21; // 2 in base58
|
const int NAMESPACE_LENGTH = 21;
|
||||||
|
const std::string DUMMY_NAMESPACE = "___DUMMY_NAMESPACE___";
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
@ -71,34 +72,32 @@ UniValue keva_namespace(const JSONRPCRequest& request)
|
|||||||
|
|
||||||
CKeyID keyId = pubKey.GetID();
|
CKeyID keyId = pubKey.GetID();
|
||||||
|
|
||||||
// The namespace name is: Hash160(Hash160(keyId) || displayName)
|
// The namespace name is: Hash160("first txin" || displayName)
|
||||||
// JWU TODO: double check this! How can node verify this!!!???
|
// For now we don't know the first txin, so use dummy name here.
|
||||||
valtype toHash = ToByteVector(Hash160(ToByteVector(keyId)));
|
// It will be replaced later in CreateTransaction.
|
||||||
toHash.insert(toHash.end(), displayName.begin(), displayName.end());
|
valtype namespaceDummy = ToByteVector(std::string(DUMMY_NAMESPACE));
|
||||||
valtype namespaceHashVal = ToByteVector(Hash160(toHash));
|
assert(namespaceDummy.size() == NAMESPACE_LENGTH);
|
||||||
namespaceHashVal.insert(namespaceHashVal.begin(), NAMESPACE_PREFIX);
|
|
||||||
const std::string namespaceHash = EncodeBase58(namespaceHashVal);
|
|
||||||
|
|
||||||
//const CScript addrName = GetScriptForDestination(keyId);
|
|
||||||
CScript redeemScript = GetScriptForDestination(WitnessV0KeyHash(keyId));
|
CScript redeemScript = GetScriptForDestination(WitnessV0KeyHash(keyId));
|
||||||
CScriptID scriptHash = CScriptID(redeemScript);
|
CScriptID scriptHash = CScriptID(redeemScript);
|
||||||
CScript addrName = GetScriptForDestination(scriptHash);
|
CScript addrName = GetScriptForDestination(scriptHash);
|
||||||
const CScript newScript = CKevaScript::buildKevaNamespace(addrName, namespaceHashVal, displayName);
|
const CScript newScript = CKevaScript::buildKevaNamespace(addrName, namespaceDummy, displayName);
|
||||||
|
|
||||||
CCoinControl coinControl;
|
CCoinControl coinControl;
|
||||||
CWalletTx wtx;
|
CWalletTx wtx;
|
||||||
SendMoneyToScript(pwallet, newScript, nullptr,
|
valtype kevaNamespace;
|
||||||
|
SendMoneyToScript(pwallet, newScript, nullptr, kevaNamespace,
|
||||||
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
|
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
|
||||||
|
|
||||||
keyName.KeepKey();
|
keyName.KeepKey();
|
||||||
|
|
||||||
|
std::string kevaNamespaceBase58 = EncodeBase58(kevaNamespace);
|
||||||
const std::string txid = wtx.GetHash().GetHex();
|
const std::string txid = wtx.GetHash().GetHex();
|
||||||
LogPrintf("keva_namespace: namespace=%s, displayName=%s, tx=%s\n",
|
LogPrintf("keva_namespace: namespace=%s, displayName=%s, tx=%s\n",
|
||||||
namespaceHash.c_str(), displayNameStr.c_str(), txid.c_str());
|
kevaNamespaceBase58.c_str(), displayNameStr.c_str(), txid.c_str());
|
||||||
|
|
||||||
UniValue res(UniValue::VARR);
|
UniValue res(UniValue::VARR);
|
||||||
res.push_back(txid);
|
res.push_back(txid);
|
||||||
res.push_back(namespaceHash);
|
res.push_back(kevaNamespaceBase58);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -275,7 +274,8 @@ UniValue keva_put(const JSONRPCRequest& request)
|
|||||||
|
|
||||||
CCoinControl coinControl;
|
CCoinControl coinControl;
|
||||||
CWalletTx wtx;
|
CWalletTx wtx;
|
||||||
SendMoneyToScript(pwallet, kevaScript, &txIn,
|
valtype empty;
|
||||||
|
SendMoneyToScript(pwallet, kevaScript, &txIn, empty,
|
||||||
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
|
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
|
||||||
|
|
||||||
if (usedKey) {
|
if (usedKey) {
|
||||||
|
@ -428,7 +428,8 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
|
|||||||
int nChangePosRet = -1;
|
int nChangePosRet = -1;
|
||||||
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
|
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
|
||||||
vecSend.push_back(recipient);
|
vecSend.push_back(recipient);
|
||||||
if (!pwallet->CreateTransaction(vecSend, nullptr, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
|
std::vector<unsigned char> empty;
|
||||||
|
if (!pwallet->CreateTransaction(vecSend, nullptr, empty, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
|
||||||
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
|
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
|
||||||
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||||
@ -441,7 +442,9 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SendMoneyToScript(CWallet* const pwallet, const CScript &scriptPubKey,
|
void SendMoneyToScript(CWallet* const pwallet, const CScript &scriptPubKey,
|
||||||
const CTxIn* withInput, CAmount nValue,
|
const CTxIn* withInput,
|
||||||
|
std::vector<unsigned char>& kevaNamespace,
|
||||||
|
CAmount nValue,
|
||||||
bool fSubtractFeeFromAmount, CWalletTx& wtxNew,
|
bool fSubtractFeeFromAmount, CWalletTx& wtxNew,
|
||||||
const CCoinControl& coin_control)
|
const CCoinControl& coin_control)
|
||||||
{
|
{
|
||||||
@ -478,7 +481,7 @@ void SendMoneyToScript(CWallet* const pwallet, const CScript &scriptPubKey,
|
|||||||
int nChangePosRet = -1;
|
int nChangePosRet = -1;
|
||||||
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
|
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
|
||||||
vecSend.push_back(recipient);
|
vecSend.push_back(recipient);
|
||||||
if (!pwallet->CreateTransaction(vecSend, withInput, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
|
if (!pwallet->CreateTransaction(vecSend, withInput, kevaNamespace, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
|
||||||
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
|
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
|
||||||
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||||
@ -1200,7 +1203,8 @@ UniValue sendmany(const JSONRPCRequest& request)
|
|||||||
CAmount nFeeRequired = 0;
|
CAmount nFeeRequired = 0;
|
||||||
int nChangePosRet = -1;
|
int nChangePosRet = -1;
|
||||||
std::string strFailReason;
|
std::string strFailReason;
|
||||||
bool fCreated = pwallet->CreateTransaction(vecSend, nullptr, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
|
std::vector<unsigned char> empty; empty;
|
||||||
|
bool fCreated = pwallet->CreateTransaction(vecSend, nullptr, empty, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
|
||||||
if (!fCreated)
|
if (!fCreated)
|
||||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
|
@ -27,7 +27,9 @@ std::string HelpRequiringPassphrase(CWallet *);
|
|||||||
void EnsureWalletIsUnlocked(CWallet *);
|
void EnsureWalletIsUnlocked(CWallet *);
|
||||||
bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
|
bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
|
||||||
void SendMoneyToScript(CWallet* pwallet, const CScript& scriptPubKey,
|
void SendMoneyToScript(CWallet* pwallet, const CScript& scriptPubKey,
|
||||||
const CTxIn* withInput, CAmount nValue,
|
const CTxIn* withInput,
|
||||||
|
std::vector<unsigned char>& kevaNamespace,
|
||||||
|
CAmount nValue,
|
||||||
bool fSubtractFeeFromAmount, CWalletTx& wtxNew,
|
bool fSubtractFeeFromAmount, CWalletTx& wtxNew,
|
||||||
const CCoinControl& coin_control);
|
const CCoinControl& coin_control);
|
||||||
|
|
||||||
|
@ -636,7 +636,8 @@ public:
|
|||||||
int changePos = -1;
|
int changePos = -1;
|
||||||
std::string error;
|
std::string error;
|
||||||
CCoinControl dummy;
|
CCoinControl dummy;
|
||||||
BOOST_CHECK(wallet->CreateTransaction({recipient}, nullptr, wtx, reservekey, fee, changePos, error, dummy));
|
std::vector<unsigned char> empty;
|
||||||
|
BOOST_CHECK(wallet->CreateTransaction({recipient}, nullptr, empty, wtx, reservekey, fee, changePos, error, dummy));
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
BOOST_CHECK(wallet->CommitTransaction(wtx, reservekey, nullptr, state));
|
BOOST_CHECK(wallet->CommitTransaction(wtx, reservekey, nullptr, state));
|
||||||
CMutableTransaction blocktx;
|
CMutableTransaction blocktx;
|
||||||
|
@ -2628,7 +2628,8 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
|
|||||||
|
|
||||||
CReserveKey reservekey(this);
|
CReserveKey reservekey(this);
|
||||||
CWalletTx wtx;
|
CWalletTx wtx;
|
||||||
if (!CreateTransaction(vecSend, nullptr, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
|
std::vector<unsigned char> empty;
|
||||||
|
if (!CreateTransaction(vecSend, nullptr, empty, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2689,6 +2690,7 @@ OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vec
|
|||||||
|
|
||||||
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||||
const CTxIn* withInput,
|
const CTxIn* withInput,
|
||||||
|
std::vector<unsigned char>& kaveNamespace,
|
||||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
|
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
|
||||||
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
|
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
|
||||||
{
|
{
|
||||||
@ -2708,9 +2710,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
|||||||
if (recipient.fSubtractFeeFromAmount)
|
if (recipient.fSubtractFeeFromAmount)
|
||||||
nSubtractFeeFromAmount++;
|
nSubtractFeeFromAmount++;
|
||||||
|
|
||||||
if (CKevaScript::isKevaScript (recipient.scriptPubKey))
|
if (CKevaScript::isKevaScript(recipient.scriptPubKey)) {
|
||||||
isKevacoin = true;
|
isKevacoin = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (vecSend.empty())
|
if (vecSend.empty())
|
||||||
{
|
{
|
||||||
strFailReason = _("Transaction must have at least one recipient");
|
strFailReason = _("Transaction must have at least one recipient");
|
||||||
@ -2919,9 +2922,21 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
|||||||
// and in the spirit of "smallest possible change from prior
|
// and in the spirit of "smallest possible change from prior
|
||||||
// behavior."
|
// behavior."
|
||||||
const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
|
const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
|
||||||
for (const auto& coin : setCoins)
|
bool kevaDummyReplaced = false;
|
||||||
txNew.vin.push_back(CTxIn(coin.outpoint,CScript(),
|
for (const auto& coin : setCoins) {
|
||||||
nSequence));
|
txNew.vin.push_back(CTxIn(coin.outpoint,CScript(), nSequence));
|
||||||
|
if (isKevacoin && !kevaDummyReplaced) {
|
||||||
|
for (std::vector<CTxOut>::iterator iter = txNew.vout.begin(); iter != txNew.vout.end(); ++iter) {
|
||||||
|
CScript dummyScript = iter->scriptPubKey;
|
||||||
|
CKevaScript kevaOp(dummyScript);
|
||||||
|
if (kevaOp.isKevaOp() && kevaOp.isNamespaceRegistration()) {
|
||||||
|
iter->scriptPubKey = CKevaScript::replaceKevaNamespace(dummyScript, coin.outpoint.hash, kaveNamespace);
|
||||||
|
kevaDummyReplaced = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fill in dummy signatures for fee calculation.
|
// Fill in dummy signatures for fee calculation.
|
||||||
if (!DummySignTx(txNew, setCoins)) {
|
if (!DummySignTx(txNew, setCoins)) {
|
||||||
@ -3131,11 +3146,9 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
|
|||||||
{
|
{
|
||||||
// Broadcast
|
// Broadcast
|
||||||
if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
|
if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
|
||||||
printf("JWU Transaction cannot be broadcast immediately! \n");
|
|
||||||
LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", state.GetRejectReason());
|
LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", state.GetRejectReason());
|
||||||
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
|
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
|
||||||
} else {
|
} else {
|
||||||
printf("JWU Transaction CAN OK be broadcast immediately! \n");
|
|
||||||
wtx.RelayWalletTransaction(connman);
|
wtx.RelayWalletTransaction(connman);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -993,6 +993,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool CreateTransaction(const std::vector<CRecipient>& vecSend,
|
bool CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||||
const CTxIn* withInput,
|
const CTxIn* withInput,
|
||||||
|
std::vector<unsigned char>& kaveNamespace,
|
||||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
|
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
|
||||||
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
|
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
|
||||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
|
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user