Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
40571ab
Turn on secp-zkp experimental modules for PAK
instagibbs Dec 14, 2018
378e594
Define PAKList structure and operations
instagibbs Jan 3, 2019
43424cb
Add PAK proof validation function
instagibbs Jan 17, 2019
8c7746c
Add CScript::IsPayToPubkeyHash convienience function
instagibbs Dec 17, 2018
6679823
Create global PAK lists for config and blockchain state
instagibbs Jan 3, 2019
2b4899d
PAK enforcement via standardness, drop multi-op_return restriction
instagibbs Dec 17, 2018
bf66d77
Add Read/Write functions to txdb for PAK lists
instagibbs Dec 17, 2018
86fbc24
GetPAKKeysFromCommitment utility function
instagibbs Dec 17, 2018
9f5cc03
Read PAK list from connected blocks, save list, and boot transactions…
instagibbs Dec 17, 2018
f1dbd1c
-multi_data_permitted: Allow >1 op_return output by policy
instagibbs Dec 17, 2018
1559cc9
C(Pub)Key::Derive: Return optional tweak vector for peg-out wallets
instagibbs Dec 17, 2018
4e631bd
Add derivation helpers for peg-out wallet infrastructure
instagibbs Dec 17, 2018
47422e7
Write and load peg-out wallet functions on wallet load
instagibbs Dec 17, 2018
070be0f
add initpegout RPC for peg-out wallet initialization
instagibbs Dec 17, 2018
567de67
Break out sendtomainchain to call functions based on -enforce_pak
instagibbs Dec 17, 2018
3cfe2d4
Add sendtomainchain RPC call which is used when -pak_enforce is enabled
instagibbs Dec 17, 2018
050bb49
Add getpakinfo RPC call, without wallet state
instagibbs Dec 17, 2018
0e52456
Return status of pak enforcement on the blockchain in
instagibbs Dec 17, 2018
f06e6f6
Wallet offline_counter starts at -1
instagibbs Dec 17, 2018
d391782
Add getwalletpakinfo RPC call
instagibbs Dec 17, 2018
5b6d767
Load PAK arguments from config and disk on startup
instagibbs Dec 18, 2018
bcd8db9
functional test for pak feature
instagibbs Dec 18, 2018
dfe5331
Miner adds PAK commitments when config 'disagress' with block commits
instagibbs Dec 20, 2018
3fc3ac3
disallow pak enforcement arg when nonstandard tx are possible
instagibbs Dec 20, 2018
47ea638
miner adds commitment when pak enforcement is set only
instagibbs Dec 20, 2018
1241343
testproposedblock: Reject blocks with non-matching pak commitments
instagibbs Jan 2, 2019
71acfb3
Add IsPayToWitnessPubkeyHash convenience function
instagibbs Jan 3, 2019
542b826
ScriptHasvalidPAKProof: Allow any standard single-key output script type
instagibbs Jan 3, 2019
8de4237
fixup mempool clearing of peg-outs on block commitment
instagibbs Jan 7, 2019
85bcda5
pak mempool removal: don't modify the vector you are taking range over
instagibbs Jan 7, 2019
7e63ce3
Extend validateaddress to check parent address validity.
instagibbs Jan 11, 2019
6366734
Properly encode parent witness addresses
instagibbs Jan 11, 2019
1cb252e
Descriptor support in PAK infrastructure and tests
instagibbs Jan 11, 2019
19ef5e3
Add link to pak authorization design in secp-zpk
instagibbs Jan 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@ if test x$need_bundled_univalue = xyes; then
AC_CONFIG_SUBDIRS([src/univalue])
fi

ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery --disable-jni"
ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery --disable-jni --enable-experimental --enable-module-whitelist --enable-module-rangeproof --enable-module-generator"
AC_CONFIG_SUBDIRS([src/secp256k1])

AC_OUTPUT
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ libbitcoin_consensus_a_SOURCES = \
primitives/block.h \
primitives/transaction.cpp \
primitives/transaction.h \
primitives/pak.cpp \
primitives/pak.h \
primitives/bitcoin/block.cpp \
primitives/bitcoin/block.h \
primitives/bitcoin/merkleblock.cpp \
Expand Down
12 changes: 12 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ class CMainParams : public CChainParams {
consensus.genesis_subsidy = 50*COIN;
consensus.connect_genesis_outputs = false;
anyonecanspend_aremine = false;
enforce_pak = false;
multi_data_permitted = false;

/**
* The message start string is designed to be unlikely to occur in normal data.
Expand Down Expand Up @@ -271,6 +273,8 @@ class CTestNetParams : public CChainParams {
consensus.genesis_subsidy = 50*COIN;
consensus.connect_genesis_outputs = false;
anyonecanspend_aremine = false;
enforce_pak = false;
multi_data_permitted = false;

pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
Expand Down Expand Up @@ -364,6 +368,8 @@ class CRegTestParams : public CChainParams {
consensus.genesis_subsidy = 50*COIN;
consensus.connect_genesis_outputs = false;
anyonecanspend_aremine = false;
enforce_pak = false;
multi_data_permitted = false;

pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
Expand Down Expand Up @@ -541,6 +547,12 @@ class CCustomParams : public CRegTestParams {
anyonecanspend_aremine = args.GetBoolArg("-anyonecanspendaremine", true);

consensus.has_parent_chain = args.GetBoolArg("-con_has_parent_chain", true);

enforce_pak = args.GetBoolArg("-enforce_pak", false);

// Allow multiple op_return outputs by relay policy
multi_data_permitted = args.GetBoolArg("-multi_data_permitted", true);

// bitcoin regtest is the parent chain by default
parentGenesisBlockHash = uint256S(args.GetArg("-parentgenesisblockhash", "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
// Either it has a parent chain or not
Expand Down
4 changes: 4 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class CChainParams
const uint256 ParentGenesisBlockHash() const { return parentGenesisBlockHash; }
bool anyonecanspend_aremine;
const std::string& ParentBech32HRP() const { return parent_bech32_hrp; }
bool GetEnforcePak() const { return enforce_pak; }
bool GetMultiDataPermitted() const { return multi_data_permitted; }

protected:
CChainParams() {}
Expand All @@ -111,6 +113,8 @@ class CChainParams
// ELEMENTS extra fields:
uint256 parentGenesisBlockHash;
std::string parent_bech32_hrp;
bool enforce_pak;
bool multi_data_permitted;
};

/**
Expand Down
3 changes: 3 additions & 0 deletions src/chainparamsbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ void SetupChainParamsBaseOptions()
gArgs.AddArg("-con_parent_chain_signblockscript", "Whether parent chain uses pow or signed blocks. If the parent chain uses signed blocks, the challenge (scriptPubKey) script. If not, an empty string. (default: empty script [ie parent uses pow])", false, OptionsCategory::CHAINPARAMS);

gArgs.AddArg("-fedpegscript", "The script for the federated peg.", false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-enforce_pak", "Causes standardness checks to enforce Pegout Authorization Key(PAK) validation, and miner to include PAK commitments when configured. Can not be set when acceptnonstdtx is set to true.", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-multi_data_permitted", "Allow relay of multiple OP_RETURN outputs. (default: true)", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-pak", "Entries in the PAK list. Order of entries matter.", false, OptionsCategory::ELEMENTS);
}

static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
Expand Down
69 changes: 68 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
#include <boost/thread.hpp>
#include <openssl/crypto.h>

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

#if ENABLE_ZMQ
#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqrpc.h>
Expand Down Expand Up @@ -1760,7 +1762,72 @@ bool AppInitMain()
return false;
}

// ********************************************************* Step 13: finished
// ********************************************************* Step 13: Load PAK List

// First, make sure -enforce_pak and -acceptnonstdtxn aren't conflicting
if (Params().GetEnforcePak() && gArgs.GetBoolArg("-acceptnonstdtxn", !Params().RequireStandard())) {
return InitError("-enforce_pak can not be true if the network accepts non-standard transactions for relay.");
}

//Entire list of PAK entries from conf must be of valid format
std::vector<std::string> pak_list_str = gArgs.GetArgs("-pak");
bool valid_paklist = true;
bool is_reject = false;
std::vector<std::vector<unsigned char> > offline_keys;
std::vector<std::vector<unsigned char> > online_keys;
for (unsigned int i = 0; i < pak_list_str.size(); i++) {
if (pak_list_str[i] == "reject") {
is_reject = true;
continue;
}

size_t colon_index = pak_list_str[i].find(":");
if (colon_index == std::string::npos) {
valid_paklist = false;
break;
}

std::string offline = pak_list_str[i].substr(0, colon_index);
std::string online = pak_list_str[i].substr(colon_index + 1);

if (!IsHex(offline) || !IsHex(online) || offline.size() != 66 || online.size() != 66) {
valid_paklist = false;
break;
}

online_keys.push_back(ParseHex(online));
offline_keys.push_back(ParseHex(offline));
}
// pak=reject must be alone
if (is_reject && offline_keys.size() > 0)
valid_paklist = false;
if (!valid_paklist)
return InitError(_("ERROR: Invalid PAK entries given in conf file."));
if (is_reject || offline_keys.size() > 0) {
CPAKList paklist;
if(CPAKList::FromBytes(paklist, offline_keys, online_keys, is_reject)) {
g_paklist_config = paklist;
} else {
return InitError(_("ERROR: Invalid PAK entries given in conf file."));
}
} else {
g_paklist_config = boost::none;
}

// Read and parse committed pak list from disk
CPAKList paklist;
offline_keys.resize(0);
online_keys.resize(0);
bool reject;
if (pblocktree->ReadPAKList(offline_keys, online_keys, reject)) {
if (CPAKList::FromBytes(paklist, offline_keys, online_keys, reject)) {
g_paklist_blockchain = paklist;
} else {
return InitError(_("ERROR: Read invalid PAK list."));
}
}

// ********************************************************* Step 14: finished

SetRPCWarmupFinished();

Expand Down
6 changes: 5 additions & 1 deletion src/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ bool CKey::Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipChe
return VerifyPubKey(vchPubKey);
}

bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, std::vector<unsigned char>* tweak) const {
assert(IsValid());
assert(IsCompressed());
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
Expand All @@ -277,6 +277,10 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
assert(size() == 32);
BIP32Hash(cc, nChild, 0, begin(), vout.data());
}
if (tweak) {
tweak->clear();
*tweak = std::vector<unsigned char>(vout.data(), vout.data()+32);
}
memcpy(ccChild.begin(), vout.data()+32, 32);
memcpy((unsigned char*)keyChild.begin(), begin(), 32);
bool ret = secp256k1_ec_privkey_tweak_add(secp256k1_context_sign, (unsigned char*)keyChild.begin(), vout.data());
Expand Down
2 changes: 1 addition & 1 deletion src/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class CKey
bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;

//! Derive BIP32 child key.
bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, std::vector<unsigned char>* tweak = nullptr /* ELEMENTS: vector of key tweak values that are filled out if non-null */) const;

/**
* Verify thoroughly whether a private key and a public key match.
Expand Down
6 changes: 4 additions & 2 deletions src/key_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,17 @@ class DestinationEncoder : public boost::static_visitor<std::string>
std::vector<unsigned char> data = {0};
data.reserve(33);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
const std::string& hrp = for_parent ? m_params.ParentBech32HRP() : m_params.Bech32HRP();
return bech32::Encode(hrp, data);
}

std::string operator()(const WitnessV0ScriptHash& id) const
{
std::vector<unsigned char> data = {0};
data.reserve(53);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
const std::string& hrp = for_parent ? m_params.ParentBech32HRP() : m_params.Bech32HRP();
return bech32::Encode(hrp, data);
}

std::string operator()(const WitnessUnknown& id) const
Expand Down
23 changes: 23 additions & 0 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,23 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
return nullptr;
pblock = &pblocktemplate->block; // pointer for convenience

std::vector<CScript> commitments;

// ELEMENTS: PAK
// Create block pak commitment if set in conf file and validating pegouts
if (Params().GetEnforcePak() && g_paklist_config) {
if (*g_paklist_config != g_paklist_blockchain) {
g_paklist_config->CreateCommitments(commitments);
}
}

// Pad block weight to account for OP_RETURN commitments with two compressed pubkeys
for (const auto& commitment : commitments) {
CTxOut output(0, commitment);
nBlockWeight += ::GetSerializeSize(output, SER_NETWORK, PROTOCOL_VERSION)*WITNESS_SCALE_FACTOR;
}
// END PAK

// Add dummy coinbase tx as first transaction
pblock->vtx.emplace_back();
pblocktemplate->vTxFees.push_back(-1); // updated at end
Expand Down Expand Up @@ -172,6 +189,12 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
// ELEMENTS: PAK
// Add PAK transition commitments
for (unsigned int i = 0; i < commitments.size(); i++) {
coinbaseTx.vout.push_back(CTxOut(0, commitments[i]));
}
// END PAK
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
pblocktemplate->vTxFees[0] = -nFees;
Expand Down
22 changes: 19 additions & 3 deletions src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <tinyformat.h>
#include <util.h>
#include <utilstrencodings.h>
#include <chainparams.h> // Peg-out enforcement


CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
Expand Down Expand Up @@ -61,6 +62,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
if (!Solver(scriptPubKey, whichType, vSolutions))
return false;

CChainParams params = Params();
if (whichType == TX_MULTISIG)
{
unsigned char m = vSolutions.front()[0];
Expand All @@ -70,6 +72,10 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
return false;
if (m < 1 || m > n)
return false;
} else if (whichType == TX_NULL_DATA && params.GetEnforcePak() &&
scriptPubKey.IsPegoutScript(Params().ParentGenesisBlockHash()) ) {
// If we're enforcing pak let through larger peg-out scripts
return true;
} else if (whichType == TX_NULL_DATA &&
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
return false;
Expand Down Expand Up @@ -113,6 +119,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
}
}

CChainParams params = Params();
unsigned int nDataOut = 0;
txnouttype whichType;
for (const CTxOut& txout : tx.vout) {
Expand All @@ -121,9 +128,18 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
return false;
}

if (whichType == TX_NULL_DATA)
if (whichType == TX_NULL_DATA) {
}
if (whichType == TX_NULL_DATA) {
nDataOut++;
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
if (params.GetEnforcePak() &&
txout.scriptPubKey.IsPegoutScript(params.ParentGenesisBlockHash()) &&
(!ScriptHasValidPAKProof(txout.scriptPubKey, params.ParentGenesisBlockHash()))) {
// TODO(rebase) CT/CA check for asset type
reason = "invalid-pegout-proof";
return false;
}
} else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
} else if (IsDust(txout, ::dustRelayFee)) {
Expand All @@ -133,7 +149,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
}

// only one OP_RETURN txout is permitted
if (nDataOut > 1) {
if (!params.GetMultiDataPermitted() && nDataOut > 1) {
reason = "multi-op-return";
return false;
}
Expand Down
1 change: 1 addition & 0 deletions src/primitives/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <utilstrencodings.h>
#include <crypto/common.h>


bool g_con_blockheightinheader = false;
bool g_signed_blocks = false;

Expand Down
Loading