Register
Registers are a high level data type in the Autonomi Network. Which means they are a client side construct built on top of the lower level native data types. Registers are a 32 bytes mutable memory unit with all versions history accessible.
key-addressed: Network address is derived from a BLS public key
Size: 32 bytes of content per entry
Mutable but immutable history: Register old entries are kept forever but the register can be updated with new entries endlessly.
Pay to update: Register updates are paid for, but cheaper than creation.
Signed: Owned and signed by a key for cryptographic verification
Client Methods
register_get Retrieves a register from the network by its address.
register_create Creates and uploads a new register for a payment. Returns the total cost and the register's address.
register_update Updates an existing register with new content for a payment. The old content is kept in the history.
register_cost Estimates the storage cost for a register.
register_history Retrieves the history of a register.
API helpers for registers:
register_key_from_name Creates a new BLS key deriving it from a name and a base key. This is used to be able to create multiple registers with the same key (and different names). cf bls key derivation
register_value_from_bytes Makes sure the content fits in 32 bytes.
Examples
use autonomi::Client;
use autonomi::client::payment::PaymentOption;
use autonomi::SecretKey;
use eyre::Result;
async fn register_example() -> Result<()> {
// initialize a local client and test wallet
let client = Client::init_local().await?;
let wallet = get_funded_wallet();
let main_key = SecretKey::random();
// create a register key from a name and our main key
let register_key = Client::register_key_from_name(&main_key, "register1");
// estimate the cost of the register
let cost = client.register_cost(®ister_key.public_key()).await?;
// create the register
let content = Client::register_value_from_bytes(b"Hello, World!")?;
let (_cost, addr) = client
.register_create(®ister_key, content, PaymentOption::from(&wallet))
.await?;
// let the network replicate the register
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
// get the register
let value = client.register_get(&addr).await?;
assert_eq!(value, content);
// update the register
let content2 = Client::register_value_from_bytes(b"你好世界")?;
client
.register_update(®ister_key, content2, PaymentOption::from(&wallet))
.await?;
// let the network replicate the updates
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
let all = client.register_history(&addr).collect().await?;
assert_eq!(all.len(), 2);
assert_eq!(all[0], content);
assert_eq!(all[1], content2);
Ok(())
}from autonomi_client import Client, Wallet, EVMNetwork, PaymentOption, SecretKey
import asyncio
async def register_example():
# Initialize client and wallet
client = await Client.init_local()
wallet = Wallet.new_from_private_key(
EVMNetwork(True),
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
)
payment = PaymentOption.wallet(wallet)
# Generate keys
main_key = SecretKey.random()
register_key = Client.register_key_from_name(main_key, "my-counter")
# Create register content (max 32 bytes)
initial_content = Client.register_value_from_bytes(b"counter: 0")
# Check cost before creating
cost = await client.register_cost(register_key.public_key())
print(f"Register creation cost: {cost} AttoTokens")
# Create the register
creation_cost, address = await client.register_create(
register_key, initial_content, payment)
print(f"Register created at: {address.to_hex()}")
# Wait for network replication
await asyncio.sleep(5)
# Read current value
current_value = await client.register_get(address)
print(f"Current value: {current_value}")
# Update the register
new_content = Client.register_value_from_bytes(b"counter: 1")
update_cost = await client.register_update(register_key, new_content, payment)
print(f"Update cost: {update_cost} AttoTokens")
# Wait for replication
await asyncio.sleep(5)
# Get updated value
updated_value = await client.register_get(address)
print(f"Updated value: {updated_value}")
# Get complete history
history = client.register_history(address)
all_versions = await history.collect()
print(f"History has {len(all_versions)} versions:")
for i, version in enumerate(all_versions):
print(f" Version {i}: {version}")
# Run the example
asyncio.run(register_example())import { Client, Wallet, Network, PaymentOption, SecretKey } from '@withautonomi/autonomi'
async function registerExample() {
// Initialize client and wallet
const client = await Client.initLocal()
const wallet = Wallet.newFromPrivateKey(
new Network(true),
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
)
const payment = PaymentOption.fromWallet(wallet)
// Generate keys
const mainKey = SecretKey.random()
const registerKey = Client.registerKeyFromName(mainKey, "my-counter")
// Create register content (max 32 bytes)
const initialContent = Client.registerValueFromBytes(Buffer.from("counter: 0"))
// Check cost before creating
const cost = await client.registerCost(registerKey.publicKey())
console.log(`Register creation cost: ${cost} AttoTokens`)
// Create the register
const {cost: creationCost, addr} = await client.registerCreate(
registerKey, initialContent, payment
)
console.log(`Register created at: ${addr.toHex()}`)
// Wait for network replication
await new Promise(resolve => setTimeout(resolve, 5000))
// Read current value
const currentValue = await client.registerGet(addr)
console.log(`Current value: ${currentValue}`)
// Update the register
const newContent = Client.registerValueFromBytes(Buffer.from("counter: 1"))
const updateCost = await client.registerUpdate(registerKey, newContent, payment)
console.log(`Update cost: ${updateCost} AttoTokens`)
// Wait for replication
await new Promise(resolve => setTimeout(resolve, 5000))
// Get updated value
const updatedValue = await client.registerGet(addr)
console.log(`Updated value: ${updatedValue}`)
// Get complete history
const history = client.registerHistory(addr)
const allVersions = await history.collect()
console.log(`History has ${allVersions.length} versions:`)
allVersions.forEach((version, i) => {
console.log(` Version ${i}: ${version}`)
})
}
// Run the example
registerExample().catch(console.error)Language-Specific Usage
Python API
The Python client provides these register methods:
Methods
register_cost(public_key: PublicKey) -> strCalculate the cost to create a registerregister_create(key: SecretKey, content: RegisterValue, payment: PaymentOption) -> Tuple[str, RegisterAddress]Create a new register on the networkregister_get(address: RegisterAddress) -> RegisterValueRetrieve current value of a registerregister_update(key: SecretKey, content: RegisterValue, payment: PaymentOption) -> strUpdate an existing register with new contentregister_history(address: RegisterAddress) -> RegisterHistoryGet the complete version history of a register
Utility Functions
Client.register_key_from_name(main_key: SecretKey, name: str) -> SecretKeyGenerate a deterministic register key from a main key and nameClient.register_value_from_bytes(data: bytes) -> RegisterValueCreate RegisterValue from byte data (limited to 32 bytes)
RegisterAddress Class
RegisterAddress(public_key: PublicKey)- Create from owner's public keyfrom_hex(hex: str) -> RegisterAddress- Create from hex stringto_hex() -> str- Convert to hex stringowner() -> PublicKey- Get the public key that owns this register
Node.js API
The Node.js client provides these register methods:
Methods
client.registerCost(publicKey)- Calculate creation costclient.registerCreate(key, content, payment)- Create new registerclient.registerGet(address)- Get current register valueclient.registerUpdate(key, content, payment)- Update register contentclient.registerHistory(address)- Get version history iterator
Utility Functions
Client.registerKeyFromName(mainKey, name)- Generate deterministic keyClient.registerValueFromBytes(data)- Create RegisterValue from Buffer
RegisterAddress Class
new RegisterAddress(publicKey)- Create from public keyRegisterAddress.fromHex(hex)- Create from hex stringaddr.toHex()- Convert to hex stringaddr.owner()- Get owner public key
Use Cases
Mutable Configuration: Store application settings that need periodic updates
Status Updates: Maintain current status or state information
Version Control: Track document or data versions with full history
Counters: Implement distributed counters or sequence numbers
Metadata: Store changeable metadata for files or applications
Important Notes
Size Limit: Register values are limited to 32 bytes maximum
Ownership: Only the key holder can update a register
Network Delays: Allow time for network replication after operations (typically 5+ seconds)
Deterministic Keys: Use
register_key_from_name()for consistent key generationPayment Required: Both creation and updates require payment
History Preserved: All versions are permanently stored and accessible
Error Handling:
Creating an existing register throws
AlreadyExistserrorUpdating a non-existent register throws
CannotUpdateNewRegistererror
Last updated