Experimental TechnologyThe Arkade Language is experimental technology in active development. All code and examples presented here are for exploration and proof of concept purposes only. Do not use in production environments.
Arkade Functions
Arkade Script provides a comprehensive set of built-in functions for common operations in Bitcoin smart contracts. These functions abstract away the complexity of Bitcoin Script while providing powerful capabilities for contract development.
Signature Verification
checkSig
Verifies a signature against a public key:
bool isValid = checkSig(signature, pubkey);
Parameters:
signature: The signature to verify
pubkey: The public key to verify against
Returns:
bool: True if the signature is valid, false otherwise
Example:
require(checkSig(userSig, user), "Invalid signature");
checkMultisig
Verifies multiple signatures against multiple public keys:
bool isValid = checkMultisig(pubkeys, signatures);
Parameters:
pubkeys: Array of public keys
signatures: Array of signatures
Returns:
bool: True if all signatures are valid, false otherwise
Example:
require(checkMultisig([alice, bob], [aliceSig, bobSig]), "Invalid multisig");
checkSigFromStack
Verifies a signature against a message and public key:
bool isValid = checkSigFromStack(signature, pubkey, message);
Parameters:
signature: The signature to verify
pubkey: The public key to verify against
message: The message that was signed
Returns:
bool: True if the signature is valid, false otherwise
Example:
bytes message = sha256(assetPair + int2bytes(price));
require(checkSigFromStack(oracleSig, oracle, message), "Invalid oracle signature");
Hash Functions
sha256
Computes the SHA-256 hash of data:
bytes32 hash = sha256(data);
Parameters:
Returns:
bytes32: The SHA-256 hash
Example:
require(sha256(preimage) == hash, "Invalid preimage");
ripemd160
Computes the RIPEMD-160 hash of data:
bytes20 hash = ripemd160(data);
Parameters:
Returns:
bytes20: The RIPEMD-160 hash
Example:
bytes20 pubkeyHash = ripemd160(sha256(pubkey));
hash160
Computes the Hash160 (SHA-256 followed by RIPEMD-160) of data:
bytes20 hash = hash160(data);
Parameters:
Returns:
bytes20: The Hash160 result
Example:
bytes20 pubkeyHash = hash160(pubkey);
hash256
Computes the double SHA-256 hash of data:
bytes32 hash = hash256(data);
Parameters:
Returns:
bytes32: The double SHA-256 hash
Example:
bytes32 txid = hash256(txdata);
Timelock Functions
checkLockTime
Verifies that the transaction’s locktime meets a requirement:
bool isValid = checkLockTime(locktime);
Parameters:
locktime: The minimum required locktime
Returns:
bool: True if the transaction’s locktime is greater than or equal to the specified locktime
Example:
require(checkLockTime(expiryTime), "Timelock not yet reached");
checkSequence
Verifies that the input’s sequence number meets a requirement:
bool isValid = checkSequence(sequence);
Parameters:
sequence: The minimum required sequence
Returns:
bool: True if the input’s sequence is greater than or equal to the specified sequence
Example:
require(checkSequence(relativeLocktime), "Relative timelock not yet reached");
Conversion Functions
int2bytes
Converts an integer to a byte array:
bytes intBytes = int2bytes(value);
Parameters:
value: The integer to convert
Returns:
bytes: The byte representation of the integer
Example:
bytes message = assetId + int2bytes(amount);
bytes2int
Converts a byte array to an integer:
int value = bytes2int(bytes);
Parameters:
bytes: The byte array to convert
Returns:
Example:
int amount = bytes2int(amountBytes);
Script Generation
new P2PKH
Creates a Pay-to-Public-Key-Hash (P2PKH) script:
bytes script = new P2PKH(pubkey);
Parameters:
pubkey: The public key to create the script for
Returns:
Example:
require(tx.outputs[0].scriptPubKey == new P2PKH(recipient), "Output not spendable by recipient");
new P2SH
Creates a Pay-to-Script-Hash (P2SH) script:
bytes script = new P2SH(redeemScript);
Parameters:
redeemScript: The redeem script to hash
Returns:
Example:
bytes redeemScript = /* complex script */;
require(tx.outputs[0].scriptPubKey == new P2SH(redeemScript), "Output not using correct P2SH");
new P2WPKH
Creates a Pay-to-Witness-Public-Key-Hash (P2WPKH) script:
bytes script = new P2WPKH(pubkey);
Parameters:
pubkey: The public key to create the script for
Returns:
Example:
require(tx.outputs[0].scriptPubKey == new P2WPKH(recipient), "Output not using P2WPKH");
new P2WSH
Creates a Pay-to-Witness-Script-Hash (P2WSH) script:
bytes script = new P2WSH(witnessScript);
Parameters:
witnessScript: The witness script to hash
Returns:
Example:
bytes witnessScript = /* complex script */;
require(tx.outputs[0].scriptPubKey == new P2WSH(witnessScript), "Output not using correct P2WSH");
new P2TR
Creates a Pay-to-Taproot (P2TR) script:
bytes script = new P2TR(internalKey, scriptTree);
Parameters:
internalKey: The internal key for the Taproot output
scriptTree (optional): The script tree for the Taproot output
Returns:
Example:
require(tx.outputs[0].scriptPubKey == new P2TR(internalKey, contractHash), "Output not using correct P2TR");
Key Functions
tweakKey
Tweaks a public key with a value:
pubkey tweakedKey = tweakKey(pubkey, tweak);
Parameters:
pubkey: The public key to tweak
tweak: The value to tweak with
Returns:
pubkey: The tweaked public key
Example:
pubkey expectedKey = tweakKey(internalKey, contractHash);
require(tx.outputs[0].scriptPubKey == new P2TR(expectedKey), "Output key not correctly tweaked");
aggregateKeys
Aggregates multiple public keys into a single key:
pubkey aggregatedKey = aggregateKeys(pubkeys);
Parameters:
pubkeys: Array of public keys to aggregate
Returns:
pubkey: The aggregated public key
Example:
pubkey multisigKey = aggregateKeys([alice, bob, charlie]);
Array Functions
length
Returns the length of an array:
int arrayLength = array.length;
Example:
require(pubkeys.length == signatures.length, "Mismatched array lengths");
concat
Concatenates two arrays:
bytes[] combined = concat(array1, array2);
Parameters:
array1: The first array
array2: The second array
Returns:
- Array containing all elements from both input arrays
Example:
bytes message = concat(header, payload);
Utility Functions
require
Enforces a condition, failing if it’s not met:
require(condition, "Error message");
Parameters:
condition: The condition to check
message (optional): Error message if the condition fails
Example:
require(amount > 0, "Amount must be positive");
min
Returns the minimum of two values:
Parameters:
a: First value
b: Second value
Returns:
- The smaller of the two values
Example:
int fee = min(calculatedFee, maxFee);
max
Returns the maximum of two values:
Parameters:
a: First value
b: Second value
Returns:
- The larger of the two values
Example:
int payout = max(minimumPayout, calculatedPayout);
Advanced Functions
verifyTaprootSignature
Verifies a Taproot signature:
bool isValid = verifyTaprootSignature(signature, pubkey, message, leafHash);
Parameters:
signature: The signature to verify
pubkey: The public key to verify against
message: The message that was signed
leafHash: The leaf hash for the Taproot script path
Returns:
bool: True if the signature is valid, false otherwise
Example:
require(verifyTaprootSignature(sig, key, msg, leafHash), "Invalid Taproot signature");
computeMerkleRoot
Computes a Merkle root from a list of hashes:
bytes32 root = computeMerkleRoot(hashes);
Parameters:
hashes: Array of hashes to include in the Merkle tree
Returns:
Example:
bytes32 expectedRoot = computeMerkleRoot(leafHashes);
require(contractRoot == expectedRoot, "Invalid Merkle root");
Conclusion
These built-in functions provide the building blocks for creating sophisticated Bitcoin smart contracts with Arkade Script. By combining these functions with the language’s syntax and type system, you can create secure and efficient contracts for a wide range of use cases.
For more advanced use cases, you may also need to use the new opcodes described in the Arkade Script documentation.