Skip to content

Commit

Permalink
Fix IsServiceTransaction by allowing all 0 gas price transactions to …
Browse files Browse the repository at this point in the history
…be service transactions when processing and validator transactions to be service transactions when producing block (#3572)
  • Loading branch information
LukaszRozmej authored Nov 2, 2021
1 parent aaef50f commit affbf1e
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ protected override BlockProcessor CreateBlockProcessor()
ITxFilter auRaTxFilter = TxAuRaFilterBuilders.CreateAuRaTxFilter(
_api,
txPermissionFilterOnlyTxProcessorSource,
_api.SpecProvider);
_api.SpecProvider,
new ServiceTxFilter(_api.SpecProvider));

var processor = new AuRaBlockProcessor(
_api.SpecProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ private BlockProcessor CreateBlockProcessor(ReadOnlyTxProcessingEnv changeableTx
ITxFilter auRaTxFilter = TxAuRaFilterBuilders.CreateAuRaTxFilter(
_api,
constantContractTxProcessingEnv,
_api.SpecProvider);
_api.SpecProvider,
new LocalTxFilter(_api.EngineSigner));

_validator = new AuRaValidatorFactory(_api.AbiEncoder,
changeableTxProcessingEnv.StateProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,18 @@ private static ITxFilter CreateBaseAuRaTxFilter(
private static ITxFilter CreateBaseAuRaTxFilter(
AuRaNethermindApi api,
IReadOnlyTxProcessorSource readOnlyTxProcessorSource,
ISpecProvider specProvider)
ISpecProvider specProvider,
ITxFilter baseTxFilter)
{
Address? registrar = api.ChainSpec?.Parameters.Registrar;
if (registrar != null)
{
RegisterContract registerContract = new(api.AbiEncoder, registrar, readOnlyTxProcessorSource);
CertifierContract certifierContract = new(api.AbiEncoder, registerContract, readOnlyTxProcessorSource);
return new TxCertifierFilter(certifierContract, NullTxFilter.Instance, specProvider, api.LogManager);
return new TxCertifierFilter(certifierContract, baseTxFilter, specProvider, api.LogManager);
}

return NullTxFilter.Instance;
return baseTxFilter;
}


Expand Down Expand Up @@ -114,9 +115,10 @@ public static ITxFilter CreateAuRaTxFilterForProducer(
public static ITxFilter CreateAuRaTxFilter(
AuRaNethermindApi api,
IReadOnlyTxProcessorSource readOnlyTxProcessorSource,
ISpecProvider specProvider)
ISpecProvider specProvider,
ITxFilter baseTxFilter)
{
ITxFilter baseAuRaTxFilter = CreateBaseAuRaTxFilter(api, readOnlyTxProcessorSource, specProvider);
ITxFilter baseAuRaTxFilter = CreateBaseAuRaTxFilter(api, readOnlyTxProcessorSource, specProvider, baseTxFilter);
ITxFilter? txPermissionFilter = CreateTxPermissionFilter(api, readOnlyTxProcessorSource);
return txPermissionFilter != null
? new CompositeTxFilter(baseAuRaTxFilter, txPermissionFilter)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System;
using Nethermind.Consensus.Transactions;
using Nethermind.Core;

namespace Nethermind.Consensus.AuRa.Transactions
{
public class LocalTxFilter : ITxFilter
{
private readonly ISigner _signer;

public LocalTxFilter(ISigner signer)
{
_signer = signer;
}

public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader)
{
if (tx.SenderAddress == _signer.Address)
{
tx.IsServiceTransaction = true;
}

return (true, string.Empty);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System;
using Nethermind.Consensus.Transactions;
using Nethermind.Core;
using Nethermind.Core.Specs;

namespace Nethermind.Consensus.AuRa.Transactions
{
public class ServiceTxFilter : ITxFilter
{
private readonly ISpecProvider _specProvider;

public ServiceTxFilter(ISpecProvider specProvider)
{
_specProvider = specProvider;
}

public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader)
{
if (tx.IsZeroGasPrice(parentHeader, _specProvider))
{
tx.IsServiceTransaction = true;
}

return (true, string.Empty);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using Nethermind.Core;
using Nethermind.Core.Specs;

namespace Nethermind.Consensus.AuRa.Transactions
{
public static class TransactionExtensions
{
public static bool IsZeroGasPrice(this Transaction tx, BlockHeader parentHeader, ISpecProvider specProvider)
{
bool isEip1559Enabled = specProvider.GetSpec(parentHeader.Number + 1).IsEip1559Enabled;
bool checkByFeeCap = isEip1559Enabled && tx.IsEip1559;
if (checkByFeeCap && !tx.MaxFeePerGas.IsZero) // only 0 gas price transactions are system transactions and can be whitelisted
{
return false;
}
else if (!tx.GasPrice.IsZero && !checkByFeeCap)
{
return false;
}

return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,38 +52,32 @@ public TxCertifierFilter(ICertifierContract certifierContract, ITxFilter notCert

private bool IsCertified(Transaction tx, BlockHeader parentHeader)
{
bool isEip1559Enabled = _specProvider.GetSpec(parentHeader.Number + 1).IsEip1559Enabled;
bool checkByFeeCap = isEip1559Enabled && tx.IsEip1559;
if (checkByFeeCap && !tx.MaxFeePerGas.IsZero) // only 0 gas price transactions are system transactions and can be whitelissted
if (tx.IsZeroGasPrice(parentHeader, _specProvider))
{
return false;
}
else if (!tx.GasPrice.IsZero && !checkByFeeCap)
{
return false;
}

Address sender = tx.SenderAddress;
if (_logger.IsTrace) _logger.Trace($"Checking service transaction checker contract from {sender}.");
IDictionary<Address, bool> cache = GetCache(parentHeader.Hash);

if (cache.TryGetValue(sender, out bool isCertified))
{
tx.IsServiceTransaction = isCertified;
return isCertified;
}
Address sender = tx.SenderAddress;
if (_logger.IsTrace) _logger.Trace($"Checking service transaction checker contract from {sender}.");
IDictionary<Address, bool> cache = GetCache(parentHeader.Hash);

try
{
bool isCertifiedByContract = _certifierContract.Certified(parentHeader, sender);
tx.IsServiceTransaction = isCertifiedByContract;
return cache[sender] = isCertifiedByContract;
}
catch (AbiException e)
{
if (_logger.IsError) _logger.Error($"Call to certifier contract failed on block {parentHeader.ToString(BlockHeader.Format.FullHashAndNumber)}.", e);
return false;
if (cache.TryGetValue(sender, out bool isCertified))
{
tx.IsServiceTransaction = isCertified;
return isCertified;
}

try
{
bool isCertifiedByContract = _certifierContract.Certified(parentHeader, sender);
tx.IsServiceTransaction = isCertifiedByContract;
return cache[sender] = isCertifiedByContract;
}
catch (AbiException e)
{
if (_logger.IsError) _logger.Error($"Call to certifier contract failed on block {parentHeader.ToString(BlockHeader.Format.FullHashAndNumber)}.", e);
return false;
}
}

return false;
}

private IDictionary<Address, bool> GetCache(Keccak blockHash)
Expand Down

0 comments on commit affbf1e

Please sign in to comment.