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

refactor: Add transaction context to contract handlers #1777

Merged
merged 2 commits into from
Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, bool* pfMissingInput
// Verify beacon contract in tx if found
for (const auto& contract : tx.GetContracts()) {
if (contract.m_type == NN::ContractType::BEACON
&& !NN::GetBeaconRegistry().Validate(contract))
&& !NN::GetBeaconRegistry().Validate(contract, tx))
{
return tx.DoS(25, error("%s: bad beacon contract in tx %s", __func__, tx.GetHash().ToString()));
}
Expand Down Expand Up @@ -2232,7 +2232,7 @@ bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)

if (pindex->nIsContract == 1)
{
NN::RevertContracts(vtx[i].GetContracts());
NN::RevertContracts(vtx[i]);
}
}

Expand Down Expand Up @@ -3618,7 +3618,7 @@ bool CBlock::AcceptBlock(bool generated_by_me)
if (nVersion >= 9) {
for (const auto& contract : tx.GetContracts()) {
if (contract.m_type == NN::ContractType::BEACON
&& !NN::GetBeaconRegistry().Validate(contract))
&& !NN::GetBeaconRegistry().Validate(contract, tx))
{
return tx.DoS(25, error("%s: bad beacon contract in tx %s", __func__, tx.GetHash().ToString()));
}
Expand Down
8 changes: 1 addition & 7 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,12 +640,6 @@ class CTransaction

if (nVersion >= 2) {
READWRITE(vContracts);

if (ser_action.ForRead()) {
for (auto& contract : REF(vContracts)) {
contract.m_tx_timestamp = nTime;
}
}
}
}

Expand Down Expand Up @@ -904,7 +898,7 @@ class CTransaction
const std::vector<NN::Contract>& GetContracts() const
{
if (nVersion == 1 && vContracts.empty() && NN::Contract::Detect(hashBoinc)) {
REF(vContracts).emplace_back(NN::Contract::Parse(hashBoinc, nTime));
REF(vContracts).emplace_back(NN::Contract::Parse(hashBoinc));
}

return vContracts;
Expand Down
15 changes: 8 additions & 7 deletions src/neuralnet/beacon.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "base58.h"
#include "logging.h"
#include "main.h"
#include "neuralnet/beacon.h"
#include "neuralnet/contract/contract.h"
#include "util.h"
Expand Down Expand Up @@ -318,11 +319,11 @@ bool BeaconRegistry::ContainsActive(const Cpid& cpid) const
return ContainsActive(cpid, GetAdjustedTime());
}

void BeaconRegistry::Add(Contract contract)
void BeaconRegistry::Add(Contract contract, const CTransaction& tx)
{
BeaconPayload payload = contract.CopyPayloadAs<BeaconPayload>();

payload.m_beacon.m_timestamp = contract.m_tx_timestamp;
payload.m_beacon.m_timestamp = tx.nTime;

// Legacy beacon contracts before block version 11--just load the beacon:
//
Expand All @@ -346,7 +347,7 @@ void BeaconRegistry::Add(Contract contract)
m_pending.emplace(pending.GetId(), std::move(pending));
}

void BeaconRegistry::Delete(const Contract& contract)
void BeaconRegistry::Delete(const Contract& contract, const CTransaction& tx)
{
const auto payload = contract.SharePayloadAs<BeaconPayload>();

Expand All @@ -357,7 +358,7 @@ void BeaconRegistry::Delete(const Contract& contract)
m_beacons.erase(payload->m_cpid);
}

bool BeaconRegistry::Validate(const Contract& contract) const
bool BeaconRegistry::Validate(const Contract& contract, const CTransaction& tx) const
{
// For legacy beacons, check that the unused parts contain non-empty values
// for compatibility with the existing protocol to prevent a fork.
Expand Down Expand Up @@ -405,7 +406,7 @@ bool BeaconRegistry::Validate(const Contract& contract) const

const BeaconOption current_beacon = Try(payload->m_cpid);

if (!current_beacon || current_beacon->Expired(contract.m_tx_timestamp)) {
if (!current_beacon || current_beacon->Expired(tx.nTime)) {
return true;
}

Expand All @@ -432,12 +433,12 @@ bool BeaconRegistry::Validate(const Contract& contract) const
return false;
}

if (!current_beacon->Renewable(contract.m_tx_timestamp)) {
if (!current_beacon->Renewable(tx.nTime)) {
LogPrint(LogFlags::CONTRACT,
"%s: Beacon for CPID %s is not renewable. Age: %" PRId64,
__func__,
payload->m_cpid.ToString(),
current_beacon->Age(contract.m_tx_timestamp));
current_beacon->Age(tx.nTime));

return false;
}
Expand Down
10 changes: 7 additions & 3 deletions src/neuralnet/beacon.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <vector>

class CBitcoinAddress;
class CTransaction;

namespace NN {

Expand Down Expand Up @@ -468,24 +469,27 @@ class BeaconRegistry : public IContractHandler
//! \brief Determine whether a beacon contract is valid.
//!
//! \param contract Contains the beacon data to validate.
//! \param tx Transaction that contains the contract.
//!
//! \return \c true if the contract contains a valid beacon.
//!
bool Validate(const Contract& contract) const;
bool Validate(const Contract& contract, const CTransaction& tx) const;

//!
//! \brief Register a beacon from contract data.
//!
//! \param contract Contains information about the beacon to add.
//! \param tx Transaction that contains the contract.
//!
void Add(Contract contract) override;
void Add(Contract contract, const CTransaction& tx) override;

//!
//! \brief Deregister the beacon specified by contract data.
//!
//! \param contract Contains information about the beacon to remove.
//! \param tx Transaction that contains the contract.
//!
void Delete(const Contract& contract) override;
void Delete(const Contract& contract, const CTransaction& tx) override;

//!
//! \brief Activate the set of pending beacons verified in a superblock.
Expand Down
61 changes: 28 additions & 33 deletions src/neuralnet/contract/contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class LegacyPayload : public IContractPayload
//!
class AppCacheContractHandler : public IContractHandler
{
void Add(Contract contract) override
void Add(Contract contract, const CTransaction& tx) override
{
auto payload = contract.CopyPayloadAs<LegacyPayload>();

Expand All @@ -159,10 +159,10 @@ class AppCacheContractHandler : public IContractHandler
StringToSection(contract.m_type.ToString()),
std::move(payload.m_key),
std::move(payload.m_value),
contract.m_tx_timestamp);
tx.nTime);
}

void Delete(const Contract& contract) override
void Delete(const Contract& contract, const CTransaction& tx) override
{
const auto payload = contract.SharePayloadAs<LegacyPayload>();

Expand All @@ -180,7 +180,7 @@ class UnknownContractHandler : public IContractHandler
//!
//! \param contract A contract message with an unknown type.
//!
void Add(Contract contract) override
void Add(Contract contract, const CTransaction& tx) override
{
contract.Log("WARNING: Add unknown contract type ignored");
}
Expand All @@ -190,7 +190,7 @@ class UnknownContractHandler : public IContractHandler
//!
//! \param contract A contract message with an unknown type.
//!
void Delete(const Contract& contract) override
void Delete(const Contract& contract, const CTransaction& tx) override
{
contract.Log("WARNING: Delete unknown contract type ignored");
}
Expand All @@ -200,7 +200,7 @@ class UnknownContractHandler : public IContractHandler
//!
//! \param contract A contract message with an unknown type.
//!
void Revert(const Contract& contract) override
void Revert(const Contract& contract, const CTransaction& tx) override
{
contract.Log("WARNING: Revert unknown contract type ignored");
}
Expand All @@ -218,8 +218,9 @@ class Dispatcher
//! contract handler.
//!
//! \param contract As received from a transaction message.
//! \param tx Transaction that contains the contract.
//!
void Apply(const Contract& contract)
void Apply(const Contract& contract, const CTransaction& tx)
{
// TODO: We need to restructure ReorganizeChain() and ConnectBlock()
// to put back the ability to std::move() contracts from new blocks.
Expand All @@ -229,13 +230,13 @@ class Dispatcher
//
if (contract.m_action == ContractAction::ADD) {
contract.Log("INFO: Add contract");
GetHandler(contract.m_type.Value()).Add(std::move(contract));
GetHandler(contract.m_type.Value()).Add(std::move(contract), tx);
return;
}

if (contract.m_action == ContractAction::REMOVE) {
contract.Log("INFO: Delete contract");
GetHandler(contract.m_type.Value()).Delete(contract);
GetHandler(contract.m_type.Value()).Delete(contract, tx);
return;
}

Expand All @@ -248,15 +249,16 @@ class Dispatcher
//!
//! \param contract Typically parsed from a message in a transaction from
//! a disconnected block.
//! \param tx Transaction that contains the contract.
//!
void Revert(const Contract& contract)
void Revert(const Contract& contract, const CTransaction& tx)
{
contract.Log("INFO: Revert contract");

// The default implementation of IContractHandler reverses an action
// (addition or deletion) declared in the contract argument, but the
// type-specific handlers may override this behavior as needed:
GetHandler(contract.m_type.Value()).Revert(contract);
GetHandler(contract.m_type.Value()).Revert(contract, tx);
}

private:
Expand Down Expand Up @@ -365,14 +367,14 @@ void NN::ApplyContracts(const CBlock& block, bool& found_contract)
{
if (!iter->GetContracts().empty()) {
found_contract = true;
ApplyContracts(iter->GetContracts());
ApplyContracts(*iter);
}
}
}

void NN::ApplyContracts(const std::vector<Contract>& contracts)
void NN::ApplyContracts(const CTransaction& tx)
{
for (const auto& contract : contracts) {
for (const auto& contract : tx.GetContracts()) {
// V2 contract signatures are checked upon receipt:
if (contract.m_version == 1 && !contract.Validate()) {
continue;
Expand All @@ -394,20 +396,20 @@ void NN::ApplyContracts(const std::vector<Contract>& contracts)
}
}

g_dispatcher.Apply(contract);
g_dispatcher.Apply(contract, tx);
}
}

void NN::RevertContracts(const std::vector<Contract>& contracts)
void NN::RevertContracts(const CTransaction& tx)
{
// Reverse the contracts. Reorganize will load any previous versions:
for (const auto& contract : contracts) {
for (const auto& contract : tx.GetContracts()) {
// V2 contract signatures are checked upon receipt:
if (contract.m_version == 1 && !contract.VerifySignature()) {
continue;
}

g_dispatcher.Revert(contract);
g_dispatcher.Revert(contract, tx);
}
}

Expand All @@ -424,7 +426,6 @@ Contract::Contract()
, m_body()
, m_signature()
, m_public_key()
, m_tx_timestamp(0)
{
}

Expand All @@ -438,7 +439,6 @@ Contract::Contract(
, m_body(std::move(body))
, m_signature()
, m_public_key()
, m_tx_timestamp(0)
{
}

Expand All @@ -448,15 +448,13 @@ Contract::Contract(
Contract::Action action,
Contract::Body body,
Contract::Signature signature,
Contract::PublicKey public_key,
int64_t tx_timestamp)
Contract::PublicKey public_key)
: m_version(version)
, m_type(type)
, m_action(action)
, m_body(std::move(body))
, m_signature(std::move(signature))
, m_public_key(std::move(public_key))
, m_tx_timestamp(tx_timestamp)
{
}

Expand Down Expand Up @@ -533,7 +531,7 @@ bool Contract::Detect(const std::string& message)
&& !Contains(message, "<MT>superblock</MT>");
}

Contract Contract::Parse(const std::string& message, const int64_t timestamp)
Contract Contract::Parse(const std::string& message)
{
if (message.empty()) {
return Contract();
Expand All @@ -551,8 +549,7 @@ Contract Contract::Parse(const std::string& message, const int64_t timestamp)
// user-supplied private key, so we can skip parsing the public keys
// altogether. We verify contracts with the master and message keys:
//Contract::PublicKey::Parse(ExtractXML(message, "<MPK>", "</MPK>")),
Contract::PublicKey(),
timestamp);
Contract::PublicKey());
}

bool Contract::RequiresMasterKey() const
Expand Down Expand Up @@ -709,10 +706,9 @@ void Contract::Log(const std::string& prefix) const
{
// TODO: temporary... needs better logging
LogPrint(BCLog::LogFlags::CONTRACT,
"<Contract::Log>: %s: v%d, %d, %s, %s, %s, %s, %s, %s",
"<Contract::Log>: %s: v%d, %s, %s, %s, %s, %s, %s",
prefix,
m_version,
m_tx_timestamp,
m_type.ToString(),
m_action.ToString(),
m_body.m_payload->LegacyKeyString(),
Expand Down Expand Up @@ -923,8 +919,7 @@ Contract Contract::ToLegacy() const
m_body.m_payload->LegacyKeyString(),
m_body.m_payload->LegacyValueString()),
m_signature,
m_public_key,
m_tx_timestamp);
m_public_key);
}

std::string Contract::Signature::ToString() const
Expand Down Expand Up @@ -987,15 +982,15 @@ std::string Contract::PublicKey::ToString() const
// Abstract Class: IContractHandler
// -----------------------------------------------------------------------------

void IContractHandler::Revert(const Contract& contract)
void IContractHandler::Revert(const Contract& contract, const CTransaction& tx)
{
if (contract.m_action == ContractAction::ADD) {
Delete(contract);
Delete(contract, tx);
return;
}

if (contract.m_action == ContractAction::REMOVE) {
Add(contract);
Add(contract, tx);
return;
}

Expand Down
Loading