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

Validate BlockCommit while in BlockChain<T>.Append() #2561

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
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Version PBFT
- Added `BlockMarshaler.UnmarshalBlockHash()` method. [[#PBFT]]
- Added `BlockChain<T>.GetBlockCommit()` method. [[#PBFT]]
- Added `BlockChain<T>.CleanupBlockCommitStore()` method. [[#PBFT]]
- Added `InvalidBlockCommitException` class. [[#PBFT]]
- Added `BlockChain<T>.ValidateBlockCommit()` method [[#PBFT]]
colibrishin marked this conversation as resolved.
Show resolved Hide resolved
- (Libplanet.Net) Added `IReactor` interface. [[#PBFT]]
- (Libplanet.Net) Added `ConsensusReactor` class which inherits
`IReactor` interface. [[#PBFT]]
Expand Down Expand Up @@ -88,6 +90,12 @@ Version PBFT
- `PreEvaluationBlockHeader()` constructor became to throw
`InvalidBlockLastCommitException` when its metadata's `LastCommit` is
invalid. [[#PBFT]]
- `BlockChain<T>.Append()` has new parameter `BlockCommit blockCommit`, which
is a set of commits for given block. `BlockCommit` is used for checks
whether a block is committed in consensus. [[#PBFT]]
- `BlockChain<T>.Append()` method became to throw
`InvalidBlockCommitException` when the given `BlockCommit` is invalid with
given block. [[#PBFT]]

### Bug fixes

Expand Down
17 changes: 6 additions & 11 deletions Libplanet.Explorer.Tests/Queries/TransactionQueryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,9 @@ async Task AssertNextNonce(long expected, Address address) {

// staging txs of key2 does not increase nonce of key1
_source.BlockChain.MakeTransaction(key2, ImmutableList<NullAction>.Empty.Add(new NullAction()));
var lastCommit = new BlockCommit(
height: 1,
round: 0,
blockHash: block.Hash,
votes: ImmutableArray<Vote>.Empty
.Add(new VoteMetadata(1, 0, block.Hash, DateTimeOffset.UtcNow,
_source.Validator.PublicKey, VoteFlag.PreCommit).Sign(_source.Validator)));
block = _source.BlockChain.ProposeBlock(new PrivateKey(), lastCommit: lastCommit);
block = _source.BlockChain.ProposeBlock(
new PrivateKey(),
lastCommit: Libplanet.Tests.TestUtils.CreateBlockCommit(block));
_source.BlockChain.Append(block, Libplanet.Tests.TestUtils.CreateBlockCommit(block));
await AssertNextNonce(1, key2.ToAddress());
await AssertNextNonce(2, key1.ToAddress());
Expand All @@ -157,7 +152,7 @@ private class MockBlockChainContext<T> : IBlockChainContext<T>

public MockBlockChainContext()
{
Validator = new PrivateKey();
Validator = Libplanet.Tests.TestUtils.ValidatorPrivateKeys[1];
Store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
var minerKey = new PrivateKey();
Expand All @@ -175,8 +170,8 @@ public MockBlockChainContext()
_ => true,
stateStore);
BlockChain = new BlockChain<T>(
new BlockPolicy<T>(getValidatorSet: index => new ValidatorSet(
new List<PublicKey> { Validator.PublicKey })),
new BlockPolicy<T>(
getValidatorSet: index => Libplanet.Tests.TestUtils.ValidatorSet),
new VolatileStagePolicy<T>(),
Store,
stateStore,
Expand Down
2 changes: 1 addition & 1 deletion Libplanet.Net.Tests/SwarmTest.Preload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ public async Task GetDemandBlockHashes()
Assert.Equal(expectedBlocks, demands);
}

[Fact(Timeout = Timeout)]
[Fact(Timeout = Timeout, Skip = "No Reorganization in PBFT")]
public async Task PreloadAfterReorg()
{
var minerKey = new PrivateKey();
Expand Down
7 changes: 5 additions & 2 deletions Libplanet.Net.Tests/SwarmTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,9 @@ public async Task GetTx()
{
var keyB = new PrivateKey();

var policy = new BlockPolicy<DumbAction>(new MinerReward(1));
var policy = new BlockPolicy<DumbAction>(
new MinerReward(1),
getValidatorSet: idx => ValidatorSet);
Block<DumbAction> genesis = BlockChain<DumbAction>.ProposeGenesisBlock(
privateKey: new PrivateKey(), blockAction: policy.BlockAction);
Swarm<DumbAction> swarmA = CreateSwarm(genesis: genesis, policy: policy);
Expand Down Expand Up @@ -1222,7 +1224,8 @@ public async Task DoNotReceiveBlockFromNodeHavingDifferenceGenesisBlock()
BlockChain<DumbAction> MakeGenesisChain(
IStore store, IStateStore stateStore, Block<DumbAction> genesisBlock) =>
new BlockChain<DumbAction>(
new BlockPolicy<DumbAction>(),
new BlockPolicy<DumbAction>(
getValidatorSet: idx => ValidatorSet),
new VolatileStagePolicy<DumbAction>(),
store,
stateStore,
Expand Down
9 changes: 6 additions & 3 deletions Libplanet.Tests/Action/ActionEvaluatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ public void Evaluate()
var store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
var chain = TestUtils.MakeBlockChain<EvaluateTestAction>(
policy: new BlockPolicy<EvaluateTestAction>(),
policy: new BlockPolicy<EvaluateTestAction>(
getValidatorSet: idx => ValidatorSet),
store: store,
stateStore: stateStore);
var tx = Transaction<EvaluateTestAction>.Create(
Expand Down Expand Up @@ -164,7 +165,8 @@ public void EvaluateWithException()
var store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
var chain = TestUtils.MakeBlockChain<ThrowException>(
policy: new BlockPolicy<ThrowException>(),
policy: new BlockPolicy<ThrowException>(
getValidatorSet: idx => ValidatorSet),
store: store,
stateStore: stateStore);
var tx = Transaction<ThrowException>.Create(
Expand Down Expand Up @@ -1099,7 +1101,8 @@ public void OrderTxsForEvaluation(
private void CheckGenesisHashInAction()
{
var chain = MakeBlockChain<EvaluateTestAction>(
policy: new BlockPolicy<EvaluateTestAction>(),
policy: new BlockPolicy<EvaluateTestAction>(
getValidatorSet: idx => ValidatorSet),
store: _storeFx.Store,
stateStore: _storeFx.StateStore);
var privateKey = new PrivateKey();
Expand Down
3 changes: 2 additions & 1 deletion Libplanet.Tests/Blockchain/BlockChainTest.Append.cs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ public void AppendWithoutEvaluateActions()
[Fact]
public void AppendWhenActionEvaluationFailed()
{
var policy = new NullBlockPolicy<ThrowException>();
var policy = new NullBlockPolicy<ThrowException>(
getValidatorSet: idx => TestUtils.ValidatorSet);
var store = new MemoryStore();
var stateStore =
new TrieStateStore(new MemoryKeyValueStore());
Expand Down
4 changes: 3 additions & 1 deletion Libplanet.Tests/Blockchain/BlockChainTest.MineBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ TxPolicyViolationException IsSignerValid(
: new TxPolicyViolationException("invalid signer", tx.Id);
}

var policy = new BlockPolicy<DumbAction>(validateNextBlockTx: IsSignerValid);
var policy = new BlockPolicy<DumbAction>(
validateNextBlockTx: IsSignerValid,
getValidatorSet: idx => TestUtils.ValidatorSet);
using (var fx = new MemoryStoreFixture())
{
var blockChain = new BlockChain<DumbAction>(
Expand Down
119 changes: 117 additions & 2 deletions Libplanet.Tests/Blockchain/BlockChainTest.ValidateNextBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ public void ValidateNextBlockInvalidStateRootHash()
{
IKeyValueStore stateKeyValueStore = new MemoryKeyValueStore();
var policy = new BlockPolicy<DumbAction>(
blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000)
blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000),
getValidatorSet: idx => TestUtils.ValidatorSet
);
var stateStore = new TrieStateStore(stateKeyValueStore);
IStore store = new MemoryStore();
Expand Down Expand Up @@ -195,7 +196,8 @@ public void ValidateNextBlockInvalidStateRootHash()

var policyWithBlockAction = new BlockPolicy<DumbAction>(
new SetStatesAtBlock(default, (Text)"foo", 1),
policy.BlockInterval
policy.BlockInterval,
getValidatorSet: idx => TestUtils.ValidatorSet
);
var chain2 = new BlockChain<DumbAction>(
policyWithBlockAction,
Expand Down Expand Up @@ -319,5 +321,118 @@ public void ValidateNextBlockLastCommitFailsDropExpectedValidator()
Assert.Throws<InvalidBlockLastCommitException>(() =>
_blockChain.Append(block2, TestUtils.CreateBlockCommit(block2)));
}

[Fact]
public void ValidateBlockCommitGenesis()
{
InvalidBlockCommitException ibcm =
_blockChain.ValidateBlockCommit(_fx.GenesisBlock, null);

Assert.Null(ibcm);

ibcm = _blockChain.ValidateBlockCommit(
_fx.GenesisBlock,
new BlockCommit(
0,
0,
_fx.GenesisBlock.Hash,
TestUtils.ValidatorPrivateKeys.Select(x => new VoteMetadata(
0,
0,
_fx.GenesisBlock.Hash,
DateTimeOffset.UtcNow,
x.PublicKey,
VoteFlag.PreCommit).Sign(x)).ToImmutableArray()));

Assert.NotNull(ibcm);
}

[Fact]
public void ValidateBlockCommitFailsDifferentBlockHash()
{
Block<DumbAction> validNextBlock = new BlockContent<DumbAction>(
new BlockMetadata(
index: 1L,
timestamp: _fx.GenesisBlock.Timestamp.AddDays(1),
publicKey: _fx.Miner.PublicKey,
previousHash: _fx.GenesisBlock.Hash,
txHash: null,
lastCommit: null)).Propose().Evaluate(_fx.Miner, _blockChain);

Assert.Throws<InvalidBlockCommitException>(() =>
_blockChain.Append(
validNextBlock,
TestUtils.CreateBlockCommit(
new BlockHash(TestUtils.GetRandomBytes(BlockHash.Size)),
1,
0)));
}

[Fact]
public void ValidateBlockCommitFailsDifferentHeight()
{
Block<DumbAction> validNextBlock = new BlockContent<DumbAction>(
new BlockMetadata(
index: 1L,
timestamp: _fx.GenesisBlock.Timestamp.AddDays(1),
publicKey: _fx.Miner.PublicKey,
previousHash: _fx.GenesisBlock.Hash,
txHash: null,
lastCommit: null)).Propose().Evaluate(_fx.Miner, _blockChain);

Assert.Throws<InvalidBlockCommitException>(() =>
_blockChain.Append(
validNextBlock,
TestUtils.CreateBlockCommit(
validNextBlock.Hash,
2,
0)));
}

[Fact]
public void ValidateBlockCommitFailsDifferentValidatorSet()
{
Block<DumbAction> validNextBlock = new BlockContent<DumbAction>(
new BlockMetadata(
index: 1L,
timestamp: _fx.GenesisBlock.Timestamp.AddDays(1),
publicKey: _fx.Miner.PublicKey,
previousHash: _fx.GenesisBlock.Hash,
txHash: null,
lastCommit: null)).Propose().Evaluate(_fx.Miner, _blockChain);

Assert.Throws<InvalidBlockCommitException>(() =>
_blockChain.Append(
validNextBlock,
new BlockCommit(
1,
0,
validNextBlock.Hash,
Enumerable.Range(0, TestUtils.ValidatorSet.TotalCount)
.Select(x => new PrivateKey())
.Select(x => new VoteMetadata(
1,
0,
validNextBlock.Hash,
DateTimeOffset.UtcNow,
x.PublicKey,
VoteFlag.PreCommit).Sign(x)).ToImmutableArray())));
}

[Fact]
public void ValidateBlockCommitFailsNullBlockCommit()
{
Block<DumbAction> validNextBlock = new BlockContent<DumbAction>(
new BlockMetadata(
index: 1L,
timestamp: _fx.GenesisBlock.Timestamp.AddDays(1),
publicKey: _fx.Miner.PublicKey,
previousHash: _fx.GenesisBlock.Hash,
txHash: null,
lastCommit: null)).Propose().Evaluate(_fx.Miner, _blockChain);

Assert.Throws<InvalidBlockCommitException>(() =>
_blockChain.Append(validNextBlock, null));
}
}
}
15 changes: 10 additions & 5 deletions Libplanet.Tests/Blockchain/BlockChainTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ public void ShortCircuitActionEvaluationForUnrenderWithNoActionRenderers()
IEnumerable<ExecuteRecord> NonRehearsalExecutions() =>
DumbAction.ExecuteRecords.Value.Where(r => !r.Rehearsal);

var policy = new BlockPolicy<DumbAction>();
var policy = new BlockPolicy<DumbAction>(
getValidatorSet: idx => ValidatorSet);
var key = new PrivateKey();
Address miner = key.ToAddress();

Expand Down Expand Up @@ -363,7 +364,8 @@ IEnumerable<ExecuteRecord> NonRehearsalExecutions() =>
[Fact]
public void ActionRenderersHaveDistinctContexts()
{
var policy = new NullBlockPolicy<DumbAction>();
var policy = new NullBlockPolicy<DumbAction>(
getValidatorSet: idx => ValidatorSet);
var store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
var generatedRandomValueLogs = new List<int>();
Expand Down Expand Up @@ -401,7 +403,8 @@ public void ActionRenderersHaveDistinctContexts()
[Fact]
public void RenderActionsAfterBlockIsRendered()
{
var policy = new NullBlockPolicy<DumbAction>();
var policy = new NullBlockPolicy<DumbAction>(
getValidatorSet: idx => ValidatorSet);
var store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
var recordingRenderer = new RecordingActionRenderer<DumbAction>();
Expand Down Expand Up @@ -439,7 +442,8 @@ public void RenderActionsAfterBlockIsRendered()
[Fact]
public void RenderActionsAfterAppendComplete()
{
var policy = new NullBlockPolicy<DumbAction>();
var policy = new NullBlockPolicy<DumbAction>(
getValidatorSet: idx => ValidatorSet);
var store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
IActionRenderer<DumbAction> renderer = new AnonymousActionRenderer<DumbAction>
Expand Down Expand Up @@ -1332,7 +1336,8 @@ public void GetStateReturnsValidStateAfterFork()

var chain =
new BlockChain<DumbAction>(
new NullBlockPolicy<DumbAction>(),
new NullBlockPolicy<DumbAction>(
getValidatorSet: idx => ValidatorSet),
new VolatileStagePolicy<DumbAction>(),
store,
stateStore,
Expand Down
6 changes: 4 additions & 2 deletions Libplanet.Tests/Blocks/PreEvaluationBlockTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public void Evaluate()
var blockAction = new SetStatesAtBlock(address, (Bencodex.Types.Integer)123, 0);
var policy = new BlockPolicy<Arithmetic>(
blockAction: blockAction,
blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000));
blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000),
getValidatorSet: idx => ValidatorSet);
var stagePolicy = new VolatileStagePolicy<Arithmetic>();

PreEvaluationBlock<Arithmetic> preEvalGenesis =
Expand Down Expand Up @@ -91,7 +92,8 @@ public void DetermineStateRootHash()
var blockAction = new SetStatesAtBlock(address, (Bencodex.Types.Integer)123, 0);
var policy = new BlockPolicy<Arithmetic>(
blockAction: blockAction,
blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000));
blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000),
getValidatorSet: idx => ValidatorSet);
var stagePolicy = new VolatileStagePolicy<Arithmetic>();

PreEvaluationBlock<Arithmetic> preEvalGenesis =
Expand Down
Loading