-
Notifications
You must be signed in to change notification settings - Fork 195
feat: Highest node id in state #21861
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
base: main
Are you sure you want to change the base?
Changes from 75 commits
e88d62a
e12a1b2
a67c57a
387ed61
1c6f23a
35f386d
bb69099
cc9539a
f7d8124
fe97d3b
9f5986d
a23c8c0
5dd1be7
7740ca8
5b6179d
3b6757e
89d0f8d
4a563c5
a4aeadf
9b963a7
63aa4d8
500749a
8bdbed4
072b575
ea6dc7d
ebcddaf
4b7a1f7
f7b3458
4864c8b
8787c0c
9911c89
e14b984
15e2b1b
249301e
1e35c36
581ba93
f59b08b
e41faf5
a7a57e3
c130f79
6ca2a70
f3d1c43
cc862b6
210bf0d
3a9e90d
1261983
477a123
bffa0f9
bc4ff3c
c62071c
e68784c
dee6150
25f71bf
21cb8f6
542ce5c
8f40855
f830ef7
2715819
67ea14c
3a125f8
d499abe
f8cfcce
3a01ea2
2ddf2fa
6a8fa1a
ae5a6fd
92e9479
98eb6b8
01c5c95
30d5869
79dad8a
95878a4
b552a8c
98f4584
28186dd
113e71e
9c83ec3
11aaba1
e695c2e
96fbeb0
17b2217
70252b5
d9fcf64
9a913c3
df321c0
d0a255a
b646f90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,7 @@ | |
| import static com.hedera.hapi.node.base.ResponseCodeEnum.MAX_NODES_CREATED; | ||
| import static com.hedera.node.app.service.addressbook.AddressBookHelper.checkDABEnabled; | ||
| import static com.hedera.node.app.service.addressbook.impl.validators.AddressBookValidator.validateX509Certificate; | ||
| import static com.hedera.node.app.spi.workflows.HandleException.validateFalse; | ||
| import static com.hedera.node.app.spi.workflows.HandleContext.DispatchMetadata.Type.SYSTEM_TXN_CREATION_ENTITY_NUM; | ||
| import static com.hedera.node.app.spi.workflows.HandleException.validateTrue; | ||
| import static com.hedera.node.app.spi.workflows.PreCheckException.validateFalsePreCheck; | ||
| import static java.util.Objects.requireNonNull; | ||
|
|
@@ -18,10 +18,12 @@ | |
| import com.hedera.hapi.node.base.HederaFunctionality; | ||
| import com.hedera.hapi.node.base.SubType; | ||
| import com.hedera.hapi.node.state.addressbook.Node; | ||
| import com.hedera.node.app.service.addressbook.ReadableNodeStore; | ||
| import com.hedera.node.app.service.addressbook.impl.WritableAccountNodeRelStore; | ||
| import com.hedera.node.app.service.addressbook.impl.WritableNodeStore; | ||
| import com.hedera.node.app.service.addressbook.impl.records.NodeCreateStreamBuilder; | ||
| import com.hedera.node.app.service.addressbook.impl.validators.AddressBookValidator; | ||
| import com.hedera.node.app.service.entityid.NodeIdGenerator; | ||
| import com.hedera.node.app.service.token.ReadableAccountStore; | ||
| import com.hedera.node.app.spi.fees.FeeContext; | ||
| import com.hedera.node.app.spi.fees.Fees; | ||
|
|
@@ -90,8 +92,13 @@ | |
| final var accountNodeRelStore = storeFactory.writableStore(WritableAccountNodeRelStore.class); | ||
| final var accountStore = storeFactory.readableStore(ReadableAccountStore.class); | ||
| final var accountId = op.accountIdOrElse(AccountID.DEFAULT); | ||
|
|
||
| validateFalse(nodeStore.sizeOfState() >= nodeConfig.maxNumber(), MAX_NODES_CREATED); | ||
| final var maybeSystemTxnDispatchEntityNum = | ||
| handleContext.dispatchMetadata().getMetadata(SYSTEM_TXN_CREATION_ENTITY_NUM, Long.class); | ||
| final var maybeNodeIsInStateForSystemTxn = | ||
| isNodeInStateForSystemTxn(handleContext.dispatchMetadata(), handleContext.nodeIdGenerator(), nodeStore); | ||
| validateTrue( | ||
| maybeNodeIsInStateForSystemTxn || (nodeStore.sizeOfState() < nodeConfig.maxNumber()), | ||
| MAX_NODES_CREATED); | ||
| addressBookValidator.validateAccount( | ||
| accountId, accountStore, accountNodeRelStore, handleContext.expiryValidator()); | ||
| addressBookValidator.validateDescription(op.description(), nodeConfig); | ||
|
|
@@ -116,12 +123,24 @@ | |
| nodeBuilder.grpcProxyEndpoint(op.grpcProxyEndpoint()); | ||
| } | ||
|
|
||
| // Since nodes won't be removed from state, we can set the nodeId to the next available id | ||
| // in the state based on the size of the state. | ||
| final var node = nodeBuilder.nodeId(nodeStore.sizeOfState()).build(); | ||
| long nextNodeId; | ||
| Node node; | ||
|
|
||
| // If a system-dispatched transplant transaction for nodes in override network (non-prod environments) | ||
| // attempts to create a node that already exists in the state (even if marked as deleted), | ||
| // neither the highest node ID nor the entity count should be incremented. | ||
| if (maybeNodeIsInStateForSystemTxn) { | ||
| // Assign node id using the one provided by the system dispatch metadata | ||
| nextNodeId = maybeSystemTxnDispatchEntityNum.get(); | ||
| node = nodeBuilder.nodeId(nextNodeId).build(); | ||
| nodeStore.put(node); | ||
|
Check warning on line 136 in hedera-node/hedera-addressbook-service-impl/src/main/java/com/hedera/node/app/service/addressbook/impl/handlers/NodeCreateHandler.java
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do we know if the transplant didnt add any new nodes. (total nodes > current network) |
||
| } else { | ||
| // Assign node id using a dedicated generator to avoid reuse | ||
| nextNodeId = handleContext.nodeIdGenerator().newNodeId(); | ||
| node = nodeBuilder.nodeId(nextNodeId).build(); | ||
| nodeStore.putAndIncrementCount(node); | ||
| } | ||
|
|
||
| nodeStore.putAndIncrementCount(node); | ||
| // add account id relation | ||
| accountNodeRelStore.put(op.accountIdOrThrow(), node.nodeId()); | ||
|
|
||
| final var recordBuilder = handleContext.savepointStack().getBaseBuilder(NodeCreateStreamBuilder.class); | ||
|
|
@@ -141,4 +160,25 @@ | |
| calculator.addVerificationsPerTransaction(Math.max(0, feeContext.numTxnSignatures() - 1)); | ||
| return calculator.calculate(); | ||
| } | ||
|
|
||
| /** | ||
| * Determines if a system-dispatched node creation transaction targets a node ID | ||
| * that already exists in the current state. | ||
| * | ||
| * <p>If the dispatch metadata provides a node ID (as in system transactions), this method checks | ||
| * if that node ID is already present in the node store. If not, it uses the next node ID from the generator. | ||
| * | ||
| * @param metadata the dispatch metadata containing optional system transaction node ID | ||
| * @param nodeIdGenerator the generator for new node IDs | ||
| * @param nodeStore the store containing current node state | ||
| * @return {@code true} if the node ID (from metadata or generator) already exists in the state; {@code false} otherwise | ||
| */ | ||
| private boolean isNodeInStateForSystemTxn( | ||
| final HandleContext.DispatchMetadata metadata, | ||
| final NodeIdGenerator nodeIdGenerator, | ||
| final ReadableNodeStore nodeStore) { | ||
| final var systemTxnCreationNum = metadata.getMetadataIfPresent(SYSTEM_TXN_CREATION_ENTITY_NUM, Long.class); | ||
| final var nextNodeId = systemTxnCreationNum != null ? systemTxnCreationNum : nodeIdGenerator.peekAtNewNodeId(); | ||
| return nodeStore.get(nextNodeId) != null; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.