mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
Revised ScalaDocs of DAML engine to make security relevant assumptions explicit (#16555)
CHANGE_LOG_BEGIN CHANGE_LOG_END
This commit is contained in:
parent
c423e8d151
commit
b967ef3e6d
@ -75,31 +75,26 @@ class Engine(val config: EngineConfig = Engine.StableConfig) {
|
||||
|
||||
def info = new EngineInfo(config)
|
||||
|
||||
/** Executes commands `cmds` under the authority of `submitters`, with additional readers `readAs`,
|
||||
* and returns one of the following:
|
||||
/** Interprets a sequence of commands `cmds` to the corresponding `SubmittedTransaction` and `Tx.Metadata`.
|
||||
* Requests data required during the interpretation (such as the contract or package corresponding to a given id)
|
||||
* through the `Result` subclasses.
|
||||
*
|
||||
* The resulting transaction (if any) meets the following properties:
|
||||
* <ul>
|
||||
* <li> `ResultDone(tx)` if `cmds` could be successfully executed, where `tx` is the resulting transaction.
|
||||
* The transaction `tx` conforms to the Daml model consisting of the packages that have been supplied via
|
||||
* `ResultNeedPackage.resume` to this [[Engine]].
|
||||
* The transaction `tx` is internally consistent.
|
||||
* </li>
|
||||
* <li> `ResultNeedContract(contractId, resume)` if the contract referenced by `contractId` is needed to execute
|
||||
* `cmds`.
|
||||
* </li>
|
||||
* <li> `ResultNeedPackage(packageId, resume)` if the package referenced by `packageId` is needed to execute `cmds`.
|
||||
* </li>
|
||||
* <li> `ResultError` if the execution of `cmds` fails.
|
||||
* The execution may fail due to an error during Daml evaluation (e.g. execution of "abort") or
|
||||
* because the caller has not provided a required contract instance or package.
|
||||
* </li>
|
||||
* <li>The transaction is well-typed and conforms to the DAML model described by the packages supplied via `ResultNeedPackage`.
|
||||
* In particular, each contract created by the transaction meets the ensures clauses of the underlying template.</li>
|
||||
* <li>The transaction paired with `submitters` is well-authorized according to the ledger model.</li>
|
||||
* <li>The transaction is annotated with the packages used during interpretation.</li>
|
||||
* </ul>
|
||||
*
|
||||
* [[transactionSeed]] is the master hash used to derive node and contractId discriminator.
|
||||
* If left undefined, no discriminator will be generated.
|
||||
*
|
||||
* This method does perform authorization checks
|
||||
*
|
||||
* The resulting transaction is annotated with packages required to validate it.
|
||||
* @param submitters the parties authorizing the root actions (both read and write) of the resulting transaction
|
||||
* ("committers" according to the ledger model)
|
||||
* @param readAs the parties authorizing the root actions (only read, but no write) of the resulting transaction
|
||||
* @param cmds the commands to be interpreted
|
||||
* @param disclosures contracts to be used as input contracts of the transaction;
|
||||
* contract data may come from an untrusted source and will therefore be validated during interpretation.
|
||||
* @param participantId a unique identifier (of the underlying participant) used to derive node and contractId discriminators
|
||||
* @param submissionSeed the master hash used to derive node and contractId discriminators
|
||||
*/
|
||||
def submit(
|
||||
submitters: Set[Party],
|
||||
@ -130,19 +125,21 @@ class Engine(val config: EngineConfig = Engine.StableConfig) {
|
||||
} yield tx -> meta.copy(submissionSeed = Some(submissionSeed))
|
||||
}
|
||||
|
||||
/** Behaves like `submit`, but it takes a single command argument.
|
||||
/** Behaves like `submit`, but it takes a single `ReplayCommand` (instead of `ApiCommands`) as input.
|
||||
* It can be used to reinterpret partially an already interpreted transaction.
|
||||
*
|
||||
* If the command would fail with an unhandled exception, we return a transaction containing a
|
||||
* single rollback node. (This is achieving by compiling with `unsafeCompileForReinterpretation`
|
||||
* which wraps the command with a catch-everything exception handler.)
|
||||
*
|
||||
* [[nodeSeed]] is the seed of the Create and Exercise node as generated during submission.
|
||||
* If undefined the contract IDs are derive using V0 scheme.
|
||||
* The value of [[nodeSeed]] does not matter for other kind of nodes.
|
||||
*
|
||||
* The reinterpretation does not recompute the package dependencies, so the field `usedPackages` in the
|
||||
* `Tx.MetaData` component of the output is always set to `empty`.
|
||||
*
|
||||
* @param nodeSeed the seed of the root node as generated during submission.
|
||||
* If undefined the contract IDs are derive using V0 scheme.
|
||||
* The value does not matter for other kind of nodes.
|
||||
* @param submissionTime the submission time used to compute contract IDs
|
||||
* @param ledgerEffectiveTime the ledger effective time used as a result of `getTime` during reinterpretation
|
||||
*/
|
||||
def reinterpret(
|
||||
submitters: Set[Party],
|
||||
|
@ -69,11 +69,15 @@ sealed trait Result[+A] extends Product with Serializable {
|
||||
|
||||
final case class ResultInterruption[A](continue: () => Result[A]) extends Result[A]
|
||||
|
||||
/** Indicates that the command (re)interpretation was successful.
|
||||
*/
|
||||
final case class ResultDone[A](result: A) extends Result[A]
|
||||
object ResultDone {
|
||||
val Unit: ResultDone[Unit] = new ResultDone(())
|
||||
}
|
||||
|
||||
/** Indicates that the command (re)interpretation has failed.
|
||||
*/
|
||||
final case class ResultError(err: Error) extends Result[Nothing]
|
||||
object ResultError {
|
||||
def apply(packageError: Error.Package.Error): ResultError =
|
||||
@ -93,8 +97,12 @@ object ResultError {
|
||||
* To resume the computation, the caller must invoke `resume` with the following argument:
|
||||
* <ul>
|
||||
* <li>`Some(contractInstance)`, if the caller can dereference `acoid` to `contractInstance`</li>
|
||||
* <li>`None`, if the caller is unable to dereference `acoid`
|
||||
* <li>`None`, if the caller is unable to dereference `acoid`</li>
|
||||
* </ul>
|
||||
*
|
||||
* The caller of `resume` has to ensure that the contract instance passed to `resume` is a contract instance that
|
||||
* has previously been associated with `acoid` by the engine.
|
||||
* The engine does not validate the given contract instance.
|
||||
*/
|
||||
final case class ResultNeedContract[A](
|
||||
acoid: ContractId,
|
||||
@ -105,17 +113,37 @@ final case class ResultNeedContract[A](
|
||||
* To resume the computation, the caller must invoke `resume` with the following argument:
|
||||
* <ul>
|
||||
* <li>`Some(package)`, if the caller can dereference `packageId` to `package`</li>
|
||||
* <li>`None`, if the caller is unable to dereference `packageId`
|
||||
* <li>`None`, if the caller is unable to dereference `packageId`</li>
|
||||
* </ul>
|
||||
*
|
||||
* It depends on the engine configuration whether the engine will validate the package provided to `resume`.
|
||||
* If validation is switched off, it is the callers responsibility to provide a valid package corresponding to `packageId`.
|
||||
*/
|
||||
final case class ResultNeedPackage[A](packageId: PackageId, resume: Option[Package] => Result[A])
|
||||
extends Result[A]
|
||||
|
||||
/** Intermediate result indicating that the contract id corresponding to a key is required to complete the computation.
|
||||
* To resume the computation, the caller must invoke `resume` with the following argument:
|
||||
* <ul>
|
||||
* <li>`Some(contractId)`, if `key` is currently assigned to `contractId`</li>
|
||||
* <li>`None`, if `key` is unassigned</li>
|
||||
* </ul>
|
||||
*
|
||||
* The caller of `resume` has to ensure that any contract id passed to `resume` has previously been associated with
|
||||
* a contract with `key` as a key.
|
||||
* Other than that, the caller does not need to validate the data passed to `resume`. In particular, it may pass
|
||||
* the id of an archived contract to `resume`.
|
||||
* It may also provide `None` to `resume` when the `key` is actually assigned.
|
||||
*/
|
||||
final case class ResultNeedKey[A](
|
||||
key: GlobalKeyWithMaintainers,
|
||||
resume: Option[ContractId] => Result[A],
|
||||
) extends Result[A]
|
||||
|
||||
/** TODO: https://github.com/digital-asset/daml/issues/15882
|
||||
* add ScalaDoc explaining the impact of the answers and the responsibilities of the caller.
|
||||
* (Similarly as for the other subclasses of Result.)
|
||||
*/
|
||||
final case class ResultNeedAuthority[A](
|
||||
holding: Set[Party],
|
||||
requesting: Set[Party],
|
||||
|
Loading…
Reference in New Issue
Block a user