Skip to content

Commit 4a6a9ab

Browse files
Merge conflicts
Signed-off-by: Ivan Kavaldzhiev <ivankavaldzhiev@gmail.com>
2 parents 854f897 + eded008 commit 4a6a9ab

28 files changed

Lines changed: 765 additions & 132 deletions

File tree

.github/workflows/acceptance.yaml

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ jobs:
4141
- BLOCK
4242
timeout-minutes: 40
4343
env:
44+
BASE_URL: "http://127.0.0.1:8081"
4445
BLOCK_NODE_CHART_VERSION: v0.20.1
4546
CONSENSUS_VERSION: v0.67.2-rc.2
47+
DEFAULT_DURATION: "3s"
48+
DEFAULT_GRACEFUL_STOP: "1s"
49+
DEFAULT_VUS: 2
4650
HELM_RELEASE_NAME: mirror-1
4751
MIRROR_NODE_VERSION: v0.141.0-rc1
4852
SOLO_CLUSTER_NAME: test
@@ -152,7 +156,7 @@ jobs:
152156
EOF
153157
fi
154158
155-
solo mirror node add --deployment "${SOLO_DEPLOYMENT}" -f mirror.yaml --cluster-ref kind-"${SOLO_CLUSTER_NAME}" --mirror-node-version "${MIRROR_NODE_VERSION}" --pinger
159+
solo mirror node add --deployment "${SOLO_DEPLOYMENT}" -f mirror.yaml --cluster-ref kind-"${SOLO_CLUSTER_NAME}" --mirror-node-version "${MIRROR_NODE_VERSION}" --pinger --enable-ingress
156160
157161
echo "Solo cluster setup completed successfully!"
158162
@@ -182,25 +186,38 @@ jobs:
182186
echo "${k6}=${value}" >> $GITHUB_ENV
183187
done
184188
189+
declare -A k6MapRestJava
190+
k6MapRestJava["DEFAULT_TOPIC"]="DEFAULT_TOPIC_WITH_FEE_ID"
191+
k6MapRestJava["PRECOMPILE"]="DEFAULT_ACCOUNT_ID_NFTS_ALLOWANCE_SPENDER"
192+
k6MapRestJava["DEFAULT_ACCOUNT_ID_BOB"]="DEFAULT_ACCOUNT_ID_AIRDROP_RECEIVER"
193+
194+
for key in "${!k6MapRestJava[@]}"; do
195+
k6="${k6MapRestJava[$key]}"
196+
value=$(grep -oP "^${key}=(\K.+)$" "$LOG_FILE" | tail -n 1 || true)
197+
echo "${k6}=${value}" >> $GITHUB_ENV
198+
done
199+
185200
- name: Install k6
186201
if: ${{ matrix.stream-type != 'BLOCK' }}
187202
uses: grafana/setup-k6-action@ffe7d7290dfa715e48c2ccc924d068444c94bde2 # v1
188203

189-
- name: Port forward web3
204+
- name: Run rest-java tests
190205
if: ${{ matrix.stream-type != 'BLOCK' }}
191-
run: |
192-
echo "Port forwarding 8080:80"
193-
kubectl port-forward "service/${HELM_RELEASE_NAME}-web3" -n "${SOLO_NAMESPACE}" 8080:80 &
206+
uses: grafana/run-k6-action@a15e2072ede004e8d46141e33d7f7dad8ad08d9d # v1
207+
env:
208+
DEFAULT_ACCOUNT_ID_NFTS_ALLOWANCE_OWNER: "0.0.1003"
209+
DEFAULT_ACCOUNT_ID_AIRDROP_SENDER: "0.0.1003"
210+
with:
211+
path: |
212+
./tools/k6/src/rest-java/apis.js
213+
debug: false
214+
flags: --quiet
194215

195216
- name: Run k6 web3 tests
196217
if: ${{ matrix.stream-type != 'BLOCK' }}
197218
uses: grafana/run-k6-action@a15e2072ede004e8d46141e33d7f7dad8ad08d9d # v1
198219
env:
199220
AMOUNT: "0000000000000000000000000000000000000000000000000000000000000001"
200-
BASE_URL: "http://127.0.0.1:8080"
201-
DEFAULT_DURATION: "3s"
202-
DEFAULT_GRACEFUL_STOP: "1s"
203-
DEFAULT_VUS: 2
204221
KEY_TYPE: "0000000000000000000000000000000000000000000000000000000000000001"
205222
RUN_COMPLEX_TESTS: "false"
206223
RUN_ESTIMATE_TESTS: "false"

common/src/main/java/org/hiero/mirror/common/domain/transaction/StateChangeContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,11 @@ private void processContractStorageChange(MapUpdateChange mapUpdate) {
233233

234234
private void processContractStorageChange(SlotKey slotKey, BytesValue valueWritten) {
235235
slotKey = normalize(slotKey);
236-
contractStorageChanges.put(slotKey, valueWritten);
236+
final var trimmed = DomainUtils.trim(valueWritten);
237+
contractStorageChanges.put(slotKey, trimmed);
237238
contractStorageChangesIndexed
238239
.computeIfAbsent(slotKey.getContractID(), c -> new ArrayList<>())
239-
.add(new SlotValue(slotKey.getKey(), valueWritten));
240+
.add(new SlotValue(slotKey.getKey(), trimmed));
240241
}
241242

242243
private void processNodeStateChange(MapUpdateChange mapUpdate) {

common/src/main/java/org/hiero/mirror/common/util/DomainUtils.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.google.common.primitives.Longs;
88
import com.google.protobuf.ByteOutput;
99
import com.google.protobuf.ByteString;
10+
import com.google.protobuf.BytesValue;
1011
import com.google.protobuf.Internal;
1112
import com.google.protobuf.UnsafeByteOperations;
1213
import com.hedera.services.stream.proto.HashObject;
@@ -339,6 +340,28 @@ public static byte[] trim(final byte[] data) {
339340
return ArrayUtils.subarray(data, i, data.length);
340341
}
341342

343+
public static ByteString trim(final ByteString data) {
344+
if (data == null || data.isEmpty() || data.byteAt(0) != 0) {
345+
return data;
346+
}
347+
348+
final byte[] value = DomainUtils.toBytes(data);
349+
final byte[] trimmed = trim(value);
350+
351+
return trimmed == value ? data : DomainUtils.fromBytes(trimmed);
352+
}
353+
354+
public static BytesValue trim(final BytesValue data) {
355+
if (data == null) {
356+
return null;
357+
}
358+
359+
final var value = data.getValue();
360+
final var trimmed = trim(value);
361+
362+
return trimmed == value ? data : BytesValue.of(trimmed);
363+
}
364+
342365
public static byte[] toEvmAddress(ContractID contractId) {
343366
if (contractId == null || ContractID.getDefaultInstance().equals(contractId)) {
344367
throw new InvalidEntityException("Invalid ContractID");

common/src/test/java/org/hiero/mirror/common/util/DomainUtilsTest.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import static org.junit.jupiter.params.provider.Arguments.arguments;
1313

1414
import com.google.protobuf.ByteString;
15+
import com.google.protobuf.BytesValue;
1516
import com.google.protobuf.Internal;
1617
import com.google.protobuf.UnsafeByteOperations;
1718
import com.hedera.services.stream.proto.HashObject;
@@ -43,7 +44,7 @@
4344
import org.junit.jupiter.params.provider.NullAndEmptySource;
4445
import org.junit.jupiter.params.provider.ValueSource;
4546

46-
class DomainUtilsTest {
47+
final class DomainUtilsTest {
4748

4849
private static final String ED25519_KEY = "60beee88a761e079f71b03b5fe041979369e96450a7455b203a2578c8a7d4852";
4950
private static final String ECDSA_384_KEY = "0000001365636473612d736861322d6e69737470333834000000086e697374703338"
@@ -501,6 +502,29 @@ void toSnakeCaseReturnsInputAsIsForBlankOrNull(final String input) {
501502
assertThat(DomainUtils.toSnakeCase(input)).isEqualTo(input);
502503
}
503504

505+
@Test
506+
void trimByteString() {
507+
assertThat(DomainUtils.trim((ByteString) null)).isNull();
508+
assertThat(DomainUtils.trim(ByteString.EMPTY)).isSameAs(ByteString.EMPTY);
509+
final var shouldNotTrim = ByteString.copyFrom(new byte[] {0x1, 0x2});
510+
assertThat(DomainUtils.trim(shouldNotTrim)).isSameAs(shouldNotTrim);
511+
final var shouldTrim = ByteString.copyFrom(new byte[] {0x0, 0x0, 0x1, 0x0, 0x2});
512+
final var expected = ByteString.copyFrom(new byte[] {0x1, 0x0, 0x2});
513+
assertThat(DomainUtils.trim(shouldTrim)).isEqualTo(expected);
514+
}
515+
516+
@Test
517+
void trimBytesValue() {
518+
assertThat(DomainUtils.trim((BytesValue) null)).isNull();
519+
final var emptyValue = BytesValue.of(ByteString.EMPTY);
520+
assertThat(DomainUtils.trim(emptyValue)).isSameAs(emptyValue);
521+
final var shouldNotTrim = BytesValue.of(ByteString.copyFrom(new byte[] {0x1, 0x2}));
522+
assertThat(DomainUtils.trim(shouldNotTrim)).isSameAs(shouldNotTrim);
523+
final var shouldTrim = BytesValue.of(ByteString.copyFrom(new byte[] {0x0, 0x0, 0x1, 0x0, 0x2}));
524+
final var expected = BytesValue.of(ByteString.copyFrom(new byte[] {0x1, 0x0, 0x2}));
525+
assertThat(DomainUtils.trim(shouldTrim)).isEqualTo(expected);
526+
}
527+
504528
@ParameterizedTest
505529
@MethodSource("provideByteArraysForTrim")
506530
void testTrim(byte[] input, byte[] expected) {

importer/src/main/java/org/hiero/mirror/importer/downloader/block/transformer/AbstractBlockTransactionTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ private void transformContractSlotUsage(
271271

272272
for (var slotRead : contractSlotUsage.getSlotReadsList()) {
273273
ByteString slot = null;
274-
var valueRead = slotRead.getReadValue();
274+
var valueRead = DomainUtils.trim(slotRead.getReadValue());
275275
var storageChangeBuilder = StorageChange.newBuilder().setValueRead(valueRead);
276276
if (slotRead.getIdentifierCase() == SlotRead.IdentifierCase.INDEX) {
277277
int index = slotRead.getIndex();

importer/src/main/java/org/hiero/mirror/importer/downloader/block/transformer/CryptoCreateTransformer.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import com.hedera.hapi.block.stream.output.protoc.TransactionOutput;
66
import com.hedera.hapi.block.stream.output.protoc.TransactionOutput.TransactionCase;
77
import jakarta.inject.Named;
8+
import org.apache.commons.lang3.ArrayUtils;
89
import org.hiero.mirror.common.domain.transaction.TransactionType;
910
import org.hiero.mirror.common.util.DomainUtils;
11+
import org.hiero.mirror.importer.util.Utility;
1012

1113
@Named
1214
final class CryptoCreateTransformer extends AbstractBlockTransactionTransformer {
@@ -23,16 +25,21 @@ protected void doTransform(BlockTransactionTransformation blockTransactionTransf
2325
.getTransactionBody()
2426
.getCryptoCreateAccount()
2527
.getAlias();
26-
if (alias.size() == DomainUtils.EVM_ADDRESS_LENGTH) {
27-
recordBuilder.setEvmAddress(alias);
28+
if (!alias.isEmpty() && alias.size() != DomainUtils.EVM_ADDRESS_LENGTH) {
29+
// This must be a synthetic transaction. The statechanges for its alias and evm address are in the top level
30+
// triggering crypto transfer transaction. However, there's no parent link to follow for statechanges
31+
// lookup. Instead, the evm address can be calculated from the alias.
32+
byte[] evmAddress = Utility.aliasToEvmAddress(DomainUtils.toBytes(alias));
33+
if (ArrayUtils.isNotEmpty(evmAddress)) {
34+
recordBuilder.setEvmAddress(DomainUtils.fromBytes(evmAddress));
35+
}
2836
}
2937

3038
var accountCreate = blockTransaction
3139
.getTransactionOutput(TransactionCase.ACCOUNT_CREATE)
3240
.map(TransactionOutput::getAccountCreate)
3341
.orElseThrow();
34-
var receiptBuilder = recordBuilder.getReceiptBuilder();
35-
receiptBuilder.setAccountID(accountCreate.getCreatedAccountId());
42+
recordBuilder.getReceiptBuilder().setAccountID(accountCreate.getCreatedAccountId());
3643
}
3744

3845
@Override

importer/src/main/java/org/hiero/mirror/importer/downloader/block/transformer/Utils.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,6 @@ static LogsBloomFilter bloomForAll(Collection<LogsBloomFilter> bloomFilters) {
5858
}
5959

6060
static byte[] leftPad32(ByteString topic) {
61-
byte[] bytes = DomainUtils.toBytes(topic);
62-
int length = bytes.length;
63-
if (length < TOPIC_SIZE_BYTES) {
64-
byte[] padded = new byte[TOPIC_SIZE_BYTES];
65-
System.arraycopy(bytes, 0, padded, TOPIC_SIZE_BYTES - length, length);
66-
return padded;
67-
}
68-
69-
return bytes;
61+
return DomainUtils.leftPadBytes(DomainUtils.toBytes(topic), TOPIC_SIZE_BYTES);
7062
}
7163
}

importer/src/test/java/org/hiero/mirror/importer/downloader/block/transformer/CryptoTransformerTest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
1010
import java.util.List;
1111
import java.util.stream.Stream;
12+
import org.bouncycastle.util.encoders.Hex;
1213
import org.hiero.mirror.common.domain.transaction.RecordItem;
1314
import org.hiero.mirror.importer.parser.domain.RecordItemBuilder.TransferType;
1415
import org.junit.jupiter.api.Test;
@@ -17,14 +18,18 @@
1718
import org.junit.jupiter.params.provider.EnumSource;
1819
import org.junit.jupiter.params.provider.MethodSource;
1920

20-
class CryptoTransformerTest extends AbstractTransformerTest {
21+
final class CryptoTransformerTest extends AbstractTransformerTest {
2122

2223
private static Stream<Arguments> provideAliasAndExpectedEvmAddress() {
24+
var ecDsaAlias = ByteString.copyFrom(
25+
Hex.decode("3a21029afbc3562d9ebb6e6a4d784fd7bf7389ea3047dd2a7ad3864192326388185387"));
26+
var evmAddressFromEcDsaAlias = ByteString.copyFrom(Hex.decode("5b718ea220b7784a8f4069b18506155f2ea28ef6"));
2327
var randomAlias = recordItemBuilder.bytes(20);
2428
return Stream.of(
2529
arguments(ByteString.EMPTY, ByteString.EMPTY),
2630
arguments(recordItemBuilder.key().toByteString(), ByteString.EMPTY),
27-
arguments(randomAlias, randomAlias));
31+
arguments(ecDsaAlias, evmAddressFromEcDsaAlias),
32+
arguments(randomAlias, ByteString.EMPTY));
2833
}
2934

3035
@ParameterizedTest

importer/src/test/java/org/hiero/mirror/importer/parser/domain/BlockTransactionBuilder.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import com.hederahashgraph.api.proto.java.TransactionBody;
7373
import com.hederahashgraph.api.proto.java.TransactionRecord;
7474
import jakarta.inject.Named;
75+
import java.security.SecureRandom;
7576
import java.time.Instant;
7677
import java.util.ArrayList;
7778
import java.util.Collections;
@@ -104,6 +105,7 @@
104105
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
105106
public class BlockTransactionBuilder {
106107

108+
private final SecureRandom random = new SecureRandom();
107109
private final RecordItemBuilder recordItemBuilder;
108110

109111
private static StateChanges buildFileIdStateChanges(RecordItem recordItem) {
@@ -799,7 +801,7 @@ private void convertContractStateChanges(
799801
// only read
800802
slotUsage.addSlotReads(SlotRead.newBuilder()
801803
.setKey(storageChange.getSlot())
802-
.setReadValue(storageChange.getValueRead())
804+
.setReadValue(leftPad(storageChange.getValueRead()))
803805
.build());
804806
} else {
805807
int count = contractStorageSlotCounts.compute(contractId, (k, v) -> v == null ? 1 : v + 1);
@@ -820,8 +822,8 @@ private void convertContractStateChanges(
820822
.setMapUpdate(MapUpdateChange.newBuilder()
821823
.setKey(mapChangeKey)
822824
.setValue(MapChangeValue.newBuilder()
823-
.setSlotValueValue(
824-
SlotValue.newBuilder().setValue(valueWritten.getValue())))
825+
.setSlotValueValue(SlotValue.newBuilder()
826+
.setValue(leftPad(valueWritten.getValue()))))
825827
.build()));
826828
} else {
827829
// deleted
@@ -882,6 +884,14 @@ private ByteString getEvmAddress(ContractID contractId) {
882884
return ByteString.EMPTY;
883885
}
884886

887+
private ByteString leftPad(ByteString value) {
888+
if (random.nextBoolean()) {
889+
return value;
890+
}
891+
892+
return DomainUtils.fromBytes(DomainUtils.leftPadBytes(DomainUtils.toBytes(value), 32));
893+
}
894+
885895
private Timestamp timestamp(long consensusTimestamp) {
886896
var instant = Instant.ofEpochSecond(0, consensusTimestamp);
887897
return Utility.instantToTimestamp(instant);

test/src/test/java/org/hiero/mirror/test/e2e/acceptance/client/AbstractNetworkClient.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,13 +211,15 @@ public void validateAddress(final String actualAddress) {
211211
: account.getAccountId().toEvmAddress());
212212
}
213213

214-
protected final <T> void deleteOrLogEntities(Collection<T> ids, Consumer<T> deleteAction) {
214+
// Returns "true" if the entities should be deleted
215+
protected final <T> boolean deleteOrLogEntities(Collection<T> ids, Consumer<T> deleteAction) {
215216
if (acceptanceTestProperties.isSkipEntitiesCleanup()) {
216217
logEntities();
217-
return;
218+
return false;
218219
}
219220

220221
deleteAll(ids, deleteAction);
222+
return true;
221223
}
222224

223225
protected void logEntities() {}

0 commit comments

Comments
 (0)