Skip to content
This repository was archived by the owner on Jul 23, 2024. It is now read-only.

Commit 5722c5a

Browse files
author
kale
authored
Merge pull request #268 from sirano11/validate_tx
add validateSender/FeePayer/Transaction.
2 parents 80c3eb4 + ec740fd commit 5722c5a

2 files changed

Lines changed: 1215 additions & 6 deletions

File tree

core/src/main/java/com/klaytn/caver/validator/Validator.java

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import com.klaytn.caver.account.*;
2020
import com.klaytn.caver.methods.response.AccountKey;
2121
import com.klaytn.caver.rpc.Klay;
22+
import com.klaytn.caver.transaction.AbstractFeeDelegatedTransaction;
23+
import com.klaytn.caver.transaction.AbstractTransaction;
2224
import com.klaytn.caver.utils.Utils;
2325
import com.klaytn.caver.wallet.keyring.SignatureData;
2426

@@ -154,7 +156,91 @@ public boolean validateSignedMessage(String message, List<SignatureData> signatu
154156
}
155157
}
156158

157-
private boolean validateWithAccountType(String address, IAccountKey accountKey, List<String> pubKeys, int role) {
159+
/**
160+
* Validates the sender of the transaction.<p>
161+
* This function compares the public keys of the account key of sender with the public keys recovered from signatures field.
162+
* <pre>Example :
163+
* {@code
164+
* ValueTransfer tx = caver.transaction.valueTransfer.create(...);
165+
* boolean isValid = caver.validator.validateSender(tx);
166+
* }
167+
* </pre>
168+
*
169+
* @param tx An instance of transaction to validate
170+
* @return boolean
171+
*/
172+
public boolean validateSender(AbstractTransaction tx) {
173+
try {
174+
//Loading Account Key.
175+
AccountKey accountKey = klay.getAccountKey(tx.getFrom()).send();
176+
if(accountKey.hasError()) {
177+
throw new RuntimeException("error code : " + accountKey.getError().getCode() + " error message : " + accountKey.getError().getMessage());
178+
}
179+
180+
List<String> publicKeys = tx.recoverPublicKeys();
181+
int role = tx.getType().contains("AccountUpdate") ? AccountKeyRoleBased.RoleGroup.ACCOUNT_UPDATE.getIndex() : AccountKeyRoleBased.RoleGroup.TRANSACTION.getIndex();
182+
183+
return validateWithAccountType(tx.getFrom(), accountKey.getResult().getAccountKey(), publicKeys, role);
184+
} catch(IOException e) {
185+
throw new RuntimeException("Failed to get AccountKey from Klaytn", e);
186+
}
187+
}
188+
189+
/**
190+
* Validates the fee payer in the transaction.<p>
191+
* This function compares the public keys of the account key of the fee payer with the public keys recovered from feePayerSignatures field.
192+
* <pre>Example :
193+
* {@code
194+
* ValueTransfer tx = caver.transaction.valueTransfer.create(...);
195+
* boolean isValid = caver.validator.validateSender(tx);
196+
* }
197+
* </pre>
198+
*
199+
* @param tx An instance of transaction to validate
200+
* @return boolean
201+
*/
202+
public boolean validateFeePayer(AbstractFeeDelegatedTransaction tx) {
203+
try {
204+
//Loading Account Key.
205+
AccountKey accountKey = klay.getAccountKey(tx.getFeePayer()).send();
206+
if(accountKey.hasError()) {
207+
throw new RuntimeException("error code : " + accountKey.getError().getCode() + " error message : " + accountKey.getError().getMessage());
208+
}
209+
210+
List<String> publicKeys = tx.recoverFeePayerPublicKeys();
211+
int role = AccountKeyRoleBased.RoleGroup.FEE_PAYER.getIndex();
212+
213+
return validateWithAccountType(tx.getFeePayer(), accountKey.getResult().getAccountKey(), publicKeys, role);
214+
} catch(IOException e) {
215+
throw new RuntimeException("Failed to get AccountKey from Klaytn", e);
216+
}
217+
}
218+
219+
/**
220+
* Validates a transaction.<p>
221+
* This function compares the public keys of the account key of sender with the public keys recovered from signatures field.<p>
222+
* If the transaction is fee-delegated with the `feePayerSignatures` variable inside, this function compares the public keys recovered from `feePayerSignatures` with the public keys of the fee payer.
223+
* <pre>Example
224+
* {@code
225+
* ValueTransfer tx = caver.transaction.valueTransfer.create(...);
226+
* boolean isValid = caver.validator.validateSender(tx);
227+
* }
228+
* </pre>
229+
*
230+
* @param tx An instance of transaction to validate.
231+
* @return boolean
232+
*/
233+
public boolean validateTransaction(AbstractTransaction tx) {
234+
boolean isValid = this.validateSender(tx);
235+
236+
if(isValid && tx instanceof AbstractFeeDelegatedTransaction) {
237+
isValid = this.validateFeePayer((AbstractFeeDelegatedTransaction)tx);
238+
}
239+
240+
return isValid;
241+
}
242+
243+
private boolean validateWithAccountType(String address, IAccountKey accountKey, List<String> pubKeys, int role) {
158244
// For accounts that have not yet been applied in Klaytn's state, the return value of `caver.rpc.klay.getAccountKey` is null.
159245
// In this case, the account's key has never been updated, so the logic is the same as in AccountKeyLegacy.
160246
if(accountKey == null) {

0 commit comments

Comments
 (0)