From a092d9cb879889a19f4466505c782b02f7bf36c6 Mon Sep 17 00:00:00 2001 From: magnusbechwind Date: Thu, 19 Oct 2023 10:46:02 +0200 Subject: [PATCH 1/6] updated concordium-base --- concordium-base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concordium-base b/concordium-base index 4e980f763..e7e01ef0f 160000 --- a/concordium-base +++ b/concordium-base @@ -1 +1 @@ -Subproject commit 4e980f763b0014129529224fd22ed3d34e6304bd +Subproject commit e7e01ef0f1100185722330885fb0c4ddacbd7e45 From d77dccfb4ed97ccfd915ee241209c1f8e2c3f0e4 Mon Sep 17 00:00:00 2001 From: magnusbechwind Date: Thu, 19 Oct 2023 14:23:29 +0200 Subject: [PATCH 2/6] Added support for the `GetBakerRewardPeriodInfo` query. --- .../java/com/concordium/sdk/ClientV2.java | 24 ++++++- .../bakersrewardperiod/BakerInfo.java | 56 +++++++++++++++++ .../BakerRewardPeriodInfo.java | 63 +++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerInfo.java create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerRewardPeriodInfo.java diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2.java b/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2.java index 75ed6d811..ab0e9cf03 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/ClientV2.java @@ -11,6 +11,7 @@ import com.concordium.sdk.responses.DelegatorInfo; import com.concordium.sdk.responses.DelegatorRewardPeriodInfo; import com.concordium.sdk.responses.*; +import com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo; import com.concordium.sdk.responses.accountinfo.AccountInfo; import com.concordium.sdk.responses.blockinfo.BlockInfo; import com.concordium.sdk.responses.blockitemstatus.BlockItemStatus; @@ -84,8 +85,9 @@ public static ClientV2 from(final Connection connection) throws ClientInitializa /** * Construct a new client - * @param timeout The timeout in milliseconds. - * @param channel the underlying grpc channel. + * + * @param timeout The timeout in milliseconds. + * @param channel the underlying grpc channel. * @param credentials Optionally extra headers. */ ClientV2(final int timeout, final ManagedChannel channel, final Optional credentials) { @@ -775,6 +777,24 @@ public InvokeInstanceResult invokeInstance(InvokeInstanceRequest request) { return InvokeInstanceResult.parse(grpcResponse); } + /** + * Get all bakers in the reward period of a block. + * This endpoint is only supported for protocol version 6 and onwards. + * If the protocol does not support the endpoint then an 'UNIMPLEMENTED' exception is thrown + * + * @param input The block to query. + * + * @return {@link ImmutableList} with the {@link BakerRewardPeriodInfo} of all the bakers in the block. + */ + public ImmutableList getBakersRewardPeriod(BlockQuery input) { + val response = this.server().getBakersRewardPeriod(to(input)); + val periodInfos = new ImmutableList.Builder(); + response.forEachRemaining( + info -> periodInfos.add(BakerRewardPeriodInfo.from(info)) + ); + return periodInfos.build(); + } + /** * Get a {@link QueriesGrpc.QueriesBlockingStub} with a timeout * The timeout is the one specified in via the {@link Connection} object used to diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerInfo.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerInfo.java new file mode 100644 index 000000000..a53201252 --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerInfo.java @@ -0,0 +1,56 @@ +package com.concordium.sdk.responses.bakersrewardperiod; + +import com.concordium.sdk.crypto.bls.BLSPublicKey; +import com.concordium.sdk.crypto.ed25519.ED25519PublicKey; +import com.concordium.sdk.crypto.vrf.VRFPublicKey; +import com.concordium.sdk.responses.BakerId; +import com.concordium.sdk.responses.nodeinfo.NodeInfo; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +/** + * Information about a baker. + */ +@Builder +@Getter +@EqualsAndHashCode +@ToString +public class BakerInfo { + + /** + * Id of the baker. + */ + private BakerId bakerId; + /** + * Baker's public key used to check whether they won the lottery or not. + */ + private VRFPublicKey bakerElectionVerifyKey; + /** + * Baker's public key used to check that they are indeed the ones who produced the block. + */ + private ED25519PublicKey bakerSignatureVerifyKey; + /** + * Baker's public key used to check signatures on finalization records. + * This is only used if the baker has sufficient stake to participate in finalization. + */ + private BLSPublicKey bakerAggregationVerifyKey; + + /** + * Parses {@link com.concordium.grpc.v2.BakerInfo} to {@link BakerInfo}. + * + * @param bakerInfo {@link com.concordium.grpc.v2.BakerInfo} returned by the GRPC v2 API. + * @return Parsed {@link BakerRewardPeriodInfo}. + */ + public static BakerInfo from(com.concordium.grpc.v2.BakerInfo bakerInfo) { + return BakerInfo.builder() + .bakerId(BakerId.from(bakerInfo.getBakerId())) + .bakerElectionVerifyKey(VRFPublicKey.from(bakerInfo.getElectionKey().getValue().toByteArray())) + .bakerSignatureVerifyKey(ED25519PublicKey.from(bakerInfo.getSignatureKey().getValue().toByteArray())) + .bakerAggregationVerifyKey(BLSPublicKey.from(bakerInfo.getAggregationKey().getValue().toByteArray())) + .build(); + } +} + + diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerRewardPeriodInfo.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerRewardPeriodInfo.java new file mode 100644 index 000000000..de9da3efc --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/bakersrewardperiod/BakerRewardPeriodInfo.java @@ -0,0 +1,63 @@ +package com.concordium.sdk.responses.bakersrewardperiod; + +import com.concordium.sdk.responses.accountinfo.CommissionRates; +import com.concordium.sdk.transactions.CCDAmount; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +/** + * Information about a particular baker with respect to the current reward period. + */ +@Builder +@ToString +@Getter +@EqualsAndHashCode +public class BakerRewardPeriodInfo { + + /** + * The baker id and public keys for the baker. + */ + private BakerInfo baker; + /** + * The effective stake of the baker for the consensus protocol. + * The returned amount accounts for delegation, capital bounds and leverage bounds. + */ + private CCDAmount effectiveStake; + /** + * The effective commission rate for the baker that applies for the reward period. + */ + private CommissionRates commissionRates; + /** + * The amount staked by the baker itself. + */ + private CCDAmount equityCapital; + /** + * The total amount of capital delegated to this baker pool. + */ + private CCDAmount delegatedCapital; + /** + * Whether the baker is a finalizer or not. + */ + private boolean isFinalizer; + + /** + * Parses {@link com.concordium.grpc.v2.BakerRewardPeriodInfo} to {@link BakerRewardPeriodInfo}. + * + * @param info {@link com.concordium.grpc.v2.BakerRewardPeriodInfo} returned by the GRPC v2 API. + * @return Parsed {@link BakerRewardPeriodInfo}. + */ + public static BakerRewardPeriodInfo from(com.concordium.grpc.v2.BakerRewardPeriodInfo info) { + return BakerRewardPeriodInfo.builder() + .baker(BakerInfo.from(info.getBaker())) + .effectiveStake(CCDAmount.from(info.getEffectiveStake())) + .commissionRates(CommissionRates.from(info.getCommissionRates())) + .equityCapital(CCDAmount.from(info.getEquityCapital())) + .delegatedCapital(CCDAmount.from(info.getDelegatedCapital())) + .isFinalizer(info.getIsFinalizer()) + .build(); + + } + +} From 08c99feafec3475462dcabd4fb25c2f055b7607f Mon Sep 17 00:00:00 2001 From: magnusbechwind Date: Thu, 19 Oct 2023 14:26:38 +0200 Subject: [PATCH 3/6] updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a9c3ecb5..86187b06d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased changes +- Added support for GRPC V2 `GetBakerRewardPeriodInfo` for getting all the bakers in the reward period of a block. ## 5.1.0 - Fixed a regression that made it harder to deserialize transactions from bytes. From 335071368cd6c6bf039e698bb0c835eeb5c26f5f Mon Sep 17 00:00:00 2001 From: magnusbechwind Date: Thu, 19 Oct 2023 15:38:47 +0200 Subject: [PATCH 4/6] Passing test --- .../ClientV2GetBakerRewardPeriodInfoTest.java | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 concordium-sdk/src/test/java/com/concordium/sdk/ClientV2GetBakerRewardPeriodInfoTest.java diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/ClientV2GetBakerRewardPeriodInfoTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/ClientV2GetBakerRewardPeriodInfoTest.java new file mode 100644 index 000000000..f9500190c --- /dev/null +++ b/concordium-sdk/src/test/java/com/concordium/sdk/ClientV2GetBakerRewardPeriodInfoTest.java @@ -0,0 +1,200 @@ +package com.concordium.sdk; + +import com.concordium.grpc.v2.*; +import com.concordium.sdk.crypto.bls.BLSPublicKey; +import com.concordium.sdk.crypto.ed25519.ED25519PublicKey; +import com.concordium.sdk.crypto.ed25519.ED25519SecretKey; +import com.concordium.sdk.crypto.vrf.VRFPublicKey; +import com.concordium.sdk.requests.BlockQuery; +import com.concordium.sdk.responses.BakerId; +import com.concordium.sdk.responses.accountinfo.CommissionRates; +import com.concordium.sdk.responses.transactionstatus.PartsPerHundredThousand; +import com.concordium.sdk.transactions.CCDAmount; +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.StreamObserver; +import io.grpc.testing.GrpcCleanupRule; +import lombok.val; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.mockito.AdditionalAnswers.delegatesTo; +import static org.mockito.Mockito.mock; + +/** + * The test asserts that {@link ClientV2#getBakersRewardPeriod(BlockQuery)} + * correctly converts the {@link BakerRewardPeriodInfo} returned by the node to {@link com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo} + */ +public class ClientV2GetBakerRewardPeriodInfoTest { + // ---- Test Values ---- + + // For creating BakerInfo + private static final int BAKER_ID_1 = 1; + private static final int BAKER_ID_2 = 2; + + private static final byte[] BAKER_ELECTION_VERIFY_KEY_1 + = ED25519PublicKey.from(ED25519SecretKey.createNew()).getBytes(); + private static final byte[] BAKER_ELECTION_VERIFY_KEY_2 + = ED25519PublicKey.from(ED25519SecretKey.createNew()).getBytes(); + private static final byte[] BAKER_SIGNATURE_VERIFY_KEY_1 + = ED25519PublicKey.from(ED25519SecretKey.createNew()).getBytes(); + private static final byte[] BAKER_SIGNATURE_VERIFY_KEY_2 + = ED25519PublicKey.from(ED25519SecretKey.createNew()).getBytes(); + private static final byte[] BAKER_AGGREGATION_KEY_1 + = ED25519PublicKey.from(ED25519SecretKey.createNew()).getBytes(); + private static final byte[] BAKER_AGGREGATION_KEY_2 + = ED25519PublicKey.from(ED25519SecretKey.createNew()).getBytes(); + + + private static final int EFFECTIVE_STAKE_1 = 100; + private static final int EFFECTIVE_STAKE_2 = 200; + + // For creating Commission Rates + private static final int COM_FINAL_1 = 100; + private static final int COM_FINAL_2 = 200; + private static final int COM_BAKING_1 = 100; + private static final int COM_BAKING_2 = 200; + private static final int COM_TRAN_1 = 100; + private static final int COM_TRAN_2 = 200; + + private static final int EQUITY_1 = 100; + private static final int EQUITY_2 = 200; + private static final int DELEGATED_1 = 100; + private static final int DELEGATED_2 = 200; + private static final boolean IS_FINALIZER_1 = true; + private static final boolean IS_FINALIZER_2 = false; + + // ---- Clientside Test Values ---- + private static final com.concordium.sdk.responses.bakersrewardperiod.BakerInfo CLIENT_BAKER_INFO_1 + = com.concordium.sdk.responses.bakersrewardperiod.BakerInfo.builder() + .bakerId(BakerId.from(BAKER_ID_1)) + .bakerElectionVerifyKey(VRFPublicKey.from(BAKER_ELECTION_VERIFY_KEY_1)) + .bakerSignatureVerifyKey(ED25519PublicKey.from(BAKER_SIGNATURE_VERIFY_KEY_1)) + .bakerAggregationVerifyKey(BLSPublicKey.from(BAKER_AGGREGATION_KEY_1)) + .build(); + + private static final com.concordium.sdk.responses.bakersrewardperiod.BakerInfo CLIENT_BAKER_INFO_2 + = com.concordium.sdk.responses.bakersrewardperiod.BakerInfo.builder() + .bakerId(BakerId.from(BAKER_ID_2)) + .bakerElectionVerifyKey(VRFPublicKey.from(BAKER_ELECTION_VERIFY_KEY_2)) + .bakerSignatureVerifyKey(ED25519PublicKey.from(BAKER_SIGNATURE_VERIFY_KEY_2)) + .bakerAggregationVerifyKey(BLSPublicKey.from(BAKER_AGGREGATION_KEY_2)) + .build(); + + private static final com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo CLIENT_INFO_1 = + com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo.builder() + .baker(CLIENT_BAKER_INFO_1) + .effectiveStake(CCDAmount.fromMicro(EFFECTIVE_STAKE_1)) + .commissionRates(CommissionRates.builder() + .finalizationCommission(PartsPerHundredThousand.from(COM_FINAL_1).asDouble()) + .bakingCommission(PartsPerHundredThousand.from(COM_BAKING_1).asDouble()) + .transactionCommission(PartsPerHundredThousand.from(COM_TRAN_1).asDouble()) + .build()) + .equityCapital(CCDAmount.fromMicro(EQUITY_1)) + .delegatedCapital(CCDAmount.fromMicro(DELEGATED_1)) + .isFinalizer(IS_FINALIZER_1) + .build(); + private static final com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo CLIENT_INFO_2 = + com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo.builder() + .baker(CLIENT_BAKER_INFO_2) + .effectiveStake(CCDAmount.fromMicro(EFFECTIVE_STAKE_2)) + .commissionRates(CommissionRates.builder() + .finalizationCommission(PartsPerHundredThousand.from(COM_FINAL_2).asDouble()) + .bakingCommission(PartsPerHundredThousand.from(COM_BAKING_2).asDouble()) + .transactionCommission(PartsPerHundredThousand.from(COM_TRAN_2).asDouble()) + .build()) + .equityCapital(CCDAmount.fromMicro(EQUITY_2)) + .delegatedCapital(CCDAmount.fromMicro(DELEGATED_2)) + .isFinalizer(IS_FINALIZER_2) + .build(); + + // ---- GRPC Test Values ---- + private static final BakerInfo GRPC_BAKER_1 = BakerInfo.newBuilder() + .setBakerId(com.concordium.grpc.v2.BakerId.newBuilder().setValue(BAKER_ID_1)) + .setElectionKey(BakerElectionVerifyKey.newBuilder() + .setValue(ByteString.copyFrom(BAKER_ELECTION_VERIFY_KEY_1)).build()) + .setSignatureKey(BakerSignatureVerifyKey.newBuilder() + .setValue(ByteString.copyFrom(BAKER_SIGNATURE_VERIFY_KEY_1)).build()) + .setAggregationKey(BakerAggregationVerifyKey.newBuilder() + .setValue(ByteString.copyFrom(BAKER_AGGREGATION_KEY_1)).build()) + .build(); + private static final BakerInfo GRPC_BAKER_2 = BakerInfo.newBuilder() + .setBakerId(com.concordium.grpc.v2.BakerId.newBuilder().setValue(BAKER_ID_2)) + .setElectionKey(BakerElectionVerifyKey.newBuilder() + .setValue(ByteString.copyFrom(BAKER_ELECTION_VERIFY_KEY_2)).build()) + .setSignatureKey(BakerSignatureVerifyKey.newBuilder() + .setValue(ByteString.copyFrom(BAKER_SIGNATURE_VERIFY_KEY_2)).build()) + .setAggregationKey(BakerAggregationVerifyKey.newBuilder() + .setValue(ByteString.copyFrom(BAKER_AGGREGATION_KEY_2)).build()) + .build(); + + private static final BakerRewardPeriodInfo GRPC_INFO_1 = + BakerRewardPeriodInfo.newBuilder() + .setBaker(GRPC_BAKER_1) + .setEffectiveStake(Amount.newBuilder().setValue(EFFECTIVE_STAKE_1)) + .setCommissionRates(com.concordium.grpc.v2.CommissionRates.newBuilder() + .setFinalization(AmountFraction.newBuilder().setPartsPerHundredThousand(COM_FINAL_1)) + .setBaking(AmountFraction.newBuilder().setPartsPerHundredThousand(COM_BAKING_1)) + .setTransaction(AmountFraction.newBuilder().setPartsPerHundredThousand(COM_TRAN_1))) + .setEquityCapital(Amount.newBuilder().setValue(EQUITY_1)) + .setDelegatedCapital(Amount.newBuilder().setValue(DELEGATED_1)) + .setIsFinalizer(IS_FINALIZER_1) + .build(); + private static final BakerRewardPeriodInfo GRPC_INFO_2 = + BakerRewardPeriodInfo.newBuilder() + .setBaker(GRPC_BAKER_2) + .setEffectiveStake(Amount.newBuilder().setValue(EFFECTIVE_STAKE_2)) + .setCommissionRates(com.concordium.grpc.v2.CommissionRates.newBuilder() + .setFinalization(AmountFraction.newBuilder().setPartsPerHundredThousand(COM_FINAL_2)) + .setBaking(AmountFraction.newBuilder().setPartsPerHundredThousand(COM_BAKING_2)) + .setTransaction(AmountFraction.newBuilder().setPartsPerHundredThousand(COM_TRAN_2))) + .setEquityCapital(Amount.newBuilder().setValue(EQUITY_2)) + .setDelegatedCapital(Amount.newBuilder().setValue(DELEGATED_2)) + .setIsFinalizer(IS_FINALIZER_2) + .build(); + + // ---- Setup ---- + private static final QueriesGrpc.QueriesImplBase serviceImpl = mock(QueriesGrpc.QueriesImplBase.class, delegatesTo( + new QueriesGrpc.QueriesImplBase() { + @Override + public void getBakersRewardPeriod( + com.concordium.grpc.v2.BlockHashInput request, + StreamObserver responseObserver) { + responseObserver.onNext(GRPC_INFO_1); + responseObserver.onNext(GRPC_INFO_2); + responseObserver.onCompleted(); + } + } + )); + + @Rule + public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + + private ClientV2 client; + + @Before + public void setUp() throws Exception { + String serverName = InProcessServerBuilder.generateName(); + grpcCleanup.register(InProcessServerBuilder + .forName(serverName).directExecutor().addService(serviceImpl).build().start()); + ManagedChannel channel = grpcCleanup.register( + InProcessChannelBuilder.forName(serverName).directExecutor().build()); + client = new ClientV2(10000, channel, Optional.empty()); + } + + @Test + public void shouldParseCorrectly() { + val res = client.getBakersRewardPeriod(BlockQuery.BEST); + val res1 = res.get(0); + val res2 = res.get(1); + assertEquals(CLIENT_INFO_1, res1); + assertEquals(CLIENT_INFO_2, res2); + } + +} From 1cb43e209cdea8df160048bc849af2227372e085 Mon Sep 17 00:00:00 2001 From: magnusbechwind Date: Thu, 19 Oct 2023 16:00:11 +0200 Subject: [PATCH 5/6] Added example --- .../sdk/examples/GetBakersRewardPeriod.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/GetBakersRewardPeriod.java diff --git a/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/GetBakersRewardPeriod.java b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/GetBakersRewardPeriod.java new file mode 100644 index 000000000..447f50f03 --- /dev/null +++ b/concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/GetBakersRewardPeriod.java @@ -0,0 +1,47 @@ +package com.concordium.sdk.examples; + +import com.concordium.sdk.ClientV2; +import com.concordium.sdk.Connection; +import com.concordium.sdk.requests.BlockQuery; +import com.concordium.sdk.responses.bakersrewardperiod.BakerRewardPeriodInfo; +import lombok.val; +import picocli.CommandLine; + +import java.net.URL; +import java.util.concurrent.Callable; + +/** + * Calls {@link ClientV2#getBakersRewardPeriod(BlockQuery)} + * retrieving a list of {@link BakerRewardPeriodInfo} about the bakers in the reward period of the block. + * Prints the result to the terminal. + */ +@CommandLine.Command(name = "GetBakersRewardPeriod", mixinStandardHelpOptions = true) +public class GetBakersRewardPeriod implements Callable { + + @CommandLine.Option( + names = {"--endpoint"}, + description = "GRPC interface of the node.", + defaultValue = "http://localhost:20002") + private String endpoint; + + @Override + public Integer call() throws Exception { + URL endpointUrl = new URL(this.endpoint); + Connection connection = Connection.newBuilder() + .host(endpointUrl.getHost()) + .port(endpointUrl.getPort()) + .build(); + + ClientV2 client = ClientV2.from(connection); + + + val bakerInfo = client.getBakersRewardPeriod(BlockQuery.BEST); + bakerInfo.forEach(System.out::println); + return 0; + } + + public static void main(String[] args) { + int exitCode = new CommandLine(new GetBakersRewardPeriod()).execute(args); + System.exit(exitCode); + } +} From dc356032ab0bf8fb5ce38eaf564b693d1b1a6422 Mon Sep 17 00:00:00 2001 From: magnusbechwind Date: Wed, 1 Nov 2023 13:39:10 +0100 Subject: [PATCH 6/6] Adressed review comments --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86187b06d..fd8bdc53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased changes -- Added support for GRPC V2 `GetBakerRewardPeriodInfo` for getting all the bakers in the reward period of a block. +- Added support for GRPC V2 `GetBakerRewardPeriodInfo` for getting all the bakers in the reward period of a block. Only available when querying a node with version at least 6.1. ## 5.1.0 - Fixed a regression that made it harder to deserialize transactions from bytes.