mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-26 23:19:07 +00:00
Let a contract emit transactions from its own pseudo-account
checkSign rejects every pseudo-account when BatchV1_1 is enabled, but emitted transactions need BatchV1_1 to skip the signature check. So no contract could emit anything. Allow a contract pseudo-account on inner transactions, and make emitBuiltTxn and emitTxn reject a transaction whose Account is not the running contract's account. Without that check, a contract could emit an unsigned transaction from any account.
This commit is contained in:
@@ -929,11 +929,16 @@ Transactor::checkSign(
|
||||
|
||||
if ((view.rules().enabled(featureLendingProtocol) ||
|
||||
view.rules().enabled(featureBatchV1_1) || view.rules().enabled(fixCleanup3_3_0)) &&
|
||||
isPseudoAccount(sle))
|
||||
isPseudoAccount(sle) && !(parentBatchId && sle->isFieldPresent(sfContractID)))
|
||||
{
|
||||
// Pseudo-accounts can't sign transactions. This check is gated on a
|
||||
// few different amendments so that it takes effect as soon as any of
|
||||
// them is activated.
|
||||
//
|
||||
// A contract's pseudo-account is the exception for inner transactions:
|
||||
// the contract emits them, and the emit host functions allow only the
|
||||
// running contract's own account. A Batch can't use this, because its
|
||||
// BatchSigners are checked without a parentBatchId.
|
||||
return tefBAD_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,6 +973,11 @@ ContractHostFunctionsImpl::emitBuiltTxn(std::uint32_t const& index)
|
||||
return std::unexpected(HostFunctionError::SubmitTxnFailure);
|
||||
}
|
||||
|
||||
// Inner transactions skip the signature check, so a contract may emit
|
||||
// only from its own account.
|
||||
if (stx->getAccountID(sfAccount) != contractCtx.result.contractAccount)
|
||||
return std::unexpected(HostFunctionError::SubmitTxnFailure);
|
||||
|
||||
// Use a persistent emit view that is seeded with the
|
||||
// transactor's pending state changes (balances, consumed
|
||||
// sequence, etc.) so that each emitted transaction validates
|
||||
@@ -1040,6 +1045,10 @@ ContractHostFunctionsImpl::emitTxn(std::shared_ptr<STTx const> const& stxPtr)
|
||||
return std::unexpected(HostFunctionError::SubmitTxnFailure);
|
||||
}
|
||||
|
||||
// See emitBuiltTxn: a contract may emit only from its own account.
|
||||
if (txPtr->getAccountID(sfAccount) != contractCtx.result.contractAccount)
|
||||
return std::unexpected(HostFunctionError::SubmitTxnFailure);
|
||||
|
||||
// Use a persistent emit view seeded with the transactor's
|
||||
// pending state, and do a full apply() for each emission
|
||||
// (see emitBuiltTxn for detailed rationale).
|
||||
|
||||
Reference in New Issue
Block a user