Experimental Technology

The 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:

  • data: The data to hash

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:

  • data: The data to hash

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:

  • data: The data to hash

Returns:

  • bytes20: The Hash160 result

Example:

bytes20 pubkeyHash = hash160(pubkey);

hash256

Computes the double SHA-256 hash of data:

bytes32 hash = hash256(data);

Parameters:

  • data: The data to hash

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:

  • int: The integer value

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:

  • bytes: The P2PKH script

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:

  • bytes: The P2SH script

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:

  • bytes: The P2WPKH script

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:

  • bytes: The P2WSH script

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:

  • bytes: The P2TR script

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:

int minimum = min(a, b);

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:

int maximum = max(a, b);

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:

  • bytes32: The Merkle root

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.