Skip to main content

Nuklai's Blockchain: Helix

Overview

Helix is built on the Cosmos SDK framework that enables the creation of application-specific blockchains. This architectural choice allows us to provide a protocol specifically optimized for dataset management, sharing, and collaboration while maintaining interoperability with other blockchains through the Cosmos IBC protocol.

We support the creation, management, and exchanging of datasets in a fully decentralized manner, enabling builders to create trustless data-focused applications on top of Helix. At its core, Helix's implementation leverages (native) NFTs to track dataset ownership and contributions, creating a great system for managing data provenance and attribution.

Blockchain Architecture

Cosmos SDK Core

Helix leverages the Cosmos SDK's modular architecture, which provides:

  • Account management
  • Token handling (bank module)
  • Staking and delegation
  • Governance system for protocol upgrades and parameter changes
  • Smart Contracts (CosmWasm)
  • IBC for cross-chain communication

Custom Modules

We extended the Cosmos SDK with custom modules that implements specific functionality:

Dataset Module

The dataset module is the core of our protocol, enabling:

  • Creation of datasets with sufficient metadata (name, description, license information etc.)
  • Dataset ownership management and transfer
  • Community dataset collaboration
  • Contribution tracking via NFTs
  • Transparent contribution ownership and transfer

The module uses a sophisticated storage system with prefixed KV stores for efficient data retrieval:

// SetDataset set a specific dataset in the store from its index
func (k Keeper) SetDataset(ctx context.Context, dataset types.Dataset) {
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.DatasetKeyPrefix))
b := k.cdc.MustMarshal(&dataset)
store.Set(types.DatasetKey(dataset.Denom), b)
}

Dataset contributions are implemented as (native)NFTs, with each contribution linked to a specific dataset through the NFT class ID (which matches the dataset's denom):

// Mint the NFT representing the contribution
token := nft.NFT{
ClassId: dataset.Denom, // Use dataset's denom as nft class ID
Id: nftId,
Uri: "", // No external metadata URI
UriHash: "",
Data: &sdkCodec.Any{Value: []byte(nftDataBytes)},
}

CosmWasm Integration

We included the CosmWasm module, allowing for smart contract execution through WebAssembly. This provides:

  • Support for programmable dataset interactions within our protocol
  • Custom application logic for data handling
  • Extensibility for future use cases

The integration is implemented in the app module with proper middleware setup:

// Create fee enabled wasm ibc Stack
var wasmStack porttypes.IBCModule
wasmStack = wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper, app.IBCFeeKeeper)
wasmStack = ibcfee.NewIBCMiddleware(wasmStack, app.IBCFeeKeeper)

Consensus Mechanism

Extended the Tendermint consensus engine, providing:

  • Fast finality (typically seconds rather than minutes or hours)
  • BFT protecting against malicious actors
  • Validator-based Proof of Stake (PoS)
  • Support for up to 100+ validators

Our configuration provides efficient block processing with custom parameters:

cfg := cmtconfig.DefaultConfig()
// these values put a higher strain on node memory
// cfg.P2P.MaxNumInboundPeers = 100
// cfg.P2P.MaxNumOutboundPeers = 40

NFT-Based Data Contributions

One of the key aspects is our use of NFTs to track contributions to datasets:

How It Works

  1. Dataset Creation: Any user can create a dataset, which generates a unique identifier (denom) in Cosmos case and establishes them as the dataset owner.

  2. Contribution Process:

    • A user initiates a contribution to a dataset by providing data location and identifier
    • The dataset owner approves and completes the contribution
    • An NFT is minted representing the contribution, owned by the contributor
  3. Ownership Tracking:

    • Dataset ownership is recorded on-chain and can be transferred
    • Individual contribution ownership is represented by NFTs on-chain
    • Contributors can transfer ownership of their contributions if they choose to

Dataset creation implements a secure, unique ID generation mechanism:

// Generate a guaranteed unique denom for the dataset NFT class
func generateDatasetDenom(owner, name, ticker, description, url, categories, metadata string, isCommunityDataset bool) string {
// Concatenate dataset attributes into a unique string
data := fmt.Sprintf("%s-%s-%s-%s-%s-%s-%t-%s-%d", owner, name, ticker, description, url, categories,
isCommunityDataset, metadata, time.Now().UnixNano())

// Hash the concatenated data using SHA-256
hash := sha256.Sum256([]byte(data))

// Generate a short UUID to further ensure uniqueness
uniqueID := uuid.New().String()[:8]

// Construct the final denom with "nuklaidataset" as prefix
denom := fmt.Sprintf("nuklaidataset%s%s", hex.EncodeToString(hash[:])[:19], uniqueID)

return denom
}

Transaction Flow and Validation

All transactions on Helix go through a standardized flow:

  1. Transaction Creation: Users create transactions (like creating datasets or contributing data) using the Nuklai CLI or interfaces in this case nuklaid.

  2. Validation: All transactions pass through the AnteHandler which:

    • Verifies signatures
    • Checks gas limits
    • Ensures proper formatting
    • Validates specific module requirements
  3. Execution: Once validated, transactions are executed by the appropriate module handler.

  4. State Update: The blockchain state is updated to reflect the transaction outcomes.

  5. Event Emission: Events are emitted for client applications to track changes.

The AnteHandler implementation contains sophisticated validation logic:

anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
wasmkeeper.NewLimitSimulationGasDecorator(options.WasmConfig.SimulationGasLimit),
wasmkeeper.NewCountTXDecorator(options.TXCounterStoreService),
wasmkeeper.NewGasRegisterDecorator(options.WasmKeeper.GetGasRegister()),
circuitante.NewCircuitBreakerDecorator(options.CircuitKeeper),
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
}

Governance

Extended on-chain governance through the Cosmos SDK governance module:

  • Token holders can submit proposals for improvements to our protocol
  • Voting periods allow stakeholders to approve or reject proposals
  • Successful proposals are then implemented by the protocol team
  • Parameters like voting thresholds and periods are configurable
genesis:
app_state:
gov:
voting_params:
voting_period: "180s"
deposit_params:
max_deposit_period: "60s"
min_deposit:
- denom: "nai"
amount: "1000000"
params:
expedited_voting_period: "90s"
expedited_min_deposit:
- amount: "5000000"
denom: nai

Token Economics

Our native token is NAI, which serves multiple purposes within our system:

  • Transaction Fees: All operations on the blockchain require gas paid in NAI
  • Staking: All validators stake NAI to participate in consensus
  • Governance: NAI holders can vote on proposals proportional to their holdings
  • Dataset Operations: Creating and managing datasets requires NAI
What is Nuklai

Network Security

Our security model relies on:

  1. Validator Set: A distributed group of validators stake NAI tokens and run nodes that validate transactions and produce blocks sequentially.

  2. Delegated Proof of Stake: Token holders can delegate their NAI to validators, this specifically increases security while earning a portion of rewards.

  3. Slashing Conditions: Validators who misbehave (double-sign blocks or remain offline) have a portion of their stake slashed.

  4. Consensus Rules: The Tendermint consensus algorithm ensures that 2/3+ of validators must agree on the state of the blockchain.

// reset start height on signing infos
if err := app.SlashingKeeper.IterateValidatorSigningInfos(
ctx,
func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) {
info.StartHeight = 0
_ = app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
return false
},
); err != nil {
log.Fatal(err)
}

Interoperability

Through IBC integration, We can:

  • Transfer datasets and contributions to other compatible blockchains
  • Interact with other specialized chains in the Cosmos ecosystem that we choose to
  • Access liquidity and functionality from connected blockchains

IBC integration is implemented with proper middleware stacking:

// Create static IBC router, add transfer route, then set and seal it
ibcRouter := porttypes.NewRouter().
AddRoute(ibctransfertypes.ModuleName, transferIBCModule).
AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule).
AddRoute(icahosttypes.SubModuleName, icaHostIBCModule)

wasmStack, err := app.registerWasmModules(appOpts)
if err != nil {
return err
}
ibcRouter.AddRoute(wasmtypes.ModuleName, wasmStack)

app.IBCKeeper.SetRouter(ibcRouter)

Development and Testing

You as a builder can extend and interact with Helix through:

  1. CLI Interface: For direct interaction with the blockchain nuklaid

    nuklaid tx dataset create-dataset kiran1 KP1 test nukl.ai person mit MIT test.license true test.metadata --from alice
  2. REST API: For application integration

    // RegisterAPIRoutes registers all application module routes with the provided API server
    func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
    app.App.RegisterAPIRoutes(apiSvr, apiConfig)
    if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
    panic(err)
    }
    docs.RegisterOpenAPIService(Name, apiSvr.Router)
    }
  3. gRPC Endpoints: For efficient programmatic access

    app.GRPCQueryRouter()
  4. CosmWasm Contracts: For your custom on-chain logic

    // Mint 1000 tokens to address
    {
    "name": "Shodipo Ayomide",
    "symbol": "SAY",
    "decimals": 6,
    "initial_balances": [
    {
    "address": "nuklai13fy0hfyy5h9zxmkukfx48j0m84kyl7qpcljh5h",
    "amount": "1000000000"
    }
    ]
    }
  5. Transaction Submissions: For creating new NFT, FT, datasets, contributions, and transfers

    // In code, we provide helper functions for transaction creation
    contributionId := types.ComputeContributionID(msg.Denom, msg.DataLocation, msg.DataIdentifier)