mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-27 07:14:48 +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.
|
||||
|
||||
#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)
|
||||
: op(OP_NOP), address(script)
|
||||
@ -85,3 +87,18 @@ CScript CKevaScript::buildKevaNamespace(const CScript& addr, const valtype& name
|
||||
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
|
||||
#define H_BITCOIN_SCRIPT_KEVA
|
||||
|
||||
#include <uint256.h>
|
||||
#include <script/script.h>
|
||||
|
||||
class uint160;
|
||||
@ -42,7 +43,9 @@ public:
|
||||
* The key pointing to the internal display name. This is the first
|
||||
* 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
|
||||
@ -234,6 +237,9 @@ public:
|
||||
static CScript buildKevaPut(const CScript& addr, const valtype& nameSpace,
|
||||
const valtype& key, const valtype& value);
|
||||
|
||||
|
||||
static CScript replaceKevaNamespace(const CScript& oldScript, const uint256& txId, valtype& kaveNamespace);
|
||||
|
||||
};
|
||||
|
||||
#endif // H_BITCOIN_SCRIPT_KEVA
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
#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();
|
||||
|
||||
// The namespace name is: Hash160(Hash160(keyId) || displayName)
|
||||
// JWU TODO: double check this! How can node verify this!!!???
|
||||
valtype toHash = ToByteVector(Hash160(ToByteVector(keyId)));
|
||||
toHash.insert(toHash.end(), displayName.begin(), displayName.end());
|
||||
valtype namespaceHashVal = ToByteVector(Hash160(toHash));
|
||||
namespaceHashVal.insert(namespaceHashVal.begin(), NAMESPACE_PREFIX);
|
||||
const std::string namespaceHash = EncodeBase58(namespaceHashVal);
|
||||
// The namespace name is: Hash160("first txin" || displayName)
|
||||
// For now we don't know the first txin, so use dummy name here.
|
||||
// It will be replaced later in CreateTransaction.
|
||||
valtype namespaceDummy = ToByteVector(std::string(DUMMY_NAMESPACE));
|
||||
assert(namespaceDummy.size() == NAMESPACE_LENGTH);
|
||||
|
||||
//const CScript addrName = GetScriptForDestination(keyId);
|
||||
CScript redeemScript = GetScriptForDestination(WitnessV0KeyHash(keyId));
|
||||
CScriptID scriptHash = CScriptID(redeemScript);
|
||||
CScript addrName = GetScriptForDestination(scriptHash);
|
||||
const CScript newScript = CKevaScript::buildKevaNamespace(addrName, namespaceHashVal, displayName);
|
||||
const CScript newScript = CKevaScript::buildKevaNamespace(addrName, namespaceDummy, displayName);
|
||||
|
||||
CCoinControl coinControl;
|
||||
CWalletTx wtx;
|
||||
SendMoneyToScript(pwallet, newScript, nullptr,
|
||||
valtype kevaNamespace;
|
||||
SendMoneyToScript(pwallet, newScript, nullptr, kevaNamespace,
|
||||
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
|
||||
|
||||
keyName.KeepKey();
|
||||
|
||||
std::string kevaNamespaceBase58 = EncodeBase58(kevaNamespace);
|
||||
const std::string txid = wtx.GetHash().GetHex();
|
||||
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);
|
||||
res.push_back(txid);
|
||||
res.push_back(namespaceHash);
|
||||
res.push_back(kevaNamespaceBase58);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -275,7 +274,8 @@ UniValue keva_put(const JSONRPCRequest& request)
|
||||
|
||||
CCoinControl coinControl;
|
||||
CWalletTx wtx;
|
||||
SendMoneyToScript(pwallet, kevaScript, &txIn,
|
||||
valtype empty;
|
||||
SendMoneyToScript(pwallet, kevaScript, &txIn, empty,
|
||||
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
|
||||
|
||||
if (usedKey) {
|
||||
|
@ -428,7 +428,8 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
|
||||
int nChangePosRet = -1;
|
||||
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
|
||||
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)
|
||||
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
||||
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,
|
||||
const CTxIn* withInput, CAmount nValue,
|
||||
const CTxIn* withInput,
|
||||
std::vector<unsigned char>& kevaNamespace,
|
||||
CAmount nValue,
|
||||
bool fSubtractFeeFromAmount, CWalletTx& wtxNew,
|
||||
const CCoinControl& coin_control)
|
||||
{
|
||||
@ -478,7 +481,7 @@ void SendMoneyToScript(CWallet* const pwallet, const CScript &scriptPubKey,
|
||||
int nChangePosRet = -1;
|
||||
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
|
||||
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)
|
||||
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||
@ -1200,7 +1203,8 @@ UniValue sendmany(const JSONRPCRequest& request)
|
||||
CAmount nFeeRequired = 0;
|
||||
int nChangePosRet = -1;
|
||||
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)
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
||||
CValidationState state;
|
||||
|
@ -27,7 +27,9 @@ std::string HelpRequiringPassphrase(CWallet *);
|
||||
void EnsureWalletIsUnlocked(CWallet *);
|
||||
bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
|
||||
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,
|
||||
const CCoinControl& coin_control);
|
||||
|
||||
|
@ -636,7 +636,8 @@ public:
|
||||
int changePos = -1;
|
||||
std::string error;
|
||||
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;
|
||||
BOOST_CHECK(wallet->CommitTransaction(wtx, reservekey, nullptr, state));
|
||||
CMutableTransaction blocktx;
|
||||
|
@ -2628,7 +2628,8 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
|
||||
|
||||
CReserveKey reservekey(this);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2689,6 +2690,7 @@ OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vec
|
||||
|
||||
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||
const CTxIn* withInput,
|
||||
std::vector<unsigned char>& kaveNamespace,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
|
||||
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
|
||||
{
|
||||
@ -2708,8 +2710,9 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||
if (recipient.fSubtractFeeFromAmount)
|
||||
nSubtractFeeFromAmount++;
|
||||
|
||||
if (CKevaScript::isKevaScript (recipient.scriptPubKey))
|
||||
if (CKevaScript::isKevaScript(recipient.scriptPubKey)) {
|
||||
isKevacoin = true;
|
||||
}
|
||||
}
|
||||
if (vecSend.empty())
|
||||
{
|
||||
@ -2919,9 +2922,21 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||
// and in the spirit of "smallest possible change from prior
|
||||
// behavior."
|
||||
const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
|
||||
for (const auto& coin : setCoins)
|
||||
txNew.vin.push_back(CTxIn(coin.outpoint,CScript(),
|
||||
nSequence));
|
||||
bool kevaDummyReplaced = false;
|
||||
for (const auto& coin : setCoins) {
|
||||
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.
|
||||
if (!DummySignTx(txNew, setCoins)) {
|
||||
@ -3131,11 +3146,9 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
|
||||
{
|
||||
// Broadcast
|
||||
if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
|
||||
printf("JWU Transaction cannot be broadcast immediately! \n");
|
||||
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.
|
||||
} else {
|
||||
printf("JWU Transaction CAN OK be broadcast immediately! \n");
|
||||
wtx.RelayWalletTransaction(connman);
|
||||
}
|
||||
}
|
||||
|
@ -993,6 +993,7 @@ public:
|
||||
*/
|
||||
bool CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||
const CTxIn* withInput,
|
||||
std::vector<unsigned char>& kaveNamespace,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
|
||||
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
|
||||
|
Loading…
x
Reference in New Issue
Block a user