Skip to content

Commit

Permalink
Fix NPE in TokenWipe when using missing alias for an account (#9640)
Browse files Browse the repository at this point in the history
Signed-off-by: Neeharika-Sompalli <[email protected]>
  • Loading branch information
Neeharika-Sompalli authored Nov 2, 2023
1 parent e004066 commit a04ea16
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,11 @@ public void setStateView(final StateView view) {
}

protected EntityNum lookUpAlias(final ByteString alias) {
return view.aliases().get(alias);
final var entityNum = view.aliases().get(alias);
if (entityNum == null) {
return EntityNum.MISSING_NUM;
}
return entityNum;
}

protected EntityNum unaliased(final AccountID idOrAlias) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,23 @@ void looksUpAliases() {
assertEquals(EntityNum.fromLong(10L), subject.unaliased(asAliasAccount(alias)));
}

@Test
void lookUpMissingAliasDoesntReturnNull() {
final var stateView = mock(StateView.class);
final var alias = ByteString.copyFromUtf8("someString");
final Map<ByteString, EntityNum> accountsMap = new HashMap<>();
given(stateView.aliases()).willReturn(accountsMap);

final var op = ContractCallTransactionBody.newBuilder().build();
final var txn = buildTransactionFrom(
TransactionBody.newBuilder().setContractCall(op).build());
final var subject = SignedTxnAccessor.uncheckedFrom(txn);
subject.setStateView(stateView);

assertEquals(EntityNum.MISSING_NUM, subject.lookUpAlias(alias));
assertEquals(EntityNum.MISSING_NUM, subject.unaliased(asAliasAccount(alias)));
}

private Transaction signedCryptoCreateTxn() {
return buildTransactionFrom(cryptoCreateOp());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ public static HapiTokenWipe wipeTokenAccount(String token, String account, long
return new HapiTokenWipe(token, account, amount);
}

public static HapiTokenWipe wipeTokenAccountWithAlias(String token, ByteString alias, long amount) {
return new HapiTokenWipe(token, alias, amount);
}

public static HapiTokenWipe wipeTokenAccount(String token, String account, List<Long> serialNumbers) {
return new HapiTokenWipe(token, account, serialNumbers);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.hedera.services.bdd.spec.transactions.TxnUtils.suFrom;

import com.google.common.base.MoreObjects;
import com.google.protobuf.ByteString;
import com.hedera.node.app.hapi.fees.usage.BaseTransactionMeta;
import com.hedera.node.app.hapi.fees.usage.state.UsageAccumulator;
import com.hedera.node.app.hapi.fees.usage.token.TokenOpsUsage;
Expand All @@ -28,6 +29,7 @@
import com.hedera.services.bdd.spec.fees.AdapterUtils;
import com.hedera.services.bdd.spec.transactions.HapiTxnOp;
import com.hedera.services.bdd.spec.transactions.TxnUtils;
import com.hederahashgraph.api.proto.java.AccountID;
import com.hederahashgraph.api.proto.java.FeeData;
import com.hederahashgraph.api.proto.java.HederaFunctionality;
import com.hederahashgraph.api.proto.java.Key;
Expand All @@ -51,6 +53,7 @@ public class HapiTokenWipe extends HapiTxnOp<HapiTokenWipe> {
private long amount;
private final List<Long> serialNumbers;
private final SubType subType;
private ByteString alias = ByteString.EMPTY;

@Override
public HederaFunctionality type() {
Expand All @@ -72,6 +75,15 @@ public HapiTokenWipe(final String token, final String account, final List<Long>
this.subType = SubType.TOKEN_NON_FUNGIBLE_UNIQUE;
}

public HapiTokenWipe(final String token, final ByteString alias, final long amount) {
this.token = token;
this.account = null;
this.alias = alias;
this.amount = amount;
this.serialNumbers = new ArrayList<>();
this.subType = SubType.TOKEN_FUNGIBLE_COMMON;
}

@Override
protected HapiTokenWipe self() {
return this;
Expand All @@ -97,7 +109,12 @@ private FeeData usageEstimate(final TransactionBody txn, final SigValueObj svo)
@Override
protected Consumer<TransactionBody.Builder> opBodyDef(final HapiSpec spec) throws Throwable {
final var tId = TxnUtils.asTokenId(token, spec);
final var aId = TxnUtils.asId(account, spec);
final AccountID aId;
if (!alias.isEmpty()) {
aId = AccountID.newBuilder().setAlias(alias).build();
} else {
aId = TxnUtils.asId(account, spec);
}
final TokenWipeAccountTransactionBody opBody = spec.txns()
.<TokenWipeAccountTransactionBody, TokenWipeAccountTransactionBody.Builder>body(
TokenWipeAccountTransactionBody.class, b -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.tokenFreeze;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.tokenUnfreeze;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.wipeTokenAccount;
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.wipeTokenAccountWithAlias;
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.moving;
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.movingUnique;
import static com.hedera.services.bdd.spec.utilops.CustomSpecAssert.allRunFor;
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed;
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.withOpContext;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_FROZEN_FOR_TOKEN;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_KYC_NOT_GRANTED_FOR_TOKEN;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.CANNOT_WIPE_TOKEN_TREASURY_ACCOUNT;
Expand All @@ -63,9 +65,8 @@
import static com.hederahashgraph.api.proto.java.TokenType.NON_FUNGIBLE_UNIQUE;

import com.google.protobuf.ByteString;
import com.hedera.services.bdd.junit.HapiTestSuite;
import com.hedera.services.bdd.spec.HapiSpec;
import com.hedera.services.bdd.spec.utilops.UtilVerbs;
import com.hedera.services.bdd.spec.keys.KeyFactory;
import com.hedera.services.bdd.suites.HapiSuite;
import com.hederahashgraph.api.proto.java.TokenSupplyType;
import com.hederahashgraph.api.proto.java.TokenType;
Expand All @@ -74,7 +75,7 @@
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Assertions;

@HapiTestSuite
// @HapiTestSuite
public class TokenManagementSpecs extends HapiSuite {

private static final Logger log = LogManager.getLogger(TokenManagementSpecs.class);
Expand Down Expand Up @@ -286,6 +287,7 @@ public HapiSpec wipeAccountFailureCasesWork() {
return defaultHapiSpec("WipeAccountFailureCasesWork")
.given(
newKeyNamed(multiKey),
newKeyNamed("alias").type(KeyFactory.KeyType.SIMPLE),
cryptoCreate("misc").balance(0L),
cryptoCreate(TOKEN_TREASURY).balance(0L))
.when(
Expand Down Expand Up @@ -317,7 +319,16 @@ public HapiSpec wipeAccountFailureCasesWork() {
wipeTokenAccount(wipeableToken, TOKEN_TREASURY, 1)
.hasKnownStatus(CANNOT_WIPE_TOKEN_TREASURY_ACCOUNT),
wipeTokenAccount(anotherWipeableToken, "misc", 501).hasKnownStatus(INVALID_WIPING_AMOUNT),
wipeTokenAccount(anotherWipeableToken, "misc", -1).hasPrecheck(INVALID_WIPING_AMOUNT));
wipeTokenAccount(anotherWipeableToken, "misc", -1).hasPrecheck(INVALID_WIPING_AMOUNT),
withOpContext((spec, opLog) -> {
final var key = spec.registry().getKey("alias");
final var alias = key.hasECDSASecp256K1() ? key.getECDSASecp256K1() : key.getEd25519();
allRunFor(
spec,
wipeTokenAccountWithAlias(unwipeableToken, alias, 1)
.signedBy(GENESIS)
.hasKnownStatus(INVALID_ACCOUNT_ID));
}));
}

public HapiSpec kycMgmtFailureCasesWork() {
Expand Down Expand Up @@ -439,7 +450,7 @@ private HapiSpec fungibleCommonMaxSupplyReachWork() {
.then(
getTxnRecord(SHOULD_NOT_APPEAR).showsNoTransfers(),
getAccountBalance(TOKEN_TREASURY).hasTokenBalance(FUNGIBLE_TOKEN, 0),
UtilVerbs.withOpContext((spec, opLog) -> {
withOpContext((spec, opLog) -> {
var mintNFT = getTxnRecord(SHOULD_NOT_APPEAR);
allRunFor(spec, mintNFT);
var receipt = mintNFT.getResponseRecord().getReceipt();
Expand Down

0 comments on commit a04ea16

Please sign in to comment.