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

EIP-4844 V6 fixes and improvements #5745

Merged
merged 8 commits into from
Jun 12, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -277,25 +277,49 @@ public void Transaction_with_init_code_above_max_value_is_rejected_when_eip3860E
txValidator.IsWellFormed(tx, releaseSpec).Should().Be(expectedResult);
}

[Test]
public void ShardBlobTransactions_should_have_destination_set()
{
TxValidator txValidator = new(TestBlockchainIds.ChainId);

Transaction txWithoutTo = Build.A.Transaction
.WithType(TxType.Blob)
.WithTimestamp(ulong.MaxValue)
.WithTo(null)
.WithMaxFeePerGas(1)
.WithMaxFeePerDataGas(1)
.WithBlobVersionedHashes(1)
.WithChainId(TestBlockchainIds.ChainId)
.SignedAndResolved().TestObject;

Transaction txtxWithTo = Build.A.Transaction
flcl42 marked this conversation as resolved.
Show resolved Hide resolved
.WithType(TxType.Blob)
.WithTimestamp(ulong.MaxValue)
.WithTo(TestItem.AddressA)
.WithMaxFeePerGas(1)
.WithMaxFeePerDataGas(1)
.WithBlobVersionedHashes(1)
.WithChainId(TestBlockchainIds.ChainId)
.SignedAndResolved().TestObject;

Assert.That(txValidator.IsWellFormed(txWithoutTo, Cancun.Instance), Is.False);
Assert.That(txValidator.IsWellFormed(txtxWithTo, Cancun.Instance));
flcl42 marked this conversation as resolved.
Show resolved Hide resolved
}

[Timeout(Timeout.MaxTestTime)]
[TestCase(TxType.EIP1559, false, ExpectedResult = true)]
[TestCase(TxType.EIP1559, true, ExpectedResult = false)]
[TestCase(TxType.Blob, true, ExpectedResult = true)]
public bool MaxFeePerDataGas_should_be_set_for_blob_tx_only(TxType txType, bool isMaxFeePerDataGasSet)
{
byte[] sigData = new byte[65];
sigData[31] = 1; // correct r
sigData[63] = 1; // correct s
sigData[64] = 27; // correct v
Signature signature = new(sigData);
TransactionBuilder<Transaction> txBuilder = Build.A.Transaction
.WithType(txType)
.WithTimestamp(ulong.MaxValue)
.WithMaxFeePerGas(1)
.WithMaxFeePerDataGas(isMaxFeePerDataGasSet ? 1 : null)
.WithBlobVersionedHashes(txType == TxType.Blob ? Eip4844Constants.MinBlobsPerTransaction : null)
.WithChainId(TestBlockchainIds.ChainId)
.WithSignature(signature);
.SignedAndResolved();

Transaction tx = txBuilder.TestObject;

Expand All @@ -308,19 +332,14 @@ public bool MaxFeePerDataGas_should_be_set_for_blob_tx_only(TxType txType, bool
[TestCaseSource(nameof(BlobVersionedHashValidTestCases))]
public bool BlobVersionedHash_should_be_correct(byte[] hash)
{
byte[] sigData = new byte[65];
sigData[31] = 1; // correct r
sigData[63] = 1; // correct s
sigData[64] = 27; // correct v
Signature signature = new(sigData);
Transaction tx = Build.A.Transaction
.WithType(TxType.Blob)
.WithTimestamp(ulong.MaxValue)
.WithMaxFeePerGas(1)
.WithMaxFeePerDataGas(1)
.WithBlobVersionedHashes(new[] { hash })
.WithChainId(TestBlockchainIds.ChainId)
.WithSignature(signature).TestObject;
.SignedAndResolved().TestObject;

TxValidator txValidator = new(TestBlockchainIds.ChainId);
return txValidator.IsWellFormed(tx, Cancun.Instance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ transaction.BlobVersionedHashes is null &&
transaction is not { NetworkWrapper: ShardBlobNetworkWrapper };
}

if (transaction.MaxFeePerDataGas is null ||
if (transaction.To is null ||
transaction.MaxFeePerDataGas is null ||
transaction.BlobVersionedHashes is null ||
transaction.BlobVersionedHashes!.Length > Eip4844Constants.MaxBlobsPerTransaction ||
transaction.BlobVersionedHashes!.Length < Eip4844Constants.MinBlobsPerTransaction)
Expand Down
6 changes: 6 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/BytesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -359,5 +359,11 @@ public void Or(byte[] first, byte[] second, byte[] expected)
first.AsSpan().Or(second);
first.Should().Equal(expected);
}

[Test]
public void NullableComparision()
{
Bytes.NullableEqualityComparer.Equals(null, null).Should().BeTrue();
}
}
}

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions src/Nethermind/Nethermind.Core/Extensions/Bytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace Nethermind.Core.Extensions
public static unsafe partial class Bytes
{
public static readonly IEqualityComparer<byte[]> EqualityComparer = new BytesEqualityComparer();
public static readonly IEqualityComparer<byte[]?> NullableEqualityComparer = new NullableBytesEqualityComparer();
public static readonly ISpanEqualityComparer<byte> SpanEqualityComparer = new SpanBytesEqualityComparer();
public static readonly BytesComparer Comparer = new();

Expand All @@ -40,6 +41,19 @@ public override int GetHashCode(byte[] obj)
}
}

private class NullableBytesEqualityComparer : EqualityComparer<byte[]?>
{
public override bool Equals(byte[]? x, byte[]? y)
{
return AreEqual(x, y);
}

public override int GetHashCode(byte[]? obj)
{
return obj?.GetSimplifiedHashCode() ?? 0;
}
}

private class SpanBytesEqualityComparer : ISpanEqualityComparer<byte>
{
public bool Equals(ReadOnlySpan<byte> x, ReadOnlySpan<byte> y) => AreEqual(x, y);
Expand Down
14 changes: 7 additions & 7 deletions src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@ public class Eip4844Tests : VirtualMachineTestsBase
[TestCase(2, 1, Description = "Should return 0 when way out of range")]
[TestCase(0, 1, Description = "Should return hash, when exists")]
[TestCase(1, 3, Description = "Should return hash, when exists")]
public void Test_datahash_index_in_range(int index, int datahashesCount)
public void Test_blobhash_index_in_range(int index, int blobhashesCount)
{
byte[][] hashes = new byte[datahashesCount][];
for (int i = 0; i < datahashesCount; i++)
byte[][] hashes = new byte[blobhashesCount][];
for (int i = 0; i < blobhashesCount; i++)
{
hashes[i] = new byte[32];
for (int n = 0; n < datahashesCount; n++)
for (int n = 0; n < blobhashesCount; n++)
{
hashes[i][n] = (byte)((i * 3 + 10 * 7) % 256);
}
}
byte[] expectedOutput = datahashesCount > index ? hashes[index] : new byte[32];
byte[] expectedOutput = blobhashesCount > index ? hashes[index] : new byte[32];

// Cost of transaction call + PUSH1 x4 + MSTORE (entry cost + 1 memory cell used)
const long GasCostOfCallingWrapper = GasCostOf.Transaction + GasCostOf.VeryLow * 5 + GasCostOf.Memory;

byte[] code = Prepare.EvmCode
.PushData(new UInt256((ulong)index))
.DATAHASH()
.BLOBHASH()
.MSTORE(0)
.Return(32, 0)
.Done;
Expand All @@ -48,7 +48,7 @@ public void Test_datahash_index_in_range(int index, int datahashesCount)

result.StatusCode.Should().Be(StatusCode.Success);
result.ReturnValue.SequenceEqual(expectedOutput);
AssertGas(result, GasCostOfCallingWrapper + GasCostOf.DataHash);
AssertGas(result, GasCostOfCallingWrapper + GasCostOf.BlobHash);
}

protected override TestAllTracerWithOutput CreateTracer()
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public class InvalidOpcodeTests : VirtualMachineTestsBase
{
Instruction.TSTORE,
Instruction.TLOAD,
Instruction.DATAHASH,
Instruction.BLOBHASH,
}
).ToArray();

Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Evm/ByteCodeBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ public static Prepare SELFBALANCE(this Prepare @this)
=> @this.Op(Instruction.SELFBALANCE);
public static Prepare BASEFEE(this Prepare @this)
=> @this.Op(Instruction.BASEFEE);
public static Prepare DATAHASH(this Prepare @this)
=> @this.Op(Instruction.DATAHASH);
public static Prepare BLOBHASH(this Prepare @this)
=> @this.Op(Instruction.BLOBHASH);
public static Prepare POP(this Prepare @this)
=> @this.Op(Instruction.POP);
public static Prepare PC(this Prepare @this)
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Evm/GasCostOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static class GasCostOf
public const long TxDataNonZero = 68;
public const long TxDataNonZeroEip2028 = 16;
public const long Transaction = 21000;
public const long DataHash = 3;
public const long BlobHash = 3;
public const long Log = 375;
public const long LogTopic = 375;
public const long LogData = 8;
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Evm/Instruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public enum Instruction : byte
CHAINID = 0x46,
SELFBALANCE = 0x47,
BASEFEE = 0x48,
DATAHASH = 0x49,
BLOBHASH = 0x49,

POP = 0x50,
MLOAD = 0x51,
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Evm/VirtualMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1485,11 +1485,11 @@ static void UpdateCurrentState(EvmState state, int pc, long gas, int stackHead)
stack.PushUInt256(in baseFee);
break;
}
case Instruction.DATAHASH:
case Instruction.BLOBHASH:
{
if (!spec.IsEip4844Enabled) goto InvalidInstruction;

if (!UpdateGas(GasCostOf.DataHash, ref gasAvailable)) goto OutOfGas;
if (!UpdateGas(GasCostOf.BlobHash, ref gasAvailable)) goto OutOfGas;

stack.PopUInt256(out UInt256 blobIndex);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private ExecutionPayload CreateParentBlockRequestOnHead(IBlockTree blockTree)
};
}

private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList<Withdrawal>? withdrawals = null, UInt256? excessDataGas = null)
private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList<Withdrawal>? withdrawals = null, UInt256? excessDataGas = null, Transaction[]? transactions = null)
{
ExecutionPayload blockRequest = new()
{
Expand All @@ -101,7 +101,7 @@ private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Addr
ExcessDataGas = excessDataGas,
};

blockRequest.SetTransactions(Array.Empty<Transaction>());
blockRequest.SetTransactions(transactions ?? Array.Empty<Transaction>());
TryCalculateHash(blockRequest, out Keccak? hash);
blockRequest.BlockHash = hash;
return blockRequest;
Expand Down
Loading