Please note
Since this blog was published a lot has happened. The Hooks Amendment is now running on a public testnet and has a public "Builder" where you (devs) can code Hooks and deploy them to the testnet, straight from your browser.
If you haven't already read the previous two blogs please do so first:
- Hooked #1: Smart Contracts on the XRP ledger
- Hooked #2: Hooks & Security (Smart Contracts on the XRP ledger)
Hooked #3: Tech Preview Release
This is another technical blog about the upcoming Hooks Amendment for the XRP Ledger. After months of discussing, tinkering, designing, discussing some more, building (99% Richard, hats off to him!), testing, etc. we (the people at XRPL Labs) are really excited to publish this blog, source code, sample hooks & a docker container so you can run your own local Hooks-enabled XRPL.
Get the Tech Preview running with Docker
π π² Here be dragons! We want to stress this is a tech preview it is not indicative of the final Hooks Amendment nor has it been optimised. The purpose of the preview is to demonstrate what Hooks will be able to do and how they will work in general.
To run the container interactively use:
# Run the docker container, and call it 'xrpld-hooks' | |
docker run -dit --name xrpld-hooks richardah/xrpld-hooks-tech-preview | |
# Open an interactive shell (bash) in the 'xrpld-hooks' container | |
docker exec -it xrpld-hooks /bin/bash |
If you want to play around, it makes sense to open two terminals, one with the logs generated by rippled (to see the result/logging of what you execute), and one to issue your commands.
To set up a second terminal to view the log: open a new terminal window on your system and run:
docker exec -it xrpld-hooks tail -f log |
This will show you the trace log of xrpld as it runs, which will be important for knowing if your transactions fail or succeed and what actions the hooks take.
Interacting with the Docker
After following the above steps you will be inside a shell inside the container. Rippled will already be running with the correct settings and the Hooks amendment enabled.
When you execute something in the docker container, you'll do so from the path:
/opt/rippled-hooks
(inside the container)
This path contains the contents of this folder from the Github repository.
Let's play with hooks
This is where you read the Hooks Tech Preview README.md. This README.md exists inside the Docker container, and can be found in the Github repository. This Readme contains instructions on building, installing and interacting with the example hooks. Every hook folder contains a hook written in C that can be built to a WebAssembly Hook, to be installed with a node (javascript) file inside the folder.
The sample hooks included are:
-
accept
- This hook is a minimum example hook. -
carbon
- Installing this hook causes the account to send a 1% carbon-offset txn each time another txn is sent from the account. -
firewall
- Installing this hook causes transactions from blacklisted accounts to be rejected Installing is a two step process, first create the blacklist storage account and install the blacklist, next install the firewall hook on the protected account. -
liteacc
- Installing this hook causes the account to become a multi-party pool account with each user acquiring a unique dest tag with which they can receive funds on the account.
Source Code
The work-in-progress repository for Hooks has been opened to the public:
Hooks Public Testnet + Documentation
Please see Hooks Testnet V3 for faucet + documentation + explorer + builder.
The XRP Ledger
The XRP Ledger is a decentralized cryptographic ledger powered by a network of peer-to-peer nodes. The XRP Ledger uses a novel Byzantine Fault Tolerant consensus algorithm to settle and record transactions in a secure distributed database without a central operator.
XRP
XRP is a public, counterparty-free asset native to the XRP Ledger, and is designed to bridge the many different currencies in use worldwide. XRP is traded on the open-market and is available for anyone to access. The XRP Ledger was created in 2012 with a finite supply of 100 billion units of XRP. Its creators gifted 80 billion XRP to a company, now called Ripple, to develop the XRP Ledger and its ecosystem. Ripple uses XRP to help build the Internet of Value, ushering in a worldβ¦
Hook API
The Hook API establishes several conventions to reduce friction for hook developers:
1. Naming Convention
Hooks are named in the following way:
noun [ _ ( adjective | noun#2 ) ][ _verb ]
adjective
, noun#2
and verb
are optional. If not specified the verb is implicitly get
. This may look confusing at first but it is intuitive after some examples:
state()
means 'get state'
And
state_set()
means 'set state'
And
state_foreign()
means "get foreign state" e.g. the state of a hook from another account.
Where possible the leading noun indicates the subject of the API, e.g. state
but to avoid turning the API into spaghetti the leading noun can also be a group of only loosely related APIs e.g. util
.
2. Parameter Convention
Hooks can only pass integer values back to xrpld
. However this includes pointers within its own memory.
- Pointers are named according to what
xrpld
is expected to do with the pointer. For example ifxrpld
is expected to write to the pointer it will be namedwrite_ptr
. - Pointers are always followed by a byte length indicating the size of the buffer to read or write to/from. This parameter is named in the same convention as above e.g.
write_len
. -
If there are multiple pointers of the same type a leading character indicating the name is used to disambiguate them. E.g. a key and data set of pointer-length pairs would look like this:
kread_ptr
,kread_len
,dread_ptr
,dread_len
If there are writing pointers they always come at the start of the parameter list.
If there are non-pointer parameters they always come at the end of the parameter list.
3. Return Values
All Hook APIs return int64_t. If the return value is non-negative it is a success. Typically a positive integer reflects the number of bytes read or written (depending on the API) or the amount of actions taken. However in some cases (e.g util_subfield
) the return value of the API is encoded into a positive int64_t.
If the return value is negative it is always one of the well-defined error codes. At time of writing these are:
#define OUT_OF_BOUNDS -1 // could not read or write to a pointer to provided by hook | |
#define INTERNAL_ERROR -2 // eg directory is corrupt | |
#define TOO_BIG -3 // something you tried to store was too big | |
#define TOO_SMALL -4 // something you tried to store or provide was too small | |
#define DOESNT_EXIST -5 // something you requested wasn't found | |
#define NO_FREE_SLOTS -6 // when trying to load an object there is a maximum of 255 slots | |
#define INVALID_ARGUMENT -7 // self explanatory | |
#define ALREADY_SET -8 // returned when a one-time parameter was already set by the hook | |
#define PREREQUISITE_NOT_MET -9 // returned if a required param wasn't set before calling | |
#define FEE_TOO_LARGE -10 // returned if the attempted operation would result in an absurd fee | |
#define EMISSION_FAILURE -11 // returned if an emitted tx was not accepted by rippled | |
#define TOO_MANY_NONCES -12 // a hook has a maximum of 256 nonces | |
#define TOO_MANY_EMITTED_TXN -13 // a hook has emitted more than its stated number of emitted txn | |
#define NOT_IMPLEMENTED -14 // an api was called that is reserved for a future version | |
#define INVALID_ACCOUNT -15 // an api expected an account id but got something else | |
#define GUARD_VIOLATION -16 // a guarded loop or function iterated over its maximum | |
#define INVALID_FIELD -17 // the field requested is returning sfInvalid | |
#define PARSE_ERROR -18 // hook asked hookapi to parse something the contents of which was invalid |
4. Hook API Function List
The best way to view the API function list is by reading the header comments: hookapi.h
Next Blog
We will be releasing further blogs discussing design choices and development progress over the coming weeks and months in the lead-up to a live Hooks Testnet.
Please check the other blogs, the source & README's and ... just a little more patience as we're on track for a Q1 public testnet release :)
Discussion
Discussions: here Β»
Top comments (0)