Welcome to this introduction to some more advanced Pact built-in functions.
In this guide, we will go through and explain specific built-in functions that are listed in the pact reference page.
Simple Payment Verification
The quick explanation of the
verify-spv function can be found here.
verify-spv takes some blob, a binary data type, provided by the user and runs code on it that would be too expensive to do in pact. Thus, in the statement
(verify-spv "ETH"), "ETH" has code in the chainweb-node binary to validate that the data is well-formed and returns a normal Pact object with all of the data. It is NOT an oracle; it is a tool that an oracle would use to guarantee data integrity.
Here is example code using the chain relay to validate a proof that the sender has retrieved from infura.
You can simulate any protocol desired. However, getting a protocol added to Chainweb requires support in the Chainweb binary and is a hard fork. Therefore, the community would need to spearhead by opening a pull request for a KIP, Kadena Improvement Process. For instance, to support BTC proofs, a KIP would be opened to add
verify-spv "BTC" to discuss and specify what is needed. Afterwards, the Haskell support would need to be implemented and released with a Chainweb version upgrade.
Currently Chainweb supports "ETH" and "TXOUT" only (github).
TXOUT is the same as what is used for crosschain, but should not be used for "once-and-only-once" which demands using a cross-chain defpact to enforce. TXOUT can be used for "broadcast" of e.g. a price feed to other chains.
Documentation for understanding capabilities can be found here.
The capability built-in functions can be found here.
Before diving into managed capabilities, it is important to understand the difference between managed and unmanaged capabilities. Capabilities are never "changed" since they are only granted by
with-capability. In addition to defining a capability, managed capabilities also define a "resource" that is decreased whenever the associated capability is granted.
Think of it like this, stateless capabilities are granted by
with-capability and demanded by
require-capability. Managed capabilities setup an initial "resource" by
install-capability, then deduct from the resource, granted by
with-capability, and are demanded by
install-capability is unique to managed capabilities while
with-capability does double duty.
with-capability essentially is two separate operations composed together in the managed case:
;; You write this:
(install-capability (TRANSFER FROM TO PROVIDED))
(with-capability (TRANSFER FROM TO REQUESTED) EXPR)
;; But what it does internally is more like this:
(install-capability (TRANSFER FROM TO) PROVIDED)
(if (already-granted-p (TRANSFER FROM TO))
(consume-resource (TRANSFER FROM TO) REQUESTED
(with-capability (TRANSFER FROM TO) EXPR)))
You can see here that
(TRANSFER FROM TO) identifies the capability - in both the managed and unmanaged cases. The extra parameter relating to the resource is what's new in the managed case. The fact that it gets passed as an argument in
(TRANSFER FROM TO AMOUNT) to both
with-capability is just a syntactic convenience.
Now lets take a look at the TRANSFER managed capability to get a better understanding.
@managed keyword identifies the argument referring to the resource parameter. In the case of
TRANSFER, this is the
amount argument, as declared by:
@managed amount TRANSFER_mgr
This also states that
TRANSFER_mgr will receive two arguments related to the amount:
- The current amount of the resource
- The proposed amount to be deducted by the call to
(defun TRANSFER_mgr:decimal (current:decimal requested:decimal)
amount argument passed is the initial amount of the resource. For
amount argument is the amount of resource being requested before the capability can be granted. In that case, the current amount that is passed as the first argument to the management function comes from the current state of the Pact evaluator.
@managed allows for only a single argument, but lists and objects are valid arguments too. For example, you could provide a list of names as the "resource" and write a management function that removes names from the list as they are "used." If you wanted a single managed capability to manage multiple resources, you could use an object instead.
The managed capability feature is most commonly used by coin contracts to govern transfer amounts.
The manager function has the job of confirming that sufficient resource exists and deducting from the resource. It is called whenever
with-capability is used and the capability has not yet been granted.
select built-in function can be found here.
select function is able to pull information from a table under specific conditions.
This is an example of finding people in a table with a single condition, having "Fatima" as their first or last name.
(select people ['firstName,'lastName] (where 'name (= "Fatima")))
But, what if you want to use multiple clauses to get a more specific result.
In this example, you can use the following format to find someone with the name "Fatima" that is older than 40.
(select people ['firstName,'lastName] (and? (where 'name (= "Fatima")) (where 'age (> 40))))