ProposerSelection to support multiple IBFT implementations (#307)

The ProposerSelection logic has been reworked such that it now accepts
a BlockInterface, through which IBFT parameters can be accessed
directly from the block header, without requiring literal hashing etc.

This has required the VoteBlockInterface to be renamed to
BlockInterface.
tmohay 6 years ago committed by GitHub
parent 7845494187
commit 085321b557
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueBlockInterface.java
  2. 4
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreator.java
  3. 4
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/headervalidationrules/CoinbaseHeaderValidationRule.java
  4. 4
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/headervalidationrules/VoteValidationRule.java
  5. 4
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/jsonrpc/CliqueJsonRpcMethodsFactory.java
  6. 10
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueBlockInterfaceTest.java
  7. 7
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  8. 6
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/headervalidationrules/VoteValidationRuleTest.java
  9. 4
      consensus/common/src/main/java/tech/pegasys/pantheon/consensus/common/BlockInterface.java
  10. 5
      consensus/common/src/main/java/tech/pegasys/pantheon/consensus/common/VoteTallyUpdater.java
  11. 2
      consensus/common/src/test/java/tech/pegasys/pantheon/consensus/common/VoteTallyUpdaterTest.java
  12. 11
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockInterface.java
  13. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java
  14. 12
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelector.java
  15. 112
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelectorTest.java
  16. 13
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftLegacyBlockInterface.java
  17. 2
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java
  18. 4
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/VoteValidationRule.java
  19. 2
      consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java
  20. 11
      consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftLegacyBlockInterfaceTest.java
  21. 4
      pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java
  22. 4
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java

@ -12,8 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.clique;
import tech.pegasys.pantheon.consensus.common.BlockInterface;
import tech.pegasys.pantheon.consensus.common.ValidatorVote;
import tech.pegasys.pantheon.consensus.common.VoteBlockInterface;
import tech.pegasys.pantheon.consensus.common.VoteType;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -25,7 +25,7 @@ import java.util.Optional;
import com.google.common.collect.ImmutableBiMap;
public class CliqueVotingBlockInterface implements VoteBlockInterface {
public class CliqueBlockInterface implements BlockInterface {
public static final Address NO_VOTE_SUBJECT =
Address.wrap(BytesValue.wrap(new byte[Address.SIZE]));
@ -38,12 +38,17 @@ public class CliqueVotingBlockInterface implements VoteBlockInterface {
VoteType.ADD, ADD_NONCE,
VoteType.DROP, DROP_NONCE);
@Override
public Address getProposerOfBlock(final BlockHeader header) {
final CliqueExtraData cliqueExtraData = CliqueExtraData.decode(header.getExtraData());
return CliqueBlockHashing.recoverProposerAddress(header, cliqueExtraData);
}
@Override
public Optional<ValidatorVote> extractVoteFromHeader(final BlockHeader header) {
final Address candidate = header.getCoinbase();
if (!candidate.equals(NO_VOTE_SUBJECT)) {
final CliqueExtraData cliqueExtraData = CliqueExtraData.decode(header.getExtraData());
final Address proposer = CliqueBlockHashing.recoverProposerAddress(header, cliqueExtraData);
final Address proposer = getProposerOfBlock(header);
final VoteType votePolarity = voteToValue.inverse().get(header.getNonce());
final Address recipient = header.getCoinbase();

@ -13,9 +13,9 @@
package tech.pegasys.pantheon.consensus.clique.blockcreation;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockHashing;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueExtraData;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.common.ValidatorVote;
import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.crypto.SECP256K1;
@ -92,7 +92,7 @@ public class CliqueBlockCreator extends AbstractBlockCreator<CliqueContext> {
.getVoteProposer()
.getVote(Util.publicKeyToAddress(nodeKeys.getPublicKey()), voteTally);
final BlockHeaderBuilder builderIncludingProposedVotes =
CliqueVotingBlockInterface.insertVoteToHeaderBuilder(builder, vote);
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, vote);
final CliqueExtraData sealedExtraData =
constructSignedExtraData(builderIncludingProposedVotes.buildBlockHeader());

@ -12,7 +12,7 @@
*/
package tech.pegasys.pantheon.consensus.clique.headervalidationrules;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.consensus.common.EpochManager;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.DetachedBlockHeaderValidationRule;
@ -30,7 +30,7 @@ public class CoinbaseHeaderValidationRule implements DetachedBlockHeaderValidati
// are allowed to be cast on epoch blocks
public boolean validate(final BlockHeader header, final BlockHeader parent) {
if (epochManager.isEpochBlock(header.getNumber())) {
return header.getCoinbase().equals(CliqueVotingBlockInterface.NO_VOTE_SUBJECT);
return header.getCoinbase().equals(CliqueBlockInterface.NO_VOTE_SUBJECT);
}
return true;
}

@ -12,7 +12,7 @@
*/
package tech.pegasys.pantheon.consensus.clique.headervalidationrules;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.DetachedBlockHeaderValidationRule;
@ -33,7 +33,7 @@ public class VoteValidationRule implements DetachedBlockHeaderValidationRule {
@Override
public boolean validate(final BlockHeader header, final BlockHeader parent) {
final long nonce = header.getNonce();
if (!CliqueVotingBlockInterface.isValidVoteValue(nonce)) {
if (!CliqueBlockInterface.isValidVoteValue(nonce)) {
LOG.trace("Nonce value ({}) is neither auth or drop.", nonce);
return false;
}

@ -12,8 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.clique.jsonrpc;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.clique.VoteTallyCache;
import tech.pegasys.pantheon.consensus.clique.jsonrpc.methods.CliqueGetSigners;
import tech.pegasys.pantheon.consensus.clique.jsonrpc.methods.CliqueGetSignersAtHash;
@ -72,7 +72,7 @@ public class CliqueJsonRpcMethodsFactory {
final ProtocolContext<CliqueContext> context, final MutableBlockchain blockchain) {
final EpochManager epochManager = context.getConsensusState().getEpochManager();
final VoteTallyUpdater voteTallyUpdater =
new VoteTallyUpdater(epochManager, new CliqueVotingBlockInterface());
new VoteTallyUpdater(epochManager, new CliqueBlockInterface());
return new VoteTallyCache(blockchain, voteTallyUpdater, epochManager);
}
}

@ -32,14 +32,14 @@ import java.util.Optional;
import org.junit.Test;
public class CliqueVotingBlockInterfaceTest {
public class CliqueBlockInterfaceTest {
private static final KeyPair proposerKeys = KeyPair.generate();
private static final Address proposerAddress =
Util.publicKeyToAddress(proposerKeys.getPublicKey());
private static final List<Address> validatorList = singletonList(proposerAddress);
private final CliqueVotingBlockInterface blockInterface = new CliqueVotingBlockInterface();
private final CliqueBlockInterface blockInterface = new CliqueBlockInterface();
private final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -86,7 +86,7 @@ public class CliqueVotingBlockInterfaceTest {
final ValidatorVote vote =
new ValidatorVote(ADD, AddressHelpers.ofValue(1), AddressHelpers.ofValue(2));
final BlockHeaderBuilder builderWithVote =
CliqueVotingBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
final BlockHeader header = builderWithVote.buildBlockHeader();
@ -100,7 +100,7 @@ public class CliqueVotingBlockInterfaceTest {
final ValidatorVote vote =
new ValidatorVote(DROP, AddressHelpers.ofValue(1), AddressHelpers.ofValue(2));
final BlockHeaderBuilder builderWithVote =
CliqueVotingBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
final BlockHeader header = builderWithVote.buildBlockHeader();
@ -111,7 +111,7 @@ public class CliqueVotingBlockInterfaceTest {
@Test
public void nonVoteBlendedIntoHeaderResultsInACoinbaseOfZero() {
final BlockHeaderBuilder builderWithVote =
CliqueVotingBlockInterface.insertVoteToHeaderBuilder(builder, Optional.empty());
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, Optional.empty());
final BlockHeader header = builderWithVote.buildBlockHeader();

@ -20,11 +20,11 @@ import static tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider.create
import static tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider.createInMemoryWorldStateArchive;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueExtraData;
import tech.pegasys.pantheon.consensus.clique.CliqueHelpers;
import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.clique.TestHelpers;
import tech.pegasys.pantheon.consensus.clique.VoteTallyCache;
import tech.pegasys.pantheon.consensus.common.VoteProposer;
@ -141,7 +141,7 @@ public class CliqueBlockCreatorTest {
blockchain.getChainHeadHeader());
final Block createdBlock = blockCreator.createBlock(0L);
assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueVotingBlockInterface.ADD_NONCE);
assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.ADD_NONCE);
assertThat(createdBlock.getHeader().getCoinbase()).isEqualTo(a1);
}
@ -166,8 +166,7 @@ public class CliqueBlockCreatorTest {
blockchain.getChainHeadHeader());
final Block createdBlock = blockCreator.createBlock(0L);
assertThat(createdBlock.getHeader().getNonce())
.isEqualTo(CliqueVotingBlockInterface.DROP_NONCE);
assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.DROP_NONCE);
assertThat(createdBlock.getHeader().getCoinbase()).isEqualTo(Address.fromHexString("0"));
}
}

@ -14,7 +14,7 @@ package tech.pegasys.pantheon.consensus.clique.headervalidationrules;
import static org.assertj.core.api.Java6Assertions.assertThat;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
@ -34,8 +34,8 @@ public class VoteValidationRuleTest {
public static Collection<Object[]> data() {
return Arrays.asList(
new Object[][] {
{CliqueVotingBlockInterface.DROP_NONCE, true},
{CliqueVotingBlockInterface.ADD_NONCE, true},
{CliqueBlockInterface.DROP_NONCE, true},
{CliqueBlockInterface.ADD_NONCE, true},
{0x01L, false},
{0xFFFFFFFFFFFFFFFEL, false}
});

@ -18,7 +18,9 @@ import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import java.util.List;
import java.util.Optional;
public interface VoteBlockInterface {
public interface BlockInterface {
Address getProposerOfBlock(final BlockHeader header);
Optional<ValidatorVote> extractVoteFromHeader(final BlockHeader header);

@ -31,10 +31,9 @@ public class VoteTallyUpdater {
private static final Logger LOG = LogManager.getLogger();
private final EpochManager epochManager;
private final VoteBlockInterface blockInterface;
private final BlockInterface blockInterface;
public VoteTallyUpdater(
final EpochManager epochManager, final VoteBlockInterface blockInterface) {
public VoteTallyUpdater(final EpochManager epochManager, final BlockInterface blockInterface) {
this.epochManager = epochManager;
this.blockInterface = blockInterface;
}

@ -45,7 +45,7 @@ public class VoteTallyUpdaterTest {
private final Address validator1 =
Address.fromHexString("00dae27b350bae20c5652124af5d8b5cba001ec1");
private final VoteBlockInterface serialiser = mock(VoteBlockInterface.class);
private final BlockInterface serialiser = mock(BlockInterface.class);
private final VoteTallyUpdater updater =
new VoteTallyUpdater(new EpochManager(EPOCH_LENGTH), serialiser);

@ -12,8 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.ibft;
import tech.pegasys.pantheon.consensus.common.BlockInterface;
import tech.pegasys.pantheon.consensus.common.ValidatorVote;
import tech.pegasys.pantheon.consensus.common.VoteBlockInterface;
import tech.pegasys.pantheon.consensus.common.VoteType;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -21,7 +21,12 @@ import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import java.util.List;
import java.util.Optional;
public class IbftVotingBlockInterface implements VoteBlockInterface {
public class IbftBlockInterface implements BlockInterface {
@Override
public Address getProposerOfBlock(final BlockHeader header) {
return header.getCoinbase();
}
@Override
public Optional<ValidatorVote> extractVoteFromHeader(final BlockHeader header) {
@ -32,7 +37,7 @@ public class IbftVotingBlockInterface implements VoteBlockInterface {
final ValidatorVote vote =
new ValidatorVote(
headerVote.isAuth() ? VoteType.ADD : VoteType.DROP,
header.getCoinbase(),
getProposerOfBlock(header),
headerVote.getRecipient());
return Optional.of(vote);
}

@ -58,7 +58,7 @@ public class IbftProtocolSchedule {
new IbftBlockImporter(
new MainnetBlockImporter<>(
blockHeaderValidator, blockBodyValidator, blockProcessor),
new VoteTallyUpdater(epochManager, new IbftVotingBlockInterface())),
new VoteTallyUpdater(epochManager, new IbftBlockInterface())),
(time, parent, protocolContext) -> BigInteger.ONE)
.blockReward(Wei.ZERO)
.blockHashFunction(IbftBlockHashing::calculateHashOfIbftBlockOnChain);

@ -10,14 +10,13 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.consensus.ibftlegacy.blockcreation;
package tech.pegasys.pantheon.consensus.ibft.blockcreation;
import static com.google.common.base.Preconditions.checkArgument;
import tech.pegasys.pantheon.consensus.common.BlockInterface;
import tech.pegasys.pantheon.consensus.common.ValidatorProvider;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHashing;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -56,12 +55,16 @@ public class ProposerSelector {
*/
private final Boolean changeEachBlock;
private final BlockInterface blockInterface;
public ProposerSelector(
final Blockchain blockchain,
final ValidatorProvider validators,
final BlockInterface blockInterface,
final boolean changeEachBlock) {
this.blockchain = blockchain;
this.validators = validators;
this.blockInterface = blockInterface;
this.changeEachBlock = changeEachBlock;
}
@ -152,8 +155,7 @@ public class ProposerSelector {
final Optional<BlockHeader> maybeBlockHeader = blockchain.getBlockHeader(blockNumber);
if (maybeBlockHeader.isPresent()) {
final BlockHeader blockHeader = maybeBlockHeader.get();
final IbftExtraData extraData = IbftExtraData.decode(blockHeader.getExtraData());
return IbftBlockHashing.recoverProposerAddress(blockHeader, extraData);
return blockInterface.getProposerOfBlock(blockHeader);
} else {
LOG.trace("Unable to determine proposer for requested block");
throw new RuntimeException("Unable to determine past proposer");

@ -10,28 +10,23 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.consensus.ibftlegacy.blockcreation;
package tech.pegasys.pantheon.consensus.ibft.blockcreation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.consensus.common.BlockInterface;
import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHashing;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData;
import tech.pegasys.pantheon.crypto.SECP256K1;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.AddressHelpers;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.LinkedList;
import java.util.Optional;
@ -41,36 +36,16 @@ import org.junit.Test;
public class ProposerSelectorTest {
private final BlockInterface blockInterface = mock(BlockInterface.class);
private Blockchain createMockedBlockChainWithHeadOf(
final long blockNumber, final KeyPair nodeKeys) {
final long blockNumber, final Address proposer) {
final IbftExtraData unsignedExtraData =
new IbftExtraData(
BytesValue.wrap(new byte[32]),
Lists.newArrayList(),
// seals are not required for this test.
null, // No proposer seal till after block exists
Lists.newArrayList()); // Actual content of extradata is irrelevant.
when(blockInterface.getProposerOfBlock(any())).thenReturn(proposer);
final BlockHeaderTestFixture headerBuilderFixture = new BlockHeaderTestFixture();
headerBuilderFixture.number(blockNumber).extraData(unsignedExtraData.encode());
final Hash signingHash =
IbftBlockHashing.calculateDataHashForProposerSeal(
headerBuilderFixture.buildHeader(), unsignedExtraData);
final Signature proposerSignature = SECP256K1.sign(signingHash, nodeKeys);
// Duplicate the original extraData, but include the proposerSeal
final IbftExtraData signedExtraData =
new IbftExtraData(
unsignedExtraData.getVanityData(),
unsignedExtraData.getSeals(),
proposerSignature,
unsignedExtraData.getValidators());
final BlockHeader prevBlockHeader =
headerBuilderFixture.extraData(signedExtraData.encode()).buildHeader();
headerBuilderFixture.number(blockNumber);
final BlockHeader prevBlockHeader = headerBuilderFixture.buildHeader();
// Construct a block chain and world state
final MutableBlockchain blockchain = mock(MutableBlockchain.class);
@ -110,17 +85,14 @@ public class ProposerSelectorTest {
@Test
public void roundRobinChangesProposerOnRoundZeroOfNextBlock() {
final long PREV_BLOCK_NUMBER = 2;
final KeyPair prevProposerKeys = KeyPair.generate();
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
final LinkedList<Address> validatorList = createValidatorList(localAddr, 0, 4);
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, true);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, true);
final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
@ -132,18 +104,13 @@ public class ProposerSelectorTest {
@Test
public void lastValidatorInListValidatedPreviousBlockSoFirstIsNextProposer() {
final long PREV_BLOCK_NUMBER = 2;
final KeyPair prevProposerKeys = KeyPair.generate();
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
final LinkedList<Address> validatorList = createValidatorList(localAddr, 4, 0);
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, true);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, true);
final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
@ -157,16 +124,12 @@ public class ProposerSelectorTest {
final long PREV_BLOCK_NUMBER = 2;
final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
final KeyPair prevProposerKeys = KeyPair.generate();
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
final LinkedList<Address> validatorList = createValidatorList(localAddr, 4, 0);
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, false);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, false);
final Address nextProposer = uut.selectProposerForRound(roundId);
assertThat(nextProposer).isEqualTo(localAddr);
@ -177,16 +140,13 @@ public class ProposerSelectorTest {
final long PREV_BLOCK_NUMBER = 2;
ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
final KeyPair prevProposerKeys = KeyPair.generate();
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final LinkedList<Address> validatorList = createValidatorList(localAddr, 4, 0);
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, false);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, false);
assertThat(uut.selectProposerForRound(roundId)).isEqualTo(localAddr);
roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 1);
@ -201,12 +161,8 @@ public class ProposerSelectorTest {
final long PREV_BLOCK_NUMBER = 2;
final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
final KeyPair prevProposerKeys = KeyPair.generate();
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
// LocalAddr will be in index 2 - the next proposer will also be in 2 (as prev proposer is
// removed)
@ -216,7 +172,7 @@ public class ProposerSelectorTest {
// Note the signer of the Previous block was not included.
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, false);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, false);
assertThat(uut.selectProposerForRound(roundId)).isEqualTo(validatorList.get(2));
}
@ -226,12 +182,8 @@ public class ProposerSelectorTest {
final long PREV_BLOCK_NUMBER = 2;
final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
final KeyPair prevProposerKeys = KeyPair.generate();
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
// LocalAddr will be in index 2 - the next proposer will also be in 2 (as prev proposer is
// removed)
@ -241,7 +193,7 @@ public class ProposerSelectorTest {
// Note the signer of the Previous block was not included.
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, true);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, true);
assertThat(uut.selectProposerForRound(roundId)).isEqualTo(validatorList.get(2));
}
@ -251,12 +203,8 @@ public class ProposerSelectorTest {
final long PREV_BLOCK_NUMBER = 2;
final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(PREV_BLOCK_NUMBER + 1, 0);
final KeyPair prevProposerKeys = KeyPair.generate();
final Blockchain blockchain =
createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, prevProposerKeys);
final Address localAddr =
Address.extract(Hash.hash(prevProposerKeys.getPublicKey().getEncodedBytes()));
final Address localAddr = AddressHelpers.ofValue(10); // arbitrarily selected
final Blockchain blockchain = createMockedBlockChainWithHeadOf(PREV_BLOCK_NUMBER, localAddr);
// LocalAddr will be in index 2 - the next proposer will also be in 2 (as prev proposer is
// removed)
@ -266,7 +214,7 @@ public class ProposerSelectorTest {
// Note the signer of the Previous block was not included.
final VoteTally voteTally = new VoteTally(validatorList);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, false);
final ProposerSelector uut = new ProposerSelector(blockchain, voteTally, blockInterface, false);
assertThat(uut.selectProposerForRound(roundId)).isEqualTo(validatorList.get(0));
}

@ -12,8 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.ibftlegacy;
import tech.pegasys.pantheon.consensus.common.BlockInterface;
import tech.pegasys.pantheon.consensus.common.ValidatorVote;
import tech.pegasys.pantheon.consensus.common.VoteBlockInterface;
import tech.pegasys.pantheon.consensus.common.VoteType;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -25,7 +25,7 @@ import java.util.Optional;
import com.google.common.collect.ImmutableBiMap;
public class IbftLegacyVotingBlockInterface implements VoteBlockInterface {
public class IbftLegacyBlockInterface implements BlockInterface {
public static final Address NO_VOTE_SUBJECT =
Address.wrap(BytesValue.wrap(new byte[Address.SIZE]));
@ -38,12 +38,17 @@ public class IbftLegacyVotingBlockInterface implements VoteBlockInterface {
VoteType.ADD, ADD_NONCE,
VoteType.DROP, DROP_NONCE);
@Override
public Address getProposerOfBlock(final BlockHeader header) {
final IbftExtraData ibftExtraData = IbftExtraData.decode(header.getExtraData());
return IbftBlockHashing.recoverProposerAddress(header, ibftExtraData);
}
@Override
public Optional<ValidatorVote> extractVoteFromHeader(final BlockHeader header) {
final Address candidate = header.getCoinbase();
if (!candidate.equals(NO_VOTE_SUBJECT)) {
final IbftExtraData ibftExtraData = IbftExtraData.decode(header.getExtraData());
final Address proposer = IbftBlockHashing.recoverProposerAddress(header, ibftExtraData);
final Address proposer = getProposerOfBlock(header);
final VoteType votePolarity = voteToValue.inverse().get(header.getNonce());
final Address recipient = header.getCoinbase();

@ -60,7 +60,7 @@ public class IbftProtocolSchedule {
new IbftBlockImporter(
new MainnetBlockImporter<>(
blockHeaderValidator, blockBodyValidator, blockProcessor),
new VoteTallyUpdater(epochManager, new IbftLegacyVotingBlockInterface())),
new VoteTallyUpdater(epochManager, new IbftLegacyBlockInterface())),
(time, parent, protocolContext) -> BigInteger.ONE)
.blockReward(Wei.ZERO)
.blockHashFunction(IbftBlockHashing::calculateHashOfIbftBlockOnChain);

@ -12,7 +12,7 @@
*/
package tech.pegasys.pantheon.consensus.ibftlegacy.headervalidationrules;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftLegacyVotingBlockInterface;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftLegacyBlockInterface;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.DetachedBlockHeaderValidationRule;
@ -33,7 +33,7 @@ public class VoteValidationRule implements DetachedBlockHeaderValidationRule {
@Override
public boolean validate(final BlockHeader header, final BlockHeader parent) {
final long nonce = header.getNonce();
if (!IbftLegacyVotingBlockInterface.isValidVoteValue(nonce)) {
if (!IbftLegacyBlockInterface.isValidVoteValue(nonce)) {
LOG.trace("Nonce value ({}) is neither auth or drop.", nonce);
return false;
}

@ -99,7 +99,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
builder.mixHash(
Hash.fromHexString("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365"));
builder.ommersHash(Hash.EMPTY_LIST_HASH);
builder.nonce(IbftLegacyVotingBlockInterface.DROP_NONCE);
builder.nonce(IbftLegacyBlockInterface.DROP_NONCE);
builder.difficulty(UInt256.ONE);
// Construct an extraData block

@ -33,7 +33,7 @@ import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class IbftLegacyVotingBlockInterfaceTest {
public class IbftLegacyBlockInterfaceTest {
private static final KeyPair proposerKeys = KeyPair.generate();
private static final Address proposerAddress =
@ -41,8 +41,7 @@ public class IbftLegacyVotingBlockInterfaceTest {
private static final List<Address> validatorList = singletonList(proposerAddress);
private final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
private final IbftLegacyVotingBlockInterface blockInterface =
new IbftLegacyVotingBlockInterface();
private final IbftLegacyBlockInterface blockInterface = new IbftLegacyBlockInterface();
private final BlockHeaderBuilder builder =
BlockHeaderBuilder.fromHeader(headerBuilder.buildHeader())
.blockHashFunction(MainnetBlockHashFunction::createHash);
@ -86,7 +85,7 @@ public class IbftLegacyVotingBlockInterfaceTest {
final ValidatorVote vote =
new ValidatorVote(ADD, AddressHelpers.ofValue(1), AddressHelpers.ofValue(2));
final BlockHeaderBuilder builderWithVote =
IbftLegacyVotingBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
IbftLegacyBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
final BlockHeader header = builderWithVote.buildBlockHeader();
@ -99,7 +98,7 @@ public class IbftLegacyVotingBlockInterfaceTest {
final ValidatorVote vote =
new ValidatorVote(DROP, AddressHelpers.ofValue(1), AddressHelpers.ofValue(2));
final BlockHeaderBuilder builderWithVote =
IbftLegacyVotingBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
IbftLegacyBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
final BlockHeader header = builderWithVote.buildBlockHeader();
@ -110,7 +109,7 @@ public class IbftLegacyVotingBlockInterfaceTest {
@Test
public void nonVoteBlendedIntoHeaderResultsInACoinbaseOfZero() {
final BlockHeaderBuilder builderWithVote =
IbftLegacyVotingBlockInterface.insertVoteToHeaderBuilder(builder, Optional.empty());
IbftLegacyBlockInterface.insertVoteToHeaderBuilder(builder, Optional.empty());
final BlockHeader header = builderWithVote.buildBlockHeader();

@ -16,9 +16,9 @@ import static org.apache.logging.log4j.LogManager.getLogger;
import tech.pegasys.pantheon.config.CliqueConfigOptions;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule;
import tech.pegasys.pantheon.consensus.clique.CliqueVotingBlockInterface;
import tech.pegasys.pantheon.consensus.clique.VoteTallyCache;
import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueBlockScheduler;
import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueMinerExecutor;
@ -130,7 +130,7 @@ public class CliquePantheonController implements PantheonController<CliqueContex
new CliqueContext(
new VoteTallyCache(
blockchain,
new VoteTallyUpdater(epochManger, new CliqueVotingBlockInterface()),
new VoteTallyUpdater(epochManger, new CliqueBlockInterface()),
epochManger),
new VoteProposer(),
epochManger));

@ -31,7 +31,7 @@ import tech.pegasys.pantheon.consensus.ibft.jsonrpc.IbftJsonRpcMethodsFactory;
import tech.pegasys.pantheon.consensus.ibft.network.IbftNetworkPeers;
import tech.pegasys.pantheon.consensus.ibft.protocol.IbftProtocolManager;
import tech.pegasys.pantheon.consensus.ibft.protocol.IbftSubProtocol;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftLegacyVotingBlockInterface;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftLegacyBlockInterface;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule;
import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64Protocol;
import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64ProtocolManager;
@ -135,7 +135,7 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
final VoteTally voteTally =
new VoteTallyUpdater(epochManager, new IbftLegacyVotingBlockInterface())
new VoteTallyUpdater(epochManager, new IbftLegacyBlockInterface())
.buildVoteTallyFromBlockchain(blockchain);
final VoteProposer voteProposer = new VoteProposer();

Loading…
Cancel
Save