|
19 | 19 | import com.klaytn.caver.account.*; |
20 | 20 | import com.klaytn.caver.methods.response.AccountKey; |
21 | 21 | import com.klaytn.caver.rpc.Klay; |
| 22 | +import com.klaytn.caver.transaction.AbstractFeeDelegatedTransaction; |
| 23 | +import com.klaytn.caver.transaction.AbstractTransaction; |
22 | 24 | import com.klaytn.caver.utils.Utils; |
23 | 25 | import com.klaytn.caver.wallet.keyring.SignatureData; |
24 | 26 |
|
@@ -154,7 +156,91 @@ public boolean validateSignedMessage(String message, List<SignatureData> signatu |
154 | 156 | } |
155 | 157 | } |
156 | 158 |
|
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) { |
158 | 244 | // For accounts that have not yet been applied in Klaytn's state, the return value of `caver.rpc.klay.getAccountKey` is null. |
159 | 245 | // In this case, the account's key has never been updated, so the logic is the same as in AccountKeyLegacy. |
160 | 246 | if(accountKey == null) { |
|
0 commit comments