Skip to content

Commit

Permalink
Implement Gnosis beacon chain push withdrawals (#5160)
Browse files Browse the repository at this point in the history
  • Loading branch information
rubo authored Apr 3, 2023
1 parent b458d99 commit af2279c
Show file tree
Hide file tree
Showing 38 changed files with 3,843 additions and 3,384 deletions.
3 changes: 2 additions & 1 deletion src/Nethermind/Chains/chiado.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"validators": {
"multi": {
"0": {
"list": ["0x14747a698Ec1227e6753026C08B29b4d5D3bC484"]
"list": [ "0x14747a698Ec1227e6753026C08B29b4d5D3bC484" ]
},
"67334": {
"list": [
Expand All @@ -30,6 +30,7 @@
"randomnessContractAddress": {
"0": "0x3000000000000000000000000000000000000001"
},
"withdrawalContractAddress": "0xb97036A26259B7147018913bD58a774cf91acf25",
"twoThirdsMajorityTransition": 0,
"posdaoTransition": 0,
"blockGasLimitContractTransitions": {
Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Chains/gnosis.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"randomnessContractAddress": {
"9186425": "0x5870b0527DeDB1cFBD9534343Feda1a41Ce47766"
},
"withdrawalContractAddress": "0x0B98057eA310F4d31F2a452B414647007d1645d9",
"posdaoTransition": 9186425,
"rewriteBytecode": {
"21735000": {
Expand Down
1,175 changes: 596 additions & 579 deletions src/Nethermind/Nethermind.Abi.Test/AbiTests.cs

Large diffs are not rendered by default.

74 changes: 42 additions & 32 deletions src/Nethermind/Nethermind.Abi/AbiArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,66 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Nethermind.Core.Extensions;
using Nethermind.Int256;

namespace Nethermind.Abi
namespace Nethermind.Abi;

public class AbiArray : AbiType
{
public class AbiArray : AbiType
public AbiType ElementType { get; }

public AbiArray(AbiType elementType)
{
public AbiType ElementType { get; }
ElementType = elementType;
Name = $"{ElementType}[]";
CSharpType = ElementType.CSharpType.MakeArrayType();
}

public AbiArray(AbiType elementType)
{
ElementType = elementType;
Name = $"{ElementType}[]";
CSharpType = ElementType.CSharpType.MakeArrayType();
}
public override bool IsDynamic => true;

public override bool IsDynamic => true;
public override string Name { get; }

public override string Name { get; }
public override Type CSharpType { get; }

public override Type CSharpType { get; }
public override (object, int) Decode(byte[] data, int position, bool packed)
{
UInt256 length;
(length, position) = UInt256.DecodeUInt(data, position, packed);
return DecodeSequence(ElementType.CSharpType, (int)length, ElementTypes, data, packed, position);
}

public override (object, int) Decode(byte[] data, int position, bool packed)
public override byte[] Encode(object? arg, bool packed)
{
int length;
byte[][] encodedItems;
switch (arg)
{
UInt256 length;
(length, position) = UInt256.DecodeUInt(data, position, packed);
return DecodeSequence(ElementType.CSharpType, (int)length, ElementTypes, data, packed, position);
case Array array:
length = array.Length;
encodedItems = EncodeSequence(length, ElementTypes, array.Cast<object?>(), packed, 1);
break;
case IList list:
length = list.Count;
encodedItems = EncodeSequence(length, ElementTypes, list.Cast<object?>(), packed, 1);
break;
default:
throw new AbiException(AbiEncodingExceptionMessage);
}

public override byte[] Encode(object? arg, bool packed)
{
if (arg is Array input)
{
byte[][] encodedItems = EncodeSequence(input.Length, ElementTypes, input.Cast<object?>(), packed, 1);
encodedItems[0] = UInt256.Encode((BigInteger)input.Length, packed);
return Bytes.Concat(encodedItems);
}

throw new AbiException(AbiEncodingExceptionMessage);
}
encodedItems[0] = UInt256.Encode((BigInteger)length, packed);
return Bytes.Concat(encodedItems);
}

private IEnumerable<AbiType> ElementTypes
private IEnumerable<AbiType> ElementTypes
{
get
{
get
{
yield return ElementType;
}
yield return ElementType;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,113 +9,112 @@
using Nethermind.Consensus;
using Nethermind.Consensus.AuRa;
using Nethermind.Consensus.AuRa.Contracts;
using Nethermind.Consensus.AuRa.Withdrawals;
using Nethermind.Consensus.Processing;
using Nethermind.Consensus.Rewards;
using Nethermind.Consensus.Validators;
using Nethermind.Consensus.Withdrawals;
using Nethermind.Core;
using Nethermind.Logging;
using Nethermind.Trie.Pruning;
using NUnit.Framework;

namespace Nethermind.AuRa.Test.Contract
namespace Nethermind.AuRa.Test.Contract;

public class AuRaContractGasLimitOverrideTests
{
public class AuRaContractGasLimitOverrideTests
private const int CorrectHeadGasLimit = 100000000;

// TestContract:
// pragma solidity ^0.5.0;
// contract TestValidatorSet {
// function blockGasLimit() public view returns(uint256) {
// return 100000000;
// }
// }
[Test]
public async Task can_read_block_gas_limit_from_contract()
{
private const int CorrectHeadGasLimit = 100000000;
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
long gasLimit = chain.GasLimitCalculator.GetGasLimit(chain.BlockTree.Head.Header);
gasLimit.Should().Be(CorrectHeadGasLimit);
}

// TestContract:
// pragma solidity ^0.5.0;
// contract TestValidatorSet {
// function blockGasLimit() public view returns(uint256) {
// return 100000000;
// }
// }
[Test]
public async Task can_read_block_gas_limit_from_contract()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
long gasLimit = chain.GasLimitCalculator.GetGasLimit(chain.BlockTree.Head.Header);
gasLimit.Should().Be(CorrectHeadGasLimit);
}
[Test]
public async Task caches_read_block_gas_limit()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
chain.GasLimitCalculator.GetGasLimit(chain.BlockTree.Head.Header);
long? gasLimit = chain.GasLimitOverrideCache.GasLimitCache.Get(chain.BlockTree.Head.Hash);
gasLimit.Should().Be(CorrectHeadGasLimit);
}

[Test]
public async Task caches_read_block_gas_limit()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
chain.GasLimitCalculator.GetGasLimit(chain.BlockTree.Head.Header);
long? gasLimit = chain.GasLimitOverrideCache.GasLimitCache.Get(chain.BlockTree.Head.Hash);
gasLimit.Should().Be(CorrectHeadGasLimit);
}
[Test]
public async Task can_validate_gas_limit_correct()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
bool isValid = ((AuRaContractGasLimitOverride)chain.GasLimitCalculator).IsGasLimitValid(chain.BlockTree.Head.Header, CorrectHeadGasLimit, out _);
isValid.Should().BeTrue();
}

[Test]
public async Task can_validate_gas_limit_correct()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
bool isValid = ((AuRaContractGasLimitOverride)chain.GasLimitCalculator).IsGasLimitValid(chain.BlockTree.Head.Header, CorrectHeadGasLimit, out _);
isValid.Should().BeTrue();
}
[Test]
public async Task can_validate_gas_limit_incorrect()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
bool isValid = ((AuRaContractGasLimitOverride)chain.GasLimitCalculator).IsGasLimitValid(chain.BlockTree.Head.Header, 100000001, out long? expectedGasLimit);
isValid.Should().BeFalse();
expectedGasLimit.Should().Be(CorrectHeadGasLimit);
}

[Test]
public async Task can_validate_gas_limit_incorrect()
{
using TestGasLimitContractBlockchain chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchain, AuRaContractGasLimitOverrideTests>();
bool isValid = ((AuRaContractGasLimitOverride)chain.GasLimitCalculator).IsGasLimitValid(chain.BlockTree.Head.Header, 100000001, out long? expectedGasLimit);
isValid.Should().BeFalse();
expectedGasLimit.Should().Be(CorrectHeadGasLimit);
}
[Test]
public async Task skip_validate_gas_limit_before_enabled()
{
using TestGasLimitContractBlockchainLateBlockGasLimit chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchainLateBlockGasLimit, AuRaContractGasLimitOverrideTests>();
bool isValid = ((AuRaContractGasLimitOverride)chain.GasLimitCalculator).IsGasLimitValid(chain.BlockTree.Genesis, 100000001, out _);
isValid.Should().BeTrue();
}

[Test]
public async Task skip_validate_gas_limit_before_enabled()
{
using TestGasLimitContractBlockchainLateBlockGasLimit chain = await TestContractBlockchain.ForTest<TestGasLimitContractBlockchainLateBlockGasLimit, AuRaContractGasLimitOverrideTests>();
bool isValid = ((AuRaContractGasLimitOverride)chain.GasLimitCalculator).IsGasLimitValid(chain.BlockTree.Genesis, 100000001, out _);
isValid.Should().BeTrue();
}
public class TestGasLimitContractBlockchain : TestContractBlockchain
{
public IGasLimitCalculator GasLimitCalculator { get; private set; }
public AuRaContractGasLimitOverride.Cache GasLimitOverrideCache { get; private set; }

public class TestGasLimitContractBlockchain : TestContractBlockchain
protected override BlockProcessor CreateBlockProcessor()
{
public IGasLimitCalculator GasLimitCalculator { get; private set; }
public AuRaContractGasLimitOverride.Cache GasLimitOverrideCache { get; private set; }

protected override BlockProcessor CreateBlockProcessor()
{
KeyValuePair<long, Address> blockGasLimitContractTransition = ChainSpec.AuRa.BlockGasLimitContractTransitions.First();
BlockGasLimitContract gasLimitContract = new(AbiEncoder.Instance, blockGasLimitContractTransition.Value, blockGasLimitContractTransition.Key,
new ReadOnlyTxProcessingEnv(
DbProvider,
new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(),
BlockTree, SpecProvider, LimboLogs.Instance));

GasLimitOverrideCache = new AuRaContractGasLimitOverride.Cache();
GasLimitCalculator = new AuRaContractGasLimitOverride(new[] { gasLimitContract }, GasLimitOverrideCache, false, new FollowOtherMiners(SpecProvider), LimboLogs.Instance);
KeyValuePair<long, Address> blockGasLimitContractTransition = ChainSpec.AuRa.BlockGasLimitContractTransitions.First();
BlockGasLimitContract gasLimitContract = new(AbiEncoder.Instance, blockGasLimitContractTransition.Value, blockGasLimitContractTransition.Key,
new ReadOnlyTxProcessingEnv(
DbProvider,
new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(),
BlockTree, SpecProvider, LimboLogs.Instance));

return new AuRaBlockProcessor(
SpecProvider,
Always.Valid,
new RewardCalculator(SpecProvider),
new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State),
State,
Storage,
ReceiptStorage,
LimboLogs.Instance,
BlockTree,
new WithdrawalProcessor(State, LogManager),
null,
GasLimitCalculator as AuRaContractGasLimitOverride);
}
GasLimitOverrideCache = new AuRaContractGasLimitOverride.Cache();
GasLimitCalculator = new AuRaContractGasLimitOverride(new[] { gasLimitContract }, GasLimitOverrideCache, false, new FollowOtherMiners(SpecProvider), LimboLogs.Instance);

protected override Task AddBlocksOnStart() => Task.CompletedTask;
return new AuRaBlockProcessor(
SpecProvider,
Always.Valid,
new RewardCalculator(SpecProvider),
new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State),
State,
Storage,
ReceiptStorage,
LimboLogs.Instance,
BlockTree,
NullWithdrawalProcessor.Instance,
null,
GasLimitCalculator as AuRaContractGasLimitOverride);
}

public class TestGasLimitContractBlockchainLateBlockGasLimit : TestGasLimitContractBlockchain
protected override Task AddBlocksOnStart() => Task.CompletedTask;
}

public class TestGasLimitContractBlockchainLateBlockGasLimit : TestGasLimitContractBlockchain
{
protected override BlockProcessor CreateBlockProcessor()
{
protected override BlockProcessor CreateBlockProcessor()
{
KeyValuePair<long, Address> blockGasLimitContractTransition = ChainSpec.AuRa.BlockGasLimitContractTransitions.First();
ChainSpec.AuRa.BlockGasLimitContractTransitions = new Dictionary<long, Address>() { { 10, blockGasLimitContractTransition.Value } };
return base.CreateBlockProcessor();
}
KeyValuePair<long, Address> blockGasLimitContractTransition = ChainSpec.AuRa.BlockGasLimitContractTransitions.First();
ChainSpec.AuRa.BlockGasLimitContractTransitions = new Dictionary<long, Address>() { { 10, blockGasLimitContractTransition.Value } };
return base.CreateBlockProcessor();
}
}
}
Loading

0 comments on commit af2279c

Please sign in to comment.