Closed sirlensalot closed 5 years ago
Some more context is: the actual endorsement here is that the two chains have the same version of the smart contract, as reflected by the module hash. Thus a smart contract on chain B can trustlessly validate that some smart contract on chain A has the same module hash.
Most of the time this is a reasonable assumption, and especially with a non-forked coin contract. However, since SPV happens over a span of transactions, it is well possible that a newer contract is verifying an older one's endorsement, which can be handled with the module-hash blessing system such that blessed versions will also be honored (that is, tried when the current module hash fails).
The inverse situation, verifying a newer endorsement, might require the newer endorsing version to specifically target a past module hash for compatibility with known deployments. It could even be argued that the oldest blessed hash should be used for endorsement unless otherwise specified, with a specific hash specification targeting a minimum compatible version (after all, spv interactions might become incompatible on some upgrade).
Example updated for proposal:
(defun delete-coin (delete-account create-chain-id create-account create-account-guard quantity)
(with-capability (TRANSFER)
(debit delete-account quantity)
(endorse-spv "TXOUT"
{ "create-chain-id": create-chain-id
, "create-account": create-account
... })))
(defun create-coin (proof)
(let ((outputs (at "outputs" (verify-spv "TXOUT" proof))))
(enforce (= 1 (length outputs)) "only one tx in outputs")
(bind (at 0 outputs)
{ "create-chain-id":= create-chain-id
, "create-account" := create-account
...} ...)))
A fascinating implication of this train of thought is the fact that "the ability to pair the return of one function call with another subsequent function call with some notion of continuation" sounds like pacts. Indeed, pacts could model this situation perfectly now, with yield
and resume
being supplied by SPV-specific replication, which would obviously have to serialize the closure too (at long last). To be continued ...
The specification for endorsement is now to leverage the trustlessness therein to automate cross-chain defpacts
with the following features and goals:
yield
becomes the main cross-chain mechanism. yield
provides the necessary requirements for an endorsed, SPV-recoverable receipt suitable for automatic verification. yield
as an overload [1]Thus a "cross-chain invocation" of yield
has the form (yield TARGET-CHAIN DATA)
. The data structure capturing a yield should be formalized to:
data Yield = Yield
{ _yData :: Object Name
, _yTarget :: Text -- or ChainId newtype in Pact
, _yEndorsement :: Hash
}
Endorsement is a hash of
_yData
(to assure data)_yTarget
(to assure target chain). Note #458 for better chain ID type.@spv-hash ["a5435a355fd45sgd54d35as"]
but for now the goal is maximum backward compat.Yield
replaces Term Name
in current PactExec
datatype (https://github.com/kadena-io/pact/blob/641542c16dfbd3806c4e646429e90027b1f3d07f/src/Pact/Types/Runtime.hs#L174).
Per changes in #451, will be part of an enhanced CommandResult
that will form the receipt, and thus recoverable from SPV. CommandResult
will also capture the module and defpact name as well as arguments as part of representing a continuation; the module hash will obviously be discovered using the continuation info.
Lastly, this should be accomplished in Pact as much as possible leaving just the shim for the backend, so that pact -s
can be a good testing ground (through basically validating the ChainId and otherwise saying "welp, it must be good"), .repl
tests can simply mock the chainId. Namely, endorsements is provided by Pact, and chainweb merely needs to consume the proof.
1 - The step
modifier entity
is tempting to overload, but it isn't meaningful on a first step (assuming the design labels the "target" (i.e., 2nd) step with the target chain -- could also label the "sending" step, and it's still cursed with this asymmetry). entity
currently indicates a "private" pact by having all steps labeled with entity values.
A final consideration is where "manual SPV", ie SPV that today would be supportable with spv-verify TYPE
, fits into the far more harmonious world of defpact
-driven SPV.
Proposals include:
Model any SPV interaction as a second (third,fourth) step of a Pact. The idea here is that "pact is everywhere", and the first step presumably occurred on some other network/chain/TEE. It's in fact no different than cross-chain pact here modulo the additional assurance of endorsements within Chainweb. "One day all steps will run in Pact, no matter where they execute"; at a minimum you'd want to mock the semantics of the source for FV purposes.
Endorsement, at least in the form of some kind of hash preimage or secret validation, seems flexible enough to support other auto-SPV endorsements if desired. For instance you could have an SPV only complete once you've written the preimage into the database, such that when the SPV arrives, the endorsement hash can be correctly built using that value.
However, expecting endorsement to be automatic puts a large burden on the runtime, and limits customization in Pact. As it is, defpact
-based SPV is hardcoded to "TXOUT", or "receipt-based SPV", and demands that the validating module be the same as the issuing.
Realizing now endorsements could be validated by other modules, as it's trivial to look up another module's hash and use the same logic ... but this requires ID'ing the module. ~Could add ModuleName
to the Yield
output pretty easily.~ Done, added the name of the defpact
, which enhances correctness in any case.
I think verify-spv
as specified is valuable, namely to offer "TX_IN" for inclusion proofs as a "hey who knows" and leave the door open for implementing other verifications. My worry is its a black box (which is why @buckie wanted all of SPV to be in-pact, to support building other SPVs at the smart-contract level; the argument for at least automatic defpact
SPV is cheap, fast, safe, brainless, ubiquitous, flexible, but for other SPVs building at smart-contract level is ideal, assuming its gas-efficient).
As per Emily, all done
UPDATE: this is now the discussion for automated SPV in
defpact
s viayield
, see below: https://github.com/kadena-io/pact/issues/443#issuecomment-480469325Burn/creates in chainweb use SPV to assure the create side, here's draft coin contract code:
However, there is no assurance that the result object obtained from
verify-spv
was actually emitted bydelete-coin
on the other chain. Somehow we need to prove that the coin contract emitted this.Proposal is to offer an
(endorse-spv type output)
operation to wrap results returned from some verifiable operation. The Pact runtime will store a special result value built from the hash of (TYPE,OUTPUT,calling-module-hash); this value is then encoded in some specialendorsement
field of the SPV-verified output object (e.g., in chainweb'sTransactionOutput
somewhere). It returns OUTPUT in order for that to be the recorded response to the call, to be recovered from the SPV output.On the recipient side,
(verify-spv type proof)
's backend will read the deserialized transactionoutput
and enforce thatendorsement
is populated. Ifendorsement
is populated, compute the hash of (TYPE,output
,calling-module-hash) and enforce that it equalsendorsement
.Design considerations:
(spv-verify "TXOUT" proof)
returning a list ofoutputs
, in practice the currentCommandResult
serialization only populates the last output term, soverify-spv
should only return one.endorse-spv
is creaky because it requires authors to call it in tail position with the actual function output, in the last term to execute. An alternate approach would be something like(endorse-spv tag value)
, allowingendorsement
to be a pair of TAG and the VALUE-based endorsement. This would relieve the requirement of "normal" output being the focus of spv proofs, but perhaps make the system less "visible".EDIT: going with the TAG approach above, which has nice legibility properties and further specializes the hash, but keeping the explicit operation in tail position.