Skip to content

Commit

Permalink
Merge pull request #38 from avianlabs/keep-order-in-account-keys
Browse files Browse the repository at this point in the history
keep order in account keys
  • Loading branch information
wiyarmir authored Mar 4, 2024
2 parents b0e9a05 + ee5bcd4 commit 893f43d
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.avianlabs.solana.domain.core

public class AccountKeysList {
private val accounts: HashMap<String, AccountMeta> = HashMap()
private val accounts: LinkedHashMap<String, AccountMeta> = LinkedHashMap()

public fun add(accountMeta: AccountMeta) {
val key = accountMeta.publicKey.toString()
Expand Down Expand Up @@ -31,16 +31,18 @@ public class AccountKeysList {

public companion object {
private val metaComparator = Comparator<AccountMeta> { am1, am2 ->
val cmpSigner = if (am1.isSigner == am2.isSigner) 0 else if (am1.isSigner) -1 else 1
if (cmpSigner != 0) {
return@Comparator cmpSigner
// first sort by signer, then writable
if (am1.isSigner && !am2.isSigner) {
-1
} else if (!am1.isSigner && am2.isSigner) {
1
} else if (am1.isWritable && !am2.isWritable) {
-1
} else if (!am1.isWritable && am2.isWritable) {
1
} else {
0
}
val cmpkWritable =
if (am1.isWritable == am2.isWritable) 0 else if (am1.isWritable) -1 else 1
if (cmpkWritable != 0) {
cmpkWritable
} else cmpSigner.compareTo(cmpkWritable)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public class Message(
instructions: List<TransactionInstruction> = emptyList(),
) {

private val _accountKeys: AccountKeysList
private val _instructions: MutableList<TransactionInstruction>
private val _accountKeys: AccountKeysList = accountKeys
private val _instructions: MutableList<TransactionInstruction> = instructions.toMutableList()


public val accountKeys: List<AccountMeta>
Expand All @@ -21,11 +21,6 @@ public class Message(
public val instructions: List<TransactionInstruction>
get() = _instructions

init {
_accountKeys = accountKeys
_instructions = instructions.toMutableList()
}

private class MessageHeader {
var numRequiredSignatures: Byte = 0
var numReadonlySignedAccounts: Byte = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,65 @@
package net.avianlabs.solana.domain.core

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class AccountKeysListTest {
@Test
fun add_different_writable_flags_preserves_isSigner() {
val accountKeysList = AccountKeysList()
val accountMeta1 = AccountMeta(PublicKey.fromBase58("4rZoSK72jVaAW1ayZLrefdMPAAStRVhCfH1PSundaoNt"), false, true)
val accountMeta1 = AccountMeta(
publicKey = PublicKey.fromBase58("4rZoSK72jVaAW1ayZLrefdMPAAStRVhCfH1PSundaoNt"),
isSigner = false,
isWritable = true,
)

accountKeysList.add(accountMeta1)

val accountMeta2 = AccountMeta(PublicKey.fromBase58("4rZoSK72jVaAW1ayZLrefdMPAAStRVhCfH1PSundaoNt"), true, false)
val accountMeta2 = AccountMeta(
publicKey = PublicKey.fromBase58("4rZoSK72jVaAW1ayZLrefdMPAAStRVhCfH1PSundaoNt"),
isSigner = true,
isWritable = false,
)

accountKeysList.add(accountMeta2)

assertTrue(accountKeysList.list.size == 1)
assertTrue(accountKeysList.list[0].isSigner)
assertTrue(accountKeysList.list[0].isWritable)
}

@Test
fun account_order() {
val accountKeysList = AccountKeysList()

val meta = listOf(
AccountMeta(
publicKey = PublicKey.fromBase58("EtDXsqZ9Cgod7Z6j8cqu8fNMF7fu9txu2puHnxVY1wBk"),
isSigner = true,
isWritable = true,
),
AccountMeta(
publicKey = PublicKey.fromBase58("9JGhZqi4MbnVz424uJ6vqk9a1u359xg3nJekdjzzL4d5"),
isSigner = false,
isWritable = true,
),
AccountMeta(
publicKey = PublicKey.fromBase58("G8iheDY9bGix5qCXEitCExLcgZzZrEemngk9cbTR3CQs"),
isSigner = false,
isWritable = false,
),
)

accountKeysList.addAll(meta.shuffled())

assertEquals(
listOf(
PublicKey.fromBase58("EtDXsqZ9Cgod7Z6j8cqu8fNMF7fu9txu2puHnxVY1wBk"),
PublicKey.fromBase58("9JGhZqi4MbnVz424uJ6vqk9a1u359xg3nJekdjzzL4d5"),
PublicKey.fromBase58("G8iheDY9bGix5qCXEitCExLcgZzZrEemngk9cbTR3CQs"),
),
accountKeysList.list.map { it.publicKey }
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package net.avianlabs.solana.domain.core

import net.avianlabs.solana.domain.program.ComputeBudgetProgram
import net.avianlabs.solana.domain.program.TokenProgram
import kotlin.test.Test
import kotlin.test.assertEquals

class MessageTest {

@Test
fun account_keys_order() {
val transaction = Transaction()
.addInstruction(
TokenProgram.transferChecked(
source = PublicKey.fromBase58("9JGhZqi4MbnVz424uJ6vqk9a1u359xg3nJekdjzzL4d5"),
mint = PublicKey.fromBase58("G8iheDY9bGix5qCXEitCExLcgZzZrEemngk9cbTR3CQs"),
destination = PublicKey.fromBase58("3RfWpJnpr4DHxMDWfhqZRQ4acnQwM1HQXSvmgzzpz2K2"),
owner = PublicKey.fromBase58("EtDXsqZ9Cgod7Z6j8cqu8fNMF7fu9txu2puHnxVY1wBk"),
amount = 1u,
decimals = 1u,
)
)
.addInstruction(
ComputeBudgetProgram.setComputeUnitPrice(
microLamports = 1u,
)
)

transaction.message.accountKeys.map { println(it) }

assertEquals(
transaction.message.accountKeys,
listOf(
AccountMeta(
publicKey = PublicKey.fromBase58("EtDXsqZ9Cgod7Z6j8cqu8fNMF7fu9txu2puHnxVY1wBk"),
isSigner = true,
isWritable = false
),
AccountMeta(
publicKey = PublicKey.fromBase58("9JGhZqi4MbnVz424uJ6vqk9a1u359xg3nJekdjzzL4d5"),
isSigner = false,
isWritable = true
),
AccountMeta(
publicKey = PublicKey.fromBase58("3RfWpJnpr4DHxMDWfhqZRQ4acnQwM1HQXSvmgzzpz2K2"),
isSigner = false,
isWritable = true
),
AccountMeta(
publicKey = PublicKey.fromBase58("G8iheDY9bGix5qCXEitCExLcgZzZrEemngk9cbTR3CQs"),
isSigner = false,
isWritable = false
),
AccountMeta(
publicKey = PublicKey.fromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
isSigner = false,
isWritable = false
),
AccountMeta(
publicKey = PublicKey.fromBase58("ComputeBudget111111111111111111111111111111"),
isSigner = false,
isWritable = false
),
),
)
}
}

0 comments on commit 893f43d

Please sign in to comment.