Skip to content

Latest commit

 

History

History
300 lines (231 loc) · 9.3 KB

README.md

File metadata and controls

300 lines (231 loc) · 9.3 KB

oracles

Summary

Oracle client written in bash that utilizes secure scuttlebutt for offchain message passing along with signed price data to validate identity and authenticity on-chain.

Design Goals

Goals of this new architecture are:

  1. Scalability,
  2. Reduce costs by minimizing number of ethereum transactions and operations performed on-chain,
  3. Increase reliability during periods of network congestion,
  4. Reduce latency to react to price changes,
  5. Make it easy to on-board price feeds for new collateral types, and
  6. Make it easy to on-board new Oracles.

Architecture

There are currently two main modules:

Feed

Each Feed runs a Feed client which pulls prices redundantly with Setzer and Oracle Suite/Gofer, signs them with an ethereum private key, and broadcasts them as a message to the redundant p2p networks (e.g. scuttlebutt and libp2p).

Relay

Relays monitor the broadcast messages, check for liveness, and homogenize the pricing data and signatures into a single ethereum transaction to be posted to the on-chain oracles.

Configuration Files

The sample generic configurtion file are present in ./systemd/ folder.

Install with Nix

Tested on this enviroment:

Ubuntu 22.04

nix-build (Nix) 2.13.2

To build from inside this repo, clone and run:

nix-build

The setup scripts can also be used configure Omnia as a feed running with systemd:

The setup scripts can also be used configure Omnia as a relay running with systemd but first make sure spire is running:


sudo ./setup/run_it_feed.sh --gofer <ABSOLUTE_PATH_OF_CONFIG> --omnia <ABSOLUTE_PATH_OF_CONFIG> --spire <ABSOLUTE_PATH_OF_CONFIG>

for example:

sudo ./setup/run_it_feed.sh --gofer /home/oracles/gofer.json --omnia /home/oracles/omnia_relay.json --spire /home/oracles/spire1.json

If you want to run multiple omnia's feed instances then you have to change the name of the systemd files(omnia.service, spire-agent.service) which are generated by ./setup/run_feed.sh or ./setup/run_it_relay.sh and change the config files path for shell script for example: sudo ./setup/run_it_relay.sh --omnia /home/oracles/omnia2.json --spire /home/oracles/spire.json and run the shell script again.

you can run the omnia, spire and gofer with systemd by these command:

systemctl start omnia.service
systemctl start gofer-agent.service
systemctl start spire-agent.service

Configuring Gofer

the gofer is configured by its configurations and the sample config is stated below. It uses HCL file for configuration; HCL File should be same for Gofer and Spire

Configuring Spire

spire is installed through nix.

It uses HCL file for configuration; HCL File should be same for Gofer and Spire

This is based on libp2p which is a peer-to-peer networking protocol designed to enable decentralized communication and file sharing over the internet. It is a modular, open-source networking protocol that allows nodes to communicate with each other directly, without the need for a central server or infrastructure.

One of these attributes is the "transport" attribute, which uses libp2p to establish direct peer-to-peer connections between nodes without relying on a central server or infrastructure, So we have to give the listenAddrs for example /ip4/192.168.18.109/tcp/37705/p2p/12D3KooWPFpaE13gph8p6jdNGJv1M6fwDro8kdst53MUzVpuSJUL i.e "<ip-version>/<host>/<protocol>/<port>/<type>/<peer_id>" w.r.t the quorum of median.To obtain the peer addresses, you can check the logs of Spire using journalctl, as Spire runs as a systemd service. Once you have the peer addresses, then ** you can add them to the "directPeersAddrs" array to connect peers in the "transport" attribute of the Spire configuration file. **

sudo journalctl -u <spire-agent.service> -n 100 -b -f

add peerIDs in this attr to connect spire with each other

"transport" {
      "libp2p"  {
        "directPeersAddrs"=["Add listen address here"]}}

command to run spire

spire agent -c <CONFIG_PATH> --log.verbosity debug

command to run spire systemd

systemctl start <spire-agent.service>

command to run ssb-server systemd

systemctl start <ssb-server.service>

The installed Scuttlebot config can be found in ~/.ssb.config, more details about the Scuttlebot config.

Creating and Accepting SSB Invites

Open the systemd file of ssb-server.service to lookup the binary of ssb-server.

Creating an SSB Invite

ssb-server invite.create 1 means <path of ssb-server> invite.create 1

This will output a JSON object containing the invite code.

Accepting an SSB Invite

To accept an SSB invite without using Docker, open a terminal window and run the following command:

ssb-server invite.accept <invite_code>

Replace <invite_code> with the invite code obtained in the previous step.

how it will work

we should run the 3 feeds with the 3 spires every feed should have their own omnia means the config file have the right omnia addr pasted in feed object of spire's config

Example configuration:Relay

{
  "mode": "relay",
  "ethereum": {
    "from": "0x",
    "keystore": "",
    "password": "",
    "network": "goerli",
    "gasPrice": {
      "source": "node",
      "multiplier": 1
		}
  },
  "transports":["ssb"],
  "feeds": [
    "0xdeadbeef123"
  ],
  ...
}

Example configuration:Feed

{
  "mode": "feed",
  "ethereum": {
    "from": "0x86B5B8Fe2B467F733c0624e13b9Df08867d94B96",
    "keystore": "/home/admin/.ethereum/keystore",
    "password": "/home/admin/.ethereum/keystore/.pass",
    "type": "ethereum",
    "network": "http://127.0.0.1:8545"
  },
  "options": {
    "interval": 60,
    "msgLimit": 35,
    "srcTimeout": 10,
    "setzerTimeout": 10,
    "setzerCacheExpiry": 120,
    "setzerMinMedian": 1,
    "setzerEthRpcUrl": "http://127.0.0.1:9989",
    "verbose": true,
    "logFormat": "text"
  },
  "sources": [
    "gofer","setzer"
  ],
  "transports": [
    "spire"
  ],
  "pairs": {
    "ETH/USD": {
      "msgExpiration": 1800,
      "msgSpread": 0.5
    }
  }
}

Example configuration: SPIRE && GOFER

variables {
  # List of feeds that are allowed to send price updates and event attestations.
  feeds = try(env.CFG_FEEDS == "" ? [] : split(",", env.CFG_FEEDS), [
      "0x125fC0CcCDee5ac474062F6358d4d056b0430b84",
      "0x37c273044A6ef7c9D09670C8246c49FF4CfD2511",
      "0x34050B9d0630594214008e3a2af07107B71831fd"
  ])
}

ethereum {
  rand_keys = try(env.CFG_ETH_FROM, "0x125fC0CcCDee5ac474062F6358d4d056b0430b84") == "" ? ["default"] : []

  dynamic "key" {
    for_each = try(env.CFG_ETH_FROM, "0x125fC0CcCDee5ac474062F6358d4d056b0430b84") == "" ? [] : [1]
    labels   = ["default"]
    content {
      address         = try(env.CFG_ETH_FROM, "0x125fC0CcCDee5ac474062F6358d4d056b0430b84")
      keystore_path   = try(env.CFG_ETH_KEYS, "/home/usman/.ethereum/keystore")
      passphrase_file = try(env.CFG_ETH_PASS, "/home/usman/.ethereum/keystore/.pass")
    }
  }

  client "default" {
    rpc_urls     = try(env.CFG_ETH_RPC_URLS == "" ? [] : split(",", env.CFG_ETH_RPC_URLS), [
      "https://goerli.infura.io/v3/de82b2d602264e4fbc0929dec0c45baa"
    ])
    chain_id     = 1
    ethereum_key = "default"
  }

  client "arbitrum" {
    rpc_urls     = try(env.CFG_ETH_ARB_RPC_URLS == "" ? [] : split(",", env.CFG_ETH_ARB_RPC_URLS), [
      "https://arbitrum.public-rpc.com"
    ])
    chain_id     = 42161
    ethereum_key = "default"
  }

  client "optimism" {
    rpc_urls     = try(env.CFG_ETH_OPT_RPC_URLS == "" ? [] : split(",", env.CFG_ETH_OPT_RPC_URLS), [
      "https://mainnet.optimism.io"
    ])
    chain_id     =  10
    ethereum_key = "default"
  }
}

transport {
  # LibP2P transport configuration. Always enabled.
  libp2p {
    feeds           = var.feeds
    priv_key_seed   = try(env.CFG_LIBP2P_PK_SEED, "")
    listen_addrs    = try(split(",", env.CFG_LIBP2P_LISTEN_ADDRS), ["/ip4/0.0.0.0/tcp/8779"])
    direct_peers_addrs = []
    blocked_addrs      = try(env.CFG_LIBP2P_BLOCKED_ADDRS == "" ? [] : split(",", env.CFG_LIBP2P_BLOCKED_ADDRS), [])
    disable_discovery  =  false
    ethereum_key       = try(env.CFG_ETH_FROM, "0x125fC0CcCDee5ac474062F6358d4d056b0430b84") == "" ? "" : "default"
  }
}

spire {
  rpc_listen_addr = try(env.CFG_SPIRE_RPC_ADDR, "0.0.0.0:9105")
  rpc_agent_addr  = try(env.CFG_SPIRE_RPC_ADDR, "127.0.0.1:9105")

  # List of pairs that are collected by the spire node. Other pairs are ignored.
  pairs = try(env.CFG_SPIRE_PAIRS == "" ? [] : split(",", env.CFG_SPIRE_PAIRS), [
    "BTC/USD",
    "USDT/GSU"
  ])
}

gofer {
  rpc_listen_addr = "0.0.0.0:9200"
  rpc_agent_addr  = "0.0.0.0:9200"
  price_model "ETH/GSU" "median" {
      source "ETH/GSU" "origin" { origin = "gsu" }
      source "ETH/GSU" "origin" { origin = "gsu1" }
      source "ETH/GSU" "origin" { origin = "gsu2" }
      min_sources = 1
    }
  price_model "USDT/GSU" "median" {
      source "USDT/GSU" "origin" { origin = "gsu" }
      source "USDT/GSU" "origin" { origin = "gsu1" }
      source "USDT/GSU" "origin" { origin = "gsu2" }
      min_sources = 1
    }
  price_model "BTC/USD" "median" {
    source "BTC/USD" "origin" { origin = "gsu" }
    source "BTC/USD" "origin" { origin = "gsu1" }
    source "BTC/USD" "origin" { origin = "gsu2" }
    min_sources = 1
  }
}