From ca2aba6c6a3172790b94e7d8f310084f1b65670f Mon Sep 17 00:00:00 2001 From: Steven Sheehy <17552371+steven-sheehy@users.noreply.github.com> Date: Mon, 20 Jan 2020 11:20:25 -0600 Subject: [PATCH] Fix parsing ConsensusCreateTopic with existing autorenew account (#502) * Fix parsing ConsensusCreateTopic with existing autorenew account Signed-off-by: Steven Sheehy * Fix mirror_api db permissions Signed-off-by: Steven Sheehy * Bump versions to v0.5.2 Signed-off-by: Steven Sheehy --- hedera-mirror-coverage/pom.xml | 2 +- hedera-mirror-datagenerator/pom.xml | 2 +- hedera-mirror-grpc/pom.xml | 2 +- hedera-mirror-importer/pom.xml | 2 +- .../mirror/importer/domain/Entities.java | 3 +- .../importer/domain/EntityTypeEnum.java | 36 ++++++++++++++ .../parser/record/RecordFileLogger.java | 2 + .../parser/record/RecordFileParser.java | 6 +-- .../V1.17.5__fix_mirror_api_permissions.sql | 3 ++ .../record/RecordFileLoggerTopicTest.java | 49 +++++++++++++++++-- .../repository/EntityRepositoryTest.java | 6 +-- hedera-mirror-protobuf/pom.xml | 2 +- hedera-mirror-rest/package-lock.json | 2 +- hedera-mirror-rest/package.json | 2 +- hedera-mirror-rest/pom.xml | 2 +- hedera-mirror-test/pom.xml | 2 +- pom.xml | 2 +- 17 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/EntityTypeEnum.java create mode 100644 hedera-mirror-importer/src/main/resources/db/migration/V1.17.5__fix_mirror_api_permissions.sql diff --git a/hedera-mirror-coverage/pom.xml b/hedera-mirror-coverage/pom.xml index ac8288fde31..20021eebbfc 100644 --- a/hedera-mirror-coverage/pom.xml +++ b/hedera-mirror-coverage/pom.xml @@ -11,7 +11,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 diff --git a/hedera-mirror-datagenerator/pom.xml b/hedera-mirror-datagenerator/pom.xml index 59a1c242d44..5653e50ac12 100644 --- a/hedera-mirror-datagenerator/pom.xml +++ b/hedera-mirror-datagenerator/pom.xml @@ -11,7 +11,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 diff --git a/hedera-mirror-grpc/pom.xml b/hedera-mirror-grpc/pom.xml index 1178ea20f7b..d42e941fb26 100644 --- a/hedera-mirror-grpc/pom.xml +++ b/hedera-mirror-grpc/pom.xml @@ -11,7 +11,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 diff --git a/hedera-mirror-importer/pom.xml b/hedera-mirror-importer/pom.xml index 6378f1fb0e7..0f496cf5fcf 100644 --- a/hedera-mirror-importer/pom.xml +++ b/hedera-mirror-importer/pom.xml @@ -13,7 +13,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 diff --git a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/Entities.java b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/Entities.java index e02f1c3e6f6..814169602b9 100644 --- a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/Entities.java +++ b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/Entities.java @@ -20,7 +20,6 @@ * ‍ */ -import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -54,7 +53,7 @@ public class Entities { @Column(name = "fk_entity_type_id") private Integer entityTypeId; - @ManyToOne(cascade = CascadeType.ALL) + @ManyToOne private Entities autoRenewAccount; private Long autoRenewPeriod; diff --git a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/EntityTypeEnum.java b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/EntityTypeEnum.java new file mode 100644 index 00000000000..58c869e865b --- /dev/null +++ b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/domain/EntityTypeEnum.java @@ -0,0 +1,36 @@ +package com.hedera.mirror.importer.domain; + +/*- + * ‌ + * Hedera Mirror Node + * ​ + * Copyright (C) 2019 Hedera Hashgraph, LLC + * ​ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on 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. + * ‍ + */ + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum EntityTypeEnum { + + ACCOUNT(1), + CONTRACT(2), + FILE(3), + TOPIC(4); + + private final int id; +} diff --git a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileLogger.java b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileLogger.java index 9b57cacae37..b48737ecfb1 100644 --- a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileLogger.java +++ b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileLogger.java @@ -245,6 +245,7 @@ public static void storeRecord(Transaction transaction, TransactionRecord txReco body = TransactionBody.parseFrom(transaction.getBodyBytes()); } + log.trace("Storing transaction body: {}", () -> Utility.printProtoMessage(body)); long initialBalance = 0; Entities entity = null; Entities proxyEntity = null; @@ -469,6 +470,7 @@ public static void storeRecord(Transaction transaction, TransactionRecord txReco if (proxyEntity != null) { entity.setProxyAccountId(proxyEntity.getId()); } + entity.setAutoRenewAccount(createEntity(entity.getAutoRenewAccount())); entity = entityRepository.save(entity); sqlInsertTransaction.setLong(F_TRANSACTION.CUD_ENTITY_ID.ordinal(), entity.getId()); } else { diff --git a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileParser.java b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileParser.java index 55fd3dc5053..b5bf45ad39e 100644 --- a/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileParser.java +++ b/hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/parser/record/RecordFileParser.java @@ -197,15 +197,15 @@ private boolean loadRecordFile(String fileName, String previousFileHash, String TransactionRecord txRecord = TransactionRecord.parseFrom(rawBytes); try { - RecordFileLogger.storeRecord(transaction, txRecord, rawBytes); - if (log.isTraceEnabled()) { log.trace("Transaction = {}, Record = {}", Utility .printProtoMessage(transaction), Utility.printProtoMessage(txRecord)); } else { - log.debug("Stored transaction with consensus timestamp {}", () -> Utility + log.debug("Storing transaction with consensus timestamp {}", () -> Utility .printProtoMessage(txRecord.getConsensusTimestamp())); } + + RecordFileLogger.storeRecord(transaction, txRecord, rawBytes); } finally { // TODO: Refactor to not parse TransactionBody twice DataCase dc = Utility.getTransactionBody(transaction).getDataCase(); diff --git a/hedera-mirror-importer/src/main/resources/db/migration/V1.17.5__fix_mirror_api_permissions.sql b/hedera-mirror-importer/src/main/resources/db/migration/V1.17.5__fix_mirror_api_permissions.sql new file mode 100644 index 00000000000..a1b0a9479c0 --- /dev/null +++ b/hedera-mirror-importer/src/main/resources/db/migration/V1.17.5__fix_mirror_api_permissions.sql @@ -0,0 +1,3 @@ +alter default privileges in schema public grant select on tables to ${api-user}; + +grant select on all tables in schema public to ${api-user}; diff --git a/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/parser/record/RecordFileLoggerTopicTest.java b/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/parser/record/RecordFileLoggerTopicTest.java index cfbdb6a8828..1663dfb1bec 100644 --- a/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/parser/record/RecordFileLoggerTopicTest.java +++ b/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/parser/record/RecordFileLoggerTopicTest.java @@ -47,6 +47,7 @@ import com.hedera.mirror.importer.TestUtils; import com.hedera.mirror.importer.TopicIdConverter; import com.hedera.mirror.importer.domain.Entities; +import com.hedera.mirror.importer.domain.EntityTypeEnum; import com.hedera.mirror.importer.domain.TopicMessage; import com.hedera.mirror.importer.domain.Transaction; import com.hedera.mirror.importer.util.Utility; @@ -54,7 +55,6 @@ public class RecordFileLoggerTopicTest extends AbstractRecordFileLoggerTest { static final String TRANSACTION_MEMO = "transaction memo"; - static final int TOPIC_ENTITY_TYPE_ID = 4; static final String NODE_ID = "0.0.3"; static final String TRANSACTION_ID = "0.0.9999-123456789"; @@ -110,7 +110,33 @@ void createTopicTestNulls() throws Exception { .returns("".getBytes(), from(Entities::getSubmitKey)) .returns("", from(Entities::getMemo)) .returns(false, from(Entities::isDeleted)) - .returns(TOPIC_ENTITY_TYPE_ID, from(Entities::getEntityTypeId)); + .returns(EntityTypeEnum.TOPIC.getId(), from(Entities::getEntityTypeId)); + } + + // https://github.com/hashgraph/hedera-mirror-node/issues/501 + @Test + void createTopicTestExistingAutoRenewAccount() throws Exception { + Entities autoRenewAccount = createEntity(100L, EntityTypeEnum.ACCOUNT); + var topicId = 200L; + var consensusTimestamp = 2_000_000L; + var responseCode = ResponseCodeEnum.SUCCESS; + var transaction = createCreateTopicTransaction(null, null, null, autoRenewAccount.getEntityNum(), null); + var transactionRecord = createTransactionRecord(TopicID.newBuilder().setTopicNum(topicId) + .build(), null, null, consensusTimestamp, responseCode); + + RecordFileLogger.storeRecord(transaction, transactionRecord); + RecordFileLogger.completeFile("", ""); + + var entity = entityRepository.findByPrimaryKey(0L, 0L, topicId).get(); + assertTransactionInRepository(responseCode, consensusTimestamp, entity.getId()); + assertEquals(4L, entityRepository.count()); // Node, payer, topic, autorenew + assertThat(entity) + .returns("".getBytes(), from(Entities::getKey)) + .returns("".getBytes(), from(Entities::getSubmitKey)) + .returns("", from(Entities::getMemo)) + .returns(false, from(Entities::isDeleted)) + .returns(EntityTypeEnum.TOPIC.getId(), from(Entities::getEntityTypeId)) + .returns(autoRenewAccount, from(Entities::getAutoRenewAccount)); } @Test @@ -160,6 +186,9 @@ void updateTopicTest(@ConvertWith(TopicIdConverter.class) TopicID topicId, long // Store topic to be updated. var topic = createTopicEntity(topicId, expirationTimeSeconds, expirationTimeNanos, adminKey, submitKey, memo, autoRenewAccount, autoRenewPeriod); + if (topic.getAutoRenewAccount() != null) { + topic.setAutoRenewAccount(entityRepository.save(topic.getAutoRenewAccount())); + } entityRepository.save(topic); var responseCode = ResponseCodeEnum.SUCCESS; @@ -265,6 +294,9 @@ void updateTopicTestPartialUpdates(@ConvertWith(TopicIdConverter.class) TopicID // Store topic to be updated. var topic = createTopicEntity(topicId, expirationTimeSeconds, expirationTimeNanos, adminKey, submitKey, memo, autoRenewAccount, autoRenewPeriod); + if (topic.getAutoRenewAccount() != null) { + topic.setAutoRenewAccount(entityRepository.save(topic.getAutoRenewAccount())); + } entityRepository.save(topic); // Setup the expected entity. @@ -561,6 +593,15 @@ private TransactionBody.Builder createTransactionBody() { .setMemo(TRANSACTION_MEMO); } + private Entities createEntity(long num, EntityTypeEnum entityType) { + Entities entities = new Entities(); + entities.setEntityShard(0L); + entities.setEntityRealm(0L); + entities.setEntityNum(num); + entities.setEntityTypeId(entityType.getId()); + return entityRepository.save(entities); + } + private Entities createTopicEntity(TopicID topicId, Long expirationTimeSeconds, Integer expirationTimeNanos, Key adminKey, Key submitKey, String memo, Long autoRenewAccount, Long autoRenewPeriod) { @@ -573,7 +614,7 @@ private Entities createTopicEntity(TopicID topicId, Long expirationTimeSeconds, autoRenewEntity.setEntityShard(topic.getEntityShard()); autoRenewEntity.setEntityRealm(topic.getEntityRealm()); autoRenewEntity.setEntityNum(autoRenewAccount); - autoRenewEntity.setEntityTypeId(1); + autoRenewEntity.setEntityTypeId(EntityTypeEnum.ACCOUNT.getId()); topic.setAutoRenewAccount(autoRenewEntity); } if (autoRenewPeriod != null) { @@ -589,7 +630,7 @@ private Entities createTopicEntity(TopicID topicId, Long expirationTimeSeconds, topic.setSubmitKey(submitKey.toByteArray()); } topic.setMemo(memo); - topic.setEntityTypeId(TOPIC_ENTITY_TYPE_ID); + topic.setEntityTypeId(EntityTypeEnum.TOPIC.getId()); return topic; } diff --git a/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/repository/EntityRepositoryTest.java b/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/repository/EntityRepositoryTest.java index dfa983d0653..1b8323200fb 100644 --- a/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/repository/EntityRepositoryTest.java +++ b/hedera-mirror-importer/src/test/java/com/hedera/mirror/importer/repository/EntityRepositoryTest.java @@ -37,6 +37,7 @@ void findByPrimaryKey() { autoRenewAccount.setEntityShard(0L); autoRenewAccount.setEntityRealm(0L); autoRenewAccount.setEntityNum(101L); + autoRenewAccount = entityRepository.save(autoRenewAccount); Entities proxyEntity = new Entities(); proxyEntity.setEntityTypeId(entityTypeId); @@ -60,11 +61,6 @@ void findByPrimaryKey() { entity.setSubmitKey("SubmitKey".getBytes()); entity = entityRepository.save(entity); - assertThat(entityRepository.findByPrimaryKey(autoRenewAccount.getEntityShard(), - autoRenewAccount.getEntityRealm(), autoRenewAccount.getEntityNum())) - .get() - .isEqualToIgnoringGivenFields(autoRenewAccount, "id"); - assertThat(entityRepository .findByPrimaryKey(entity.getEntityShard(), entity.getEntityRealm(), entity.getEntityNum())) .get() diff --git a/hedera-mirror-protobuf/pom.xml b/hedera-mirror-protobuf/pom.xml index 00a714649eb..23c18e6cd68 100644 --- a/hedera-mirror-protobuf/pom.xml +++ b/hedera-mirror-protobuf/pom.xml @@ -11,7 +11,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 diff --git a/hedera-mirror-rest/package-lock.json b/hedera-mirror-rest/package-lock.json index 475ea9bd905..a1d79363244 100644 --- a/hedera-mirror-rest/package-lock.json +++ b/hedera-mirror-rest/package-lock.json @@ -1,6 +1,6 @@ { "name": "hedera-mirror-rest", - "version": "0.5.1", + "version": "0.5.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/hedera-mirror-rest/package.json b/hedera-mirror-rest/package.json index cfbae9565a5..580c249007a 100644 --- a/hedera-mirror-rest/package.json +++ b/hedera-mirror-rest/package.json @@ -1,6 +1,6 @@ { "name": "hedera-mirror-rest", - "version": "0.5.1", + "version": "0.5.2", "description": "Hedera Mirror Node REST API", "main": "server.js", "scripts": { diff --git a/hedera-mirror-rest/pom.xml b/hedera-mirror-rest/pom.xml index 3c14e71c532..597465ab962 100644 --- a/hedera-mirror-rest/pom.xml +++ b/hedera-mirror-rest/pom.xml @@ -11,7 +11,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 diff --git a/hedera-mirror-test/pom.xml b/hedera-mirror-test/pom.xml index 1d77f10f86d..8b088e6cf04 100644 --- a/hedera-mirror-test/pom.xml +++ b/hedera-mirror-test/pom.xml @@ -12,7 +12,7 @@ hedera-mirror-node com.hedera - 0.5.1 + 0.5.2 diff --git a/pom.xml b/pom.xml index 6fa143e82c3..90afbb7aa78 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.hedera hedera-mirror-node - 0.5.1 + 0.5.2 Hedera Mirror Node mirrors data from Hedera nodes and serves it via an API 2019 4.0.0