Storage DFMS

Storage DFMS

  • Getting Started
  • CLI
  • Guides
  • API Endpoints
  • Help

›Different flows

Nodes

  • Create API node
  • Create API HTTP node

Contract

  • Compose Contract
  • Get Contract
  • List contracts
  • Ammends Contracts
  • Verify Contract
  • Accept Contract
  • Accepted Contract
  • Contract Invites
  • Finish Contract

Drive

  • Add
  • Get
  • Get File by CID
  • Copy
  • Move(Rename)
  • Make Dir
  • Stat
  • List
  • Remove
  • Flush
  • Clear

SuperContract

  • Deploy SuperContract
  • Execute SuperContract
  • SuperContract Results
  • List SuperContracts
  • Get SuperContract
  • SuperContract Executions
  • Deactivate SuperContract

Network

  • Node ID
  • Get Node Addresses
  • Connect to Node
  • Get Connected Peers
  • Disconnect from Node

Different flows

  • Guide of connection lifecycle
  • Guide of contract lifecycle
  • Guide of file lifecycle
  • Guide of SuperContract lifecycle

Guide of contract lifecycle

Requirements

  • IDE or text editor
  • Have one running owner/client node
  • Have at least one running Storage Replicator Node node

Example

The guides shows possible contract flows. Note that replicator can do everything that can client, but client not.

import (
    "context"
    "fmt"
    "log"
    "sync"
    "time"

    api "github.com/proximax-storage/go-xpx-dfms-api"
    apihttp "github.com/proximax-storage/go-xpx-dfms-api-http"
    "github.com/proximax-storage/go-xpx-dfms/crypto"
)

func main() {
    // Replicator a new replicator API by given address
    replicator := apihttp.NewReplicatorAPI("127.0.0.1:64666")

    // Replicator connected to client (see network guides) and can start listen new invites.
    // Not required, replicator can just accept a contract by ID without subscription.
    go func() {
        // Create a new subscription
        sub, err := replicator.Contract().Invites(context.TODO())
        if err != nil {
            log.Fatal("can't create subscription: ", err)
        }
        defer sub.Close()

        // Listening...
        for {
            // Get an invite
            inv, err := sub.Next(context.TODO())
            if err != nil {
                log.Fatal("can't get invite: ", err)
            }

            // Accept the invite
            err = replicator.Contract().Accept(context.TODO(), inv.Drive)
            if err != nil {
                log.Fatal("can't accept a contract: ", err)
            }
        }
    }()

    // Also, replicator and can subscribe on accepted drives
    go func() {
        // Create a new subscription
        sub, err := replicator.Contract().Accepted(context.TODO())
        if err != nil {
            log.Fatal("can't create subscription: ", err)
        }
        defer sub.Close()

        contractCount := 0
        // Listening...
        for {
            go func() {
                for {
                    contract, err := sub.Next(context.TODO())
                    if err != nil {
                        log.Fatal(err)
                    }
                    if contract != nil {
                        contractCount++
                        fmt.Printf("accepted a new contract:\n %+v \n sum count of acceted contracts: %d", contract, contractCount)
                    }
                }
            }()
        }
    }()

    // Create a new client API by given address
    client := apihttp.NewClientAPI("127.0.0.1:63666")

    //Not required. Generate your own private key if you want
    private, _, err := crypto.GenerateEd25519CatapultKey()
    if err != nil {
        panic(err)
    }

    //Compose a new contract
    contract, err := client.Contract().Compose(
        context.TODO(),
        // Required. size of drive
        uint64(1000),
        // Required. Duration of one billing (subscription) period when replicators will get rewards
        time.Hour*24*30,
        // Optional. Genarated private key that will use for drive
        api.PrivateKey(private),
        // Optional. The number of SO units that will be dived between replicators at the end of
        // billing period. Default valu equals to driveSize*PayedReplicas
        api.SubscriptionPrice(5000),
        // Optional. The number of billing (subscription) periods
        api.NumberSubscriptionPeriods(12),
        // Optional. The minimal amount of replicators for starting billing (subscription) periods
        // Default value 3
        api.MinReplicators(3),
        // Optional. The count of wanted (and payed) replicas
        // Default 3
        api.Replicas(5),
        // Optional. The percent for approving any transaction sent by contract account
        // Default 66
        api.PercentApprovers(66),
    )
    //Blocked till contract will have been composed or will have got an error
    if err != nil {
        panic(err)
    }

    // Note: if replicator don't listen to new invites just accept by ID
    // err = replicator.Contract().Accept(context.TODO(), contract.Drive)
    // if err != nil {
    //     log.Fatal("can't accept a contract: ", err)
    // }

    // After creation can get info about this drive
    ctr, err := client.Contract().Get(context.TODO(), contract.Drive)
    if err != nil {
        panic(err)
    }
    fmt.Println(ctr)

    // Also, the client can get list of drives where it is owner or takes paticipant
    list, err := client.Contract().List(context.TODO())
    if err != nil {
        panic(err)
    }
    for _, c := range list {
        fmt.Println(c)
    }

    // The client can create subscription on drive changes
    // Create subscription
    subscription, err := replicator.Contract().Amendments(context.TODO(), contract.Drive)
    if err != nil {
        panic(err)
    }

    // Just count updates
    m := sync.Mutex{}
    updatesCount := 0

    // Listening...
    go func() {
        defer subscription.Close()

        _, err := subscription.Next(context.TODO())
        if err != nil {
            log.Fatal(err)
        }

        m.Lock()
        updatesCount++
        fmt.Println("updates count: ", updatesCount)
        m.Unlock()
    }()

    // At any time client or replicator can start drive verification.
    // To get some result would be good add some files
    verifyRes, err := client.Contract().Verify(context.TODO(), contract.Drive)
    if err != nil {
        panic(err)
    }
    fmt.Println(verifyRes)

    // Client can finish drive at any time if it want
    err = client.Contract().Finish(context.TODO(), contract.Drive)
    if err != nil {
        panic(err)
    }
}
← Guide of connection lifecycleGuide of file lifecycle →
  • Requirements
  • Example
Storage DFMS
Roles
SDNSRNVerifierSC Executor
Built-in Features
DriveSuperContractChallengeRewards
Protocols
Cross-block protocolFair streaming
Algorithms
VerificationConsensus
CLI
dfms-clientdfms-replicatorsupercontracts
Giudes
ContractDriveSupercontractsNetwork
Copyright © 2021 ProximaX