Skip to content

Commit

Permalink
Actually use lookup accounts in integration tests and hence uncover a…
Browse files Browse the repository at this point in the history
… bug - the countUnsignedReadOnly accounts only refers to static accounts, not the lookup accounts. This was an incorrect assumption made during refactoring.
  • Loading branch information
ml-james committed Sep 27, 2024
1 parent 4f98e25 commit f336445
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void shouldCreateAddressLookupTable(final String messageEncoding)
solana.setMessageEncoding(messageEncoding);

solana.createAddressLookupTable("lookupTableAddress", "addressLookupTableAuthority", "payer");
solana.retrieveAddressLookupTable("lookupTableAddress");
solana.verifyAddressLookupTable("lookupTableAddress");
}

@ParameterizedMessageEncodingTest
Expand All @@ -40,7 +40,7 @@ void shouldExtendAddressLookupTable(final String messageEncoding)
"addressForLookupTable1, addressForLookupTable2, addressForLookupTable3"
);

solana.retrieveAddressLookupTable(
solana.verifyAddressLookupTable(
"lookupTableAddress",
"addressForLookupTable1, addressForLookupTable2, addressForLookupTable3"
);
Expand Down
5 changes: 0 additions & 5 deletions src/main/java/com/lmax/solana4j/encoding/AccountLookups.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,4 @@ public Set<PublicKey> getAccountsInLookupTables()
{
return accountsInLookupTables;
}

public int countUnsignedReadOnly()
{
return accountLookupEntries.stream().map(x -> x.getReadOnlyLookupEntrys().size()).mapToInt(Integer::intValue).sum();
}
}
2 changes: 0 additions & 2 deletions src/main/java/com/lmax/solana4j/encoding/SolanaAccounts.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ else if (!accountReference.isWriter())
}
}

countUnsignedReadOnly += accountLookups.countUnsignedReadOnly();

return new SolanaAccounts(
staticAccountReferences.stream().map(TransactionInstruction.AccountReference::account).collect(Collectors.toList()),
accountLookups.getAccountLookupEntrys(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,9 @@ public List<MessageVisitor.V0InstructionView> instructions()

private boolean isWriterStaticAccount(final int index)
{
final var unsignedReadOnlyLookupAccountsCount = accountLookups
.stream()
.map(x -> x.readOnlyTableIndexes().size())
.mapToInt(Integer::intValue)
.sum();

final var unsignedReadOnlyStaticAccountsCount = countAccountsUnsignedReadOnly() - unsignedReadOnlyLookupAccountsCount;
final var signedWriterStaticAccountsCount = countAccountsSigned() - countAccountsSignedReadOnly();
final var isSignerWriter = index < signedWriterStaticAccountsCount;
final var isNonSignerWriter = (index > (countAccountsSigned() - 1) && (index < (accountsView.staticAccounts().size() - unsignedReadOnlyStaticAccountsCount)));
final var isNonSignerWriter = (index >= countAccountsSigned() && (index < (accountsView.staticAccounts().size() - countAccountsUnsignedReadOnly())));

return isSignerWriter || isNonSignerWriter;
}
Expand Down
32 changes: 22 additions & 10 deletions src/test-support/java/com/lmax/solana4j/SolanaNodeDsl.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,23 @@ public void airdropSol(final String... args)
Waiter.waitFor(transactionFinalized(transactionSignature));
}

public void retrieveAddressLookupTable(final String... args)
public void verifyAddressLookupTable(final String... args)
{
final DslParams params = DslParams.create(
args,
new RequiredArg("lookupTableAddress"),
new OptionalArg("addresses").setAllowMultipleValues()
);

final TestPublicKey account = testContext.data(TestDataType.TEST_PUBLIC_KEY).lookup(params.value("lookupTableAddress"));

final AccountInfo accountInfo = Waiter.waitFor(isNotNull(() -> solanaDriver.getAccountInfo(account)));
final TestPublicKey lookupTableAddress = testContext.data(TestDataType.TEST_PUBLIC_KEY).lookup(params.value("lookupTableAddress"));

final List<PublicKey> expectedAddresses = stream(params.values("addresses"))
.map(address -> testContext.data(TestDataType.TEST_KEY_PAIR).lookup(address).getSolana4jPublicKey())
.collect(Collectors.toList());

final AddressLookupTable addressLookupTable = AddressLookupTableProgram.deserializeAddressLookupTable(account.getSolana4jPublicKey(), Base64.decode(accountInfo.getData().get(0)));
final AddressLookupTable addressLookupTable = storeAddressLookupTable(lookupTableAddress, params.value("lookupTableAddress"));

assertThat(addressLookupTable.getAddresses()).usingRecursiveComparison().isEqualTo(expectedAddresses);
testContext.data(TestDataType.ADDRESS_LOOKUP_TABLE).store(params.value("lookupTableAddress"), addressLookupTable);
}

public void createAddressLookupTable(final String... args)
Expand All @@ -122,13 +120,15 @@ public void createAddressLookupTable(final String... args)
final long recentSlot = solanaDriver.getSlot();

final ProgramDerivedAddress programDerivedAddress = AddressLookupTableProgram.deriveAddress(authority.getSolana4jPublicKey(), SolanaEncoding.slot(recentSlot));
final TestPublicKey address = new TestPublicKey(programDerivedAddress.address().bytes());
testContext.data(TestDataType.TEST_PUBLIC_KEY).store(params.value("lookupTableAddress"), address);
final TestPublicKey lookupTableAddress = new TestPublicKey(programDerivedAddress.address().bytes());
testContext.data(TestDataType.TEST_PUBLIC_KEY).store(params.value("lookupTableAddress"), lookupTableAddress);

// intermittency caused by slot not moving on to the next slot before including in the sent transaction
waitForSlot(recentSlot + 1);
final String transactionSignature = solanaDriver.createAddressLookupTable(programDerivedAddress, authority, payer, SolanaEncoding.slot(recentSlot));
Waiter.waitFor(transactionFinalized(transactionSignature));

storeAddressLookupTable(lookupTableAddress, params.value("lookupTableAddress"));
}

public void extendAddressLookupTable(final String... args)
Expand All @@ -142,7 +142,7 @@ public void extendAddressLookupTable(final String... args)
new OptionalArg("addressLookupTables").setAllowMultipleValues()
);

final TestPublicKey addressLookupTable = testContext.data(TestDataType.TEST_PUBLIC_KEY).lookup(params.value("lookupTableAddress"));
final TestPublicKey lookupTableAddress = testContext.data(TestDataType.TEST_PUBLIC_KEY).lookup(params.value("lookupTableAddress"));
final TestKeyPair authority = testContext.data(TestDataType.TEST_KEY_PAIR).lookup(params.value("authority"));
final TestKeyPair payer = testContext.data(TestDataType.TEST_KEY_PAIR).lookup(params.value("payer"));
final List<AddressLookupTable> addressLookupTables = params.valuesAsList("addressLookupTables").stream()
Expand All @@ -156,9 +156,11 @@ public void extendAddressLookupTable(final String... args)
addresses.add(testContext.data(TestDataType.TEST_PUBLIC_KEY).lookup(address));
}

final String transactionSignature = solanaDriver.extendAddressLookupTable(addressLookupTable, authority, payer, addresses, addressLookupTables);
final String transactionSignature = solanaDriver.extendAddressLookupTable(lookupTableAddress, authority, payer, addresses, addressLookupTables);

Waiter.waitFor(transactionFinalized(transactionSignature));

storeAddressLookupTable(lookupTableAddress, params.value("lookupTableAddress"));
}

public void waitForSlot(final String... args)
Expand Down Expand Up @@ -795,4 +797,14 @@ private Condition<TransactionData> transactionFinalized(final String transaction
{
return isNotNull(() -> solanaDriver.getTransactionResponse(transactionSignature).getTransaction());
}

private AddressLookupTable storeAddressLookupTable(final TestPublicKey lookupTableAddress, final String lookupTableAlias)
{
final AccountInfo accountInfo = Waiter.waitFor(isNotNull(() -> solanaDriver.getAccountInfo(lookupTableAddress)));
final AddressLookupTable addressLookupTable = AddressLookupTableProgram.deserializeAddressLookupTable(
lookupTableAddress.getSolana4jPublicKey(),
Base64.decode(accountInfo.getData().get(0)));
testContext.data(TestDataType.ADDRESS_LOOKUP_TABLE).store(lookupTableAlias, addressLookupTable);
return addressLookupTable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void checkSimpleUnsignedMessageHeader()
.expect("version header", (byte) 128)
.expect("count signed accounts", (byte) 3)
.expect("count signed read-only accounts", (byte) 1)
.expect("count unsigned read-only accounts", (byte) 2);
.expect("count unsigned read-only accounts", (byte) 1);
}

@Test
Expand All @@ -322,7 +322,7 @@ void checkComplexUnsignedMessageHeader()
.expect("version header", (byte) 128)
.expect("count signed accounts", (byte) 6)
.expect("count signed read-only accounts", (byte) 2)
.expect("count unsigned read-only accounts", (byte) 4);
.expect("count unsigned read-only accounts", (byte) 3);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ void nonSignerInLookupTableNoLongerInStaticAccounts()
}

@Test
void unsignedReadOnlyAccountReferenceInLookupTable()
void unsignedReadOnlyAccountReferenceInLookupTableNotIncludedInUnsignedReadOnlyCountOfMessage()
{
final SolanaAccount roUAccount = new SolanaAccount(ACCOUNT1);

Expand All @@ -568,7 +568,7 @@ void unsignedReadOnlyAccountReferenceInLookupTable()
lookupAccountsEqual(accounts.getAccountLookups(), lookupTableAddress, List.of(roUAccount));
accountLookupReadOnlyIndexEquals(accounts.getAccountLookups(), lookupTableAddress, roUAccount, 0);
flattenedAccountListEquals(accounts.getFlattenedAccountList(), List.of(RW_S_PAYER_ACCOUNT, RO_U_PROGRAM1_ACCOUNT, roUAccount));
countUnsignedReadOnlyEquals(accounts.getCountUnsignedReadOnly(), 2);
countUnsignedReadOnlyEquals(accounts.getCountUnsignedReadOnly(), 1);
countSignedReadOnlyEquals(accounts.getCountSignedReadOnly(), 0);
countSignedEquals(accounts.getCountSigned(), 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void correctlyReportCounts()

assertThat(messageView.countAccountsSigned()).isEqualTo(3);
assertThat(messageView.countAccountsSignedReadOnly()).isEqualTo(1);
assertThat(messageView.countAccountsUnsignedReadOnly()).isEqualTo(2);
assertThat(messageView.countAccountsUnsignedReadOnly()).isEqualTo(1);
}

@Test
Expand Down

0 comments on commit f336445

Please sign in to comment.