Skip to content

Commit

Permalink
Add CAssetsDir
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenroose committed Mar 20, 2019
1 parent 10773c6 commit 84954c8
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ BITCOIN_CORE_H = \
addrdb.h \
addrman.h \
asset.h \
assetsdir.h \
base58.h \
bech32.h \
blech32.h \
Expand Down Expand Up @@ -292,6 +293,7 @@ endif
libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_wallet_a_SOURCES = \
assetsdir.cpp \
interfaces/wallet.cpp \
wallet/coincontrol.cpp \
wallet/crypter.cpp \
Expand Down
99 changes: 99 additions & 0 deletions src/assetsdir.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2017-2017 The Elements Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <assetsdir.h>
#include <chainparams.h>

#include <tinyformat.h>
#include <utilstrencodings.h>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

void CAssetsDir::Set(const CAsset& asset, const AssetMetadata& metadata)
{
// No asset or label repetition
if (GetLabel(asset) != "")
throw std::runtime_error(strprintf("duplicated asset '%s'", asset.GetHex()));
if (GetAsset(metadata.GetLabel()) != CAsset())
throw std::runtime_error(strprintf("duplicated label '%s'", metadata.GetLabel()));

mapAssetMetadata[asset] = metadata;
mapAssets[metadata.GetLabel()] = asset;
}

void CAssetsDir::SetHex(const std::string& assetHex, const std::string& label)
{
if (!IsHex(assetHex) || assetHex.size() != 64)
throw std::runtime_error("The asset must be hex string of length 64");

const std::vector<std::string> protectedLabels = {"", "*", "bitcoin", "Bitcoin", "btc"};
for (std::string proLabel : protectedLabels) {
if (label == proLabel) {
throw std::runtime_error(strprintf("'%s' label is protected", proLabel));
}
}
Set(CAsset(uint256S(assetHex)), AssetMetadata(label));
}

void CAssetsDir::InitFromStrings(const std::vector<std::string>& assetsToInit, const std::string& pegged_asset_name)
{
for (std::string strToSplit : assetsToInit) {
std::vector<std::string> vAssets;
boost::split(vAssets, strToSplit, boost::is_any_of(":"));
if (vAssets.size() != 2) {
throw std::runtime_error("-assetdir parameters malformed, expecting asset:label");
}
SetHex(vAssets[0], vAssets[1]);
}
// Set "bitcoin" to the pegged asset for tests
Set(Params().GetConsensus().pegged_asset, AssetMetadata(pegged_asset_name));
}

CAsset CAssetsDir::GetAsset(const std::string& label) const
{
auto it = mapAssets.find(label);
if (it != mapAssets.end())
return it->second;
return CAsset();
}

AssetMetadata CAssetsDir::GetMetadata(const CAsset& asset) const
{
auto it = mapAssetMetadata.find(asset);
if (it != mapAssetMetadata.end())
return it->second;
return AssetMetadata("");
}

std::string CAssetsDir::GetLabel(const CAsset& asset) const
{
return GetMetadata(asset).GetLabel();
}

std::vector<CAsset> CAssetsDir::GetKnownAssets() const
{
std::vector<CAsset> knownAssets;
for (auto it = mapAssets.begin(); it != mapAssets.end(); it++) {
knownAssets.push_back(it->second);
}
return knownAssets;
}

CAsset GetAssetFromString(const std::string& strasset) {
CAsset asset = gAssetsDir.GetAsset(strasset);
if (asset.IsNull() && strasset.size() == 64 && IsHex(strasset)) {
asset = CAsset(uint256S(strasset));
}
return asset;
}

// GLOBAL:
CAssetsDir _gAssetsDir;
const CAssetsDir& gAssetsDir = _gAssetsDir;

void InitGlobalAssetDir(const std::vector<std::string>& assetsToInit, const std::string& pegged_asset_name)
{
_gAssetsDir.InitFromStrings(assetsToInit, pegged_asset_name);
}
60 changes: 60 additions & 0 deletions src/assetsdir.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

#ifndef BITCOIN_ASSETSDIR_H
#define BITCOIN_ASSETSDIR_H

#include <asset.h>

#include <map>

class AssetMetadata
{
std::string label;
public:
AssetMetadata() : label("") {};
AssetMetadata(std::string _label) : label(_label) {};

const std::string& GetLabel() const
{
return label;
}
};

class CAssetsDir
{
std::map<CAsset, AssetMetadata> mapAssetMetadata;
std::map<std::string, CAsset> mapAssets;

void Set(const CAsset& asset, const AssetMetadata& metadata);
void SetHex(const std::string& assetHex, const std::string& label);
public:
void InitFromStrings(const std::vector<std::string>& assetsToInit, const std::string& pegged_asset_name);

/**
* @param label A label string
* @return asset id corresponding to the asset label
*/
CAsset GetAsset(const std::string& label) const;

AssetMetadata GetMetadata(const CAsset& asset) const;

/** @return the label associated to the asset id */
std::string GetLabel(const CAsset& asset) const;

std::vector<CAsset> GetKnownAssets() const;
};

/**
* Returns asset id corresponding to the given asset expression, which is either an asset label or a hex value.
* @param strasset A label string or a hex value corresponding to an asset
* @return The asset ID for the given expression
*/
CAsset GetAssetFromString(const std::string& strasset);

// GLOBAL:
class CAssetsDir;

extern const CAssetsDir& gAssetsDir;

void InitGlobalAssetDir(const std::vector<std::string>& assetsToInit, const std::string& pegged_asset_name);

#endif // BITCOIN_ASSETSDIR_H
10 changes: 10 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include <openssl/crypto.h>

#include <primitives/pak.h> // CPAKList
#include <assetsdir.h> // InitGlobalAssetDir

#if ENABLE_ZMQ
#include <zmq/zmqnotificationinterface.h>
Expand Down Expand Up @@ -509,6 +510,8 @@ void SetupServerArgs()
gArgs.AddArg("-extprvkeyprefix", strprintf("The 4-byte prefix, in hex, of the chain's base58 extended private key encoding. (default: %s)", HexStr(defaultChainParams->Base58Prefix(CChainParams::EXT_SECRET_KEY))), false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-bech32_hrp", strprintf("The human-readable part of the chain's bech32 encoding. (default: %s)", defaultChainParams->Bech32HRP()), false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-blech32_hrp", strprintf("The human-readable part of the chain's blech32 encoding. Used in confidential addresses.(default: %s)", defaultChainParams->Blech32HRP()), false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-assetdir", "Entries of pet names of assets, in this format:asset=<hex>:<label>. There can be any number of entries.", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-defaultpeggedassetname", "Default name of the pegged asset. (default: bitcoin)", false, OptionsCategory::ELEMENTS);

#if HAVE_DECL_DAEMON
gArgs.AddArg("-daemon", "Run in the background as a daemon and accept commands", false, OptionsCategory::OPTIONS);
Expand Down Expand Up @@ -1163,6 +1166,13 @@ bool AppInitParameterInteraction()
}
}

try {
const std::string default_asset_name = gArgs.GetArg("-defaultpeggedassetname", "bitcoin");
InitGlobalAssetDir(gArgs.GetArgs("-assetdir"), default_asset_name);
} catch (const std::exception& e) {
return InitError(strprintf("Error in -assetdir: %s\n", e.what()));
}

return true;
}

Expand Down
18 changes: 18 additions & 0 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#include <univalue.h>

#include <assetsdir.h>

static UniValue validateaddress(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
Expand Down Expand Up @@ -542,6 +544,21 @@ UniValue calcfastmerkleroot(const JSONRPCRequest& request)
return ret;
}

UniValue dumpassetlabels(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
"dumpassetlabels\n"
"\nLists all known asset id/label pairs in this wallet. This list can be modified with `-assetdir` configuration argument.\n"
+ HelpExampleCli("dumpassetlabels", "" )
+ HelpExampleRpc("dumpassetlabels", "" )
);
UniValue obj(UniValue::VOBJ);
for (const auto& as : gAssetsDir.GetKnownAssets()) {
obj.pushKV(gAssetsDir.GetLabel(as), as.GetHex());
}
return obj;
}

class BlindingPubkeyAdderVisitor : public boost::static_visitor<>
{
Expand Down Expand Up @@ -643,6 +660,7 @@ static const CRPCCommand commands[] =
{ "util", "getpakinfo", &getpakinfo, {}},
{ "util", "tweakfedpegscript", &tweakfedpegscript, {"claim_script"} },
{ "util", "createblindedaddress", &createblindedaddress, {"address", "blinding_key"}},
{ "util", "dumpassetlabels", &dumpassetlabels, {}},
{ "hidden", "calcfastmerkleroot", &calcfastmerkleroot, {"leaves"} },

/* Not shown in help */
Expand Down
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
'rpc_calcfastmerkleroot.py',
'feature_txwitness.py',
'rpc_tweakfedpeg.py',
'feature_assetsdir.py',
# Longest test should go first, to favor running tests in parallel
'feature_fee_estimation.py',
'wallet_hd.py',
Expand Down

0 comments on commit 84954c8

Please sign in to comment.