├── debian ├── compat ├── source │ └── format ├── sonm-cli.install ├── sonm-dwh.dirs ├── sonm-node.dirs ├── sonm-cli.bash-completion ├── sonm-dwh.default ├── sonm-node.default ├── sonm-relay.default ├── sonm-connor.default ├── sonm-optimus.default ├── sonm-oracle.default ├── sonm-worker.default ├── sonm-dwh.install ├── sonm-node.install ├── sonm-rendezvous.default ├── sonm-relay.install ├── sonm-connor.install ├── sonm-optimus.install ├── sonm-oracle.install ├── sonm-worker.install ├── sonm-rendezvous.install ├── sonm-mon.install ├── sonm-connor.service ├── sonm-oracle.service ├── sonm-worker.service ├── sonm-node.service ├── sonm-optimus.service ├── sonm-dwh.service ├── sonm-relay.service ├── copyright ├── sonm-rendezvous.service ├── sonm-node.postinst ├── sonm-mon.service └── sonm-mon.postinst ├── blockchain ├── source │ ├── .eslint │ ├── .eslintignore │ ├── test │ │ ├── helpers │ │ │ ├── EVMRevert.js │ │ │ ├── EVMThrow.js │ │ │ ├── ether.js │ │ │ ├── printers.js │ │ │ ├── latestTime.js │ │ │ ├── toPromise.js │ │ │ ├── decodeLogs.js │ │ │ ├── assertRevert.js │ │ │ ├── assertJump.js │ │ │ ├── hashMessage.js │ │ │ ├── advanceToBlock.js │ │ │ ├── common.js │ │ │ ├── ask.js │ │ │ ├── bid.js │ │ │ ├── expectThrow.js │ │ │ ├── expectEvent.js │ │ │ └── transactionMined.js │ │ └── addressHashMap.js │ ├── .babelrc │ ├── scripts │ │ ├── test_coverage.sh │ │ └── dev.sh │ ├── .soliumignore │ ├── .gitignore │ ├── .solcover.js │ ├── .soliumrc.json │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 3_deploy_devices_storage.js │ ├── contracts │ │ ├── AddressHashMap.sol │ │ ├── test │ │ │ └── Dummy.sol │ │ ├── SNM.sol │ │ ├── Migrations.sol │ │ ├── OracleUSD.sol │ │ ├── TestnetFaucet.sol │ │ └── DeployList.sol │ ├── patches │ │ ├── truffle-resolver+4.0.4.patch │ │ └── truffle+4.1.14.patch │ ├── .eslintrc │ ├── package.json │ └── migration_utils │ │ └── address_hashmap.js ├── addresses.go ├── gasLimits.go └── unit.go ├── codecov.yml ├── .gitattributes ├── cmd ├── sonmmon │ ├── image.png │ └── TerminusTTFWindows-4.46.0.ttf ├── autocli │ ├── proto │ │ └── mod.go │ └── main.go ├── cli │ ├── commands │ │ ├── version.go │ │ ├── worker_tasks.go │ │ ├── completion.go │ │ ├── worker_metrics.go │ │ ├── worker_devices.go │ │ ├── version_test.go │ │ └── worker_benchmarks.go │ ├── main.go │ └── task_config │ │ ├── config.go │ │ └── load_order.go ├── pandora │ ├── config.go │ ├── main.go │ ├── registry.go │ ├── ammo.go │ ├── gun.go │ ├── gun_dwh.go │ ├── gun_marketplace.go │ └── ammo_dwh.go ├── common.go ├── lsgpu │ └── main.go ├── oracle │ └── main.go ├── connor │ └── main.go ├── secterm │ └── main.go ├── node │ └── main.go └── optimus │ └── main.go ├── secsh ├── secshc │ ├── protocol.go │ └── config.go ├── config.go └── watch.go ├── optimus ├── cgroup.go ├── context.go ├── cgroup_nonlinux.go ├── matrix.go ├── options.go ├── tagging.go ├── plan_policy.go ├── worker_test.go ├── knapsack.go ├── normalize_test.go ├── cgroup_linux.go ├── watcher.go ├── model_lls.go └── model.go ├── util ├── grpc.go ├── action │ └── action.go ├── xgrpc │ ├── method.go │ ├── credentials.go │ ├── server.go │ └── metrics.go ├── metadata.go ├── xdocker │ ├── reference_test.go │ └── xdocker.go ├── config │ ├── config.go │ └── retag_test.go ├── grpcutil_test.go ├── ticker.go ├── xconcurrency │ └── cncurrency.go ├── defergroup │ └── mod.go ├── certs_test.go ├── multierror │ └── error.go ├── debug │ └── pprof.go └── rest │ └── errors.go ├── insonmnia ├── worker │ ├── network │ │ ├── tc │ │ │ ├── tc_nonlinux.go │ │ │ ├── proto_linux.go │ │ │ ├── proto_nonlinux.go │ │ │ ├── proto.go │ │ │ ├── qdisc_test.go │ │ │ ├── handle.go │ │ │ ├── class.go │ │ │ ├── filter_test.go │ │ │ └── ifb.go │ │ ├── config.go │ │ ├── tinc_config.go │ │ ├── README.l2tp.md │ │ └── tuner.go │ ├── storage │ │ ├── errors.go │ │ ├── common.go │ │ ├── quotafactory_nonlinux.go │ │ ├── quotafactory_linux.go │ │ └── btrfs │ │ │ └── btrfs_native_api_test.go │ ├── gpu │ │ ├── dri_windows.go │ │ ├── metrics_other.go │ │ ├── tuner_other.go │ │ ├── dri_unix.go │ │ ├── remote_server.go │ │ ├── detect.go │ │ └── fake_tuner.go │ ├── plugin │ │ ├── config.go │ │ └── cleanup.go │ ├── options.go │ ├── docker.go │ ├── cgroup_test.go │ ├── ssh_test.go │ └── volume │ │ └── options.go ├── gateway │ ├── router_nonlinux.go │ ├── gateway_nonlinux.go │ ├── metrics.go │ ├── pool.go │ └── pool_test.go ├── hardware │ ├── gpu │ │ ├── cl_other.go │ │ └── device.go │ ├── marshal.go │ ├── ram │ │ └── device.go │ ├── cpu │ │ └── device.go │ └── disk │ │ └── disk.go ├── ssh │ └── config.go ├── npp │ ├── nppc │ │ └── id.go │ ├── common.go │ ├── config.go │ ├── error.go │ ├── relay │ │ ├── frame_test.go │ │ ├── options.go │ │ ├── hashring_test.go │ │ ├── logging.go │ │ └── errors.go │ ├── rendezvous │ │ ├── peer.go │ │ └── client.go │ └── conn.go ├── cgroups │ └── cgroup_nonlinux.go ├── dwh │ └── util.go ├── logging │ ├── config.go │ ├── trace.go │ └── logging_test.go ├── node │ ├── profiles.go │ └── monitoring.go ├── sysinit │ └── lsblk.go ├── resource │ └── ask_plan_map.go ├── structs │ ├── network_spec.go │ └── image.go ├── oracle │ └── config.go └── auth │ └── common_test.go ├── Cargo.toml ├── connor ├── antifraud │ ├── flags.go │ ├── flags_test.go │ ├── antifraud_test.go │ └── pool_processor_test.go ├── backends.go ├── price │ └── static.go ├── types │ ├── types.go │ └── benchmarks.go └── config_test.go ├── proto ├── geoip.proto ├── bigint.proto ├── init.proto ├── node.go ├── gpu_ctl.proto ├── volume.proto ├── optimus.go ├── optimus.proto ├── net.proto ├── timestamp.proto ├── gpu_device.go ├── pty.proto ├── gpu_device_test.go ├── log_reader.go ├── marketplace_test.go ├── rendezvous.go ├── timestamp.go ├── benchmarks.proto ├── tc.proto ├── container.go ├── dwh.go ├── relay.go ├── ask_plan.proto └── worker.go ├── etc ├── cli.yaml ├── rendezvous.yaml ├── secexec │ ├── cat.yaml │ ├── grep.yaml │ ├── ps.yaml │ ├── ls.yaml │ └── lsof.yaml ├── dwh.yaml ├── secterm.yaml ├── oracle.yaml └── qos.yaml ├── .github ├── CODEOWNERS └── ISSUE_TEMPLATE.md ├── .ci └── coverage.sh ├── secexec ├── Cargo.toml └── src │ ├── lib.rs │ └── prctl.rs ├── accounts └── config.go ├── keys └── example.key ├── .mailmap ├── ask.yaml ├── appveyor.yml ├── .gitignore ├── .travis.yml └── README.md /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /blockchain/source/.eslint: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /blockchain/source/.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - proto/*.pb.go 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /debian/sonm-cli.install: -------------------------------------------------------------------------------- 1 | target/sonmcli usr/bin 2 | -------------------------------------------------------------------------------- /debian/sonm-dwh.dirs: -------------------------------------------------------------------------------- 1 | var/lib/sonm 2 | etc/sonm 3 | -------------------------------------------------------------------------------- /debian/sonm-node.dirs: -------------------------------------------------------------------------------- 1 | var/lib/sonm 2 | var/run/sonm 3 | etc/sonm -------------------------------------------------------------------------------- /debian/sonm-cli.bash-completion: -------------------------------------------------------------------------------- 1 | sonmcli.bash-completion sonmcli 2 | -------------------------------------------------------------------------------- /debian/sonm-dwh.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/dwh-default.yaml" 2 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/EVMRevert.js: -------------------------------------------------------------------------------- 1 | export default 'revert'; 2 | -------------------------------------------------------------------------------- /debian/sonm-node.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/node-default.yaml" 2 | -------------------------------------------------------------------------------- /debian/sonm-relay.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/relay-default.yaml" 2 | -------------------------------------------------------------------------------- /debian/sonm-connor.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/connor-default.yaml" 2 | -------------------------------------------------------------------------------- /debian/sonm-optimus.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/optimus-default.yaml" 2 | -------------------------------------------------------------------------------- /debian/sonm-oracle.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/oracle-default.yaml" 2 | -------------------------------------------------------------------------------- /debian/sonm-worker.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/worker-default.yaml" 2 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/EVMThrow.js: -------------------------------------------------------------------------------- 1 | export default 'invalid opcode'; 2 | -------------------------------------------------------------------------------- /debian/sonm-dwh.install: -------------------------------------------------------------------------------- 1 | target/sonmdwh usr/bin 2 | etc/sonm/dwh-default.yaml 3 | -------------------------------------------------------------------------------- /debian/sonm-node.install: -------------------------------------------------------------------------------- 1 | target/sonmnode usr/bin 2 | etc/sonm/node-default.yaml 3 | -------------------------------------------------------------------------------- /debian/sonm-rendezvous.default: -------------------------------------------------------------------------------- 1 | CONFIG_PATH="/etc/sonm/rendezvous-default.yaml" 2 | -------------------------------------------------------------------------------- /blockchain/source/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2", "stage-3"] 3 | } 4 | -------------------------------------------------------------------------------- /debian/sonm-relay.install: -------------------------------------------------------------------------------- 1 | target/sonmrelay usr/bin 2 | etc/sonm/relay-default.yaml 3 | -------------------------------------------------------------------------------- /cmd/sonmmon/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonm-io/core/HEAD/cmd/sonmmon/image.png -------------------------------------------------------------------------------- /debian/sonm-connor.install: -------------------------------------------------------------------------------- 1 | target/sonmconnor usr/bin 2 | etc/sonm/connor-default.yaml 3 | -------------------------------------------------------------------------------- /debian/sonm-optimus.install: -------------------------------------------------------------------------------- 1 | target/sonmoptimus usr/bin 2 | etc/sonm/optimus-default.yaml 3 | -------------------------------------------------------------------------------- /debian/sonm-oracle.install: -------------------------------------------------------------------------------- 1 | target/sonmoracle usr/bin 2 | etc/sonm/oracle-default.yaml 3 | -------------------------------------------------------------------------------- /debian/sonm-worker.install: -------------------------------------------------------------------------------- 1 | target/sonmworker usr/bin 2 | etc/sonm/worker-default.yaml 3 | -------------------------------------------------------------------------------- /secsh/secshc/protocol.go: -------------------------------------------------------------------------------- 1 | package secshc 2 | 3 | const ( 4 | Protocol = "secexec" 5 | ) 6 | -------------------------------------------------------------------------------- /optimus/cgroup.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | type Deleter interface { 4 | Delete() error 5 | } 6 | -------------------------------------------------------------------------------- /debian/sonm-rendezvous.install: -------------------------------------------------------------------------------- 1 | target/sonmrendezvous usr/bin 2 | etc/sonm/rendezvous-default.yaml 3 | -------------------------------------------------------------------------------- /util/grpc.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | const ( 4 | WorkerAddressHeader = "x-worker-eth-addr" 5 | ) 6 | -------------------------------------------------------------------------------- /blockchain/source/scripts/test_coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SOLIDITY_COVERAGE=true scripts/test.sh -------------------------------------------------------------------------------- /cmd/autocli/proto/mod.go: -------------------------------------------------------------------------------- 1 | // this little boi should be here because of imports in autocli's main 2 | 3 | package sonm 4 | -------------------------------------------------------------------------------- /cmd/sonmmon/TerminusTTFWindows-4.46.0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonm-io/core/HEAD/cmd/sonmmon/TerminusTTFWindows-4.46.0.ttf -------------------------------------------------------------------------------- /blockchain/source/.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | contracts/Migrations.sol 3 | zeppelin-solidity/contracts/* 4 | contracts/SNMMasterchain.sol 5 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/ether.js: -------------------------------------------------------------------------------- 1 | export default function ether (n) { 2 | return new web3.BigNumber(web3.toWei(n, 'ether')); 3 | } 4 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/tc_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux !nl 2 | 3 | package tc 4 | 5 | func NewDefaultTC() (TC, error) { 6 | return NewCmdTC() 7 | } 8 | -------------------------------------------------------------------------------- /debian/sonm-mon.install: -------------------------------------------------------------------------------- 1 | target/sonmmon ./usr/bin/ 2 | cmd/sonmmon/image.png ./usr/share/sonmmon/ 3 | cmd/sonmmon/TerminusTTFWindows-4.46.0.ttf ./usr/share/sonmmon/ 4 | -------------------------------------------------------------------------------- /blockchain/source/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | node_modules/ 3 | .idea/ 4 | package-lock.json 5 | nohup.out 6 | coverageEnv/ 7 | coverage/ 8 | coverage.json 9 | scTopics 10 | allFiredEvents 11 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/printers.js: -------------------------------------------------------------------------------- 1 | export const inspect = async (data, clazz) => { 2 | for (let k in clazz) { 3 | console.log(`${k}: ${data[clazz[k]]} `); 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/proto_linux.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import "golang.org/x/sys/unix" 4 | 5 | const ( 6 | ProtoAll Protocol = unix.ETH_P_ALL 7 | ProtoIP = unix.ETH_P_IP 8 | ) 9 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/latestTime.js: -------------------------------------------------------------------------------- 1 | // Returns the time of the last mined block in seconds 2 | export default function latestTime () { 3 | return web3.eth.getBlock('latest').timestamp; 4 | } 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "secexec", 4 | ] 5 | 6 | [profile.dev] 7 | panic = "abort" 8 | 9 | [profile.release] 10 | debug = false 11 | rpath = false 12 | panic = "abort" 13 | lto = true 14 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/toPromise.js: -------------------------------------------------------------------------------- 1 | export default func => 2 | (...args) => 3 | new Promise((resolve, reject) => 4 | func(...args, (error, data) => error ? reject(error) : resolve(data))); 5 | -------------------------------------------------------------------------------- /optimus/context.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import "context" 4 | 5 | func contextDone(ctx context.Context) error { 6 | select { 7 | case <-ctx.Done(): 8 | return ctx.Err() 9 | default: 10 | return nil 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /connor/antifraud/flags.go: -------------------------------------------------------------------------------- 1 | package antifraud 2 | 3 | const ( 4 | AllChecks = iota 5 | SkipBlacklisting 6 | ) 7 | 8 | type flags int 9 | 10 | func (f flags) SkipBlacklist() bool { 11 | return int(f)&SkipBlacklisting == 1 12 | } 13 | -------------------------------------------------------------------------------- /insonmnia/gateway/router_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package gateway 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | func newIPVSRouter(context.Context, *Gateway, *PortPool) Router { 10 | return newDirectRouter() 11 | } 12 | -------------------------------------------------------------------------------- /insonmnia/hardware/gpu/cl_other.go: -------------------------------------------------------------------------------- 1 | // +build !cl 2 | 3 | package gpu 4 | 5 | import ( 6 | "github.com/sonm-io/core/proto" 7 | ) 8 | 9 | func GetGPUDevicesUsingOpenCL() ([]*sonm.GPUDevice, error) { 10 | return nil, ErrUnsupportedPlatform 11 | } 12 | -------------------------------------------------------------------------------- /insonmnia/worker/network/config.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type NetworkConfig struct { 4 | // RemoteQOS is an optional QOS server. Used in complex network 5 | // configurations. 6 | // You'd likely not want to touch this. 7 | RemoteQOS string `yaml:"remote_qos"` 8 | } 9 | -------------------------------------------------------------------------------- /proto/geoip.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | message GeoIPCountry { 8 | string IsoCode = 1; 9 | } 10 | 11 | message GeoIP { 12 | GeoIPCountry country = 1; 13 | } 14 | -------------------------------------------------------------------------------- /insonmnia/worker/storage/errors.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import "fmt" 4 | 5 | type ErrDriverNotSupported struct { 6 | driver string 7 | } 8 | 9 | func (e ErrDriverNotSupported) Error() string { 10 | return fmt.Sprintf("driver %s not supported", e.driver) 11 | } 12 | -------------------------------------------------------------------------------- /insonmnia/worker/gpu/dri_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package gpu 4 | 5 | import ( 6 | "fmt" 7 | "runtime" 8 | ) 9 | 10 | func deviceNumber(path string) (uint64, uint64, error) { 11 | return 0, 0, fmt.Errorf("unsupported platform: %s", runtime.GOOS) 12 | } 13 | -------------------------------------------------------------------------------- /proto/bigint.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | // BigInt represents multi-precision value stored as a big integer. 8 | message BigInt { 9 | bool neg = 1; 10 | bytes abs = 2; 11 | } 12 | -------------------------------------------------------------------------------- /optimus/cgroup_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package optimus 4 | 5 | type nilDeleter struct{} 6 | 7 | func (nilDeleter) Delete() error { 8 | return nil 9 | } 10 | 11 | func RestrictUsage(cfg *RestrictionsConfig) (Deleter, error) { 12 | return nilDeleter{}, nil 13 | } 14 | -------------------------------------------------------------------------------- /insonmnia/worker/gpu/metrics_other.go: -------------------------------------------------------------------------------- 1 | // +build !cl darwin 2 | 3 | package gpu 4 | 5 | func newNvidiaMetricsHandler() (MetricsHandler, error) { 6 | return nilMetricsHandler{}, nil 7 | } 8 | 9 | func newRadeonMetricsHandler() (MetricsHandler, error) { 10 | return nilMetricsHandler{}, nil 11 | } 12 | -------------------------------------------------------------------------------- /proto/init.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | service Init { 8 | rpc Mount(InitMountRequest) returns (InitMountResponse) {} 9 | } 10 | 11 | message InitMountRequest {} 12 | message InitMountResponse {} 13 | -------------------------------------------------------------------------------- /cmd/autocli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | _ "github.com/sonm-io/core/cmd/autocli/proto" 8 | "github.com/sonm-io/core/util/xcode" 9 | ) 10 | 11 | func main() { 12 | if err := xcode.Execute(); err != nil { 13 | fmt.Println(err) 14 | os.Exit(-1) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cmd/cli/commands/version.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | var versionCmd = &cobra.Command{ 8 | Use: "version", 9 | Short: "Show version", 10 | RunE: func(cmd *cobra.Command, args []string) error { 11 | printVersion(cmd, version) 12 | return nil 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /etc/cli.yaml: -------------------------------------------------------------------------------- 1 | # In what format CLI must show their output 2 | # can be "simple" for human-readable messages 3 | # and "json" for output in machine-readable JSON format 4 | output_format: "simple" 5 | 6 | ethereum: 7 | # path to keystore 8 | key_store: "./keys" 9 | # passphrase for keystore 10 | pass_phrase: "any" 11 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/proto_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package tc 4 | 5 | // Actual values doesn't matter for non-linux platforms, because netlink won't 6 | // compile either. 7 | // Use them as a stubs for cross-platform building and testing. 8 | const ( 9 | ProtoAll Protocol = iota 10 | ProtoIP 11 | ) 12 | -------------------------------------------------------------------------------- /connor/antifraud/flags_test.go: -------------------------------------------------------------------------------- 1 | package antifraud 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestFlags(t *testing.T) { 10 | var f flags = SkipBlacklisting 11 | assert.True(t, f.SkipBlacklist()) 12 | 13 | f = AllChecks 14 | assert.False(t, f.SkipBlacklist()) 15 | } 16 | -------------------------------------------------------------------------------- /etc/rendezvous.yaml: -------------------------------------------------------------------------------- 1 | endpoint: "[::]:14099" 2 | 3 | logging: 4 | # The desired logging level. 5 | # Allowed values are "debug", "info", "warn", "error", "panic" and "fatal" 6 | level: debug 7 | 8 | ethereum: 9 | # Path to keystore. 10 | key_store: "./keys" 11 | # Passphrase for keystore 12 | pass_phrase: "any" 13 | -------------------------------------------------------------------------------- /insonmnia/ssh/config.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "github.com/sonm-io/core/insonmnia/npp" 5 | ) 6 | 7 | // ProxyServerConfig specifies SSH proxy server configuration. 8 | type ProxyServerConfig struct { 9 | Addr string `yaml:"endpoint" required:"true"` 10 | NPP npp.Config `yaml:"npp" required:"true"` 11 | } 12 | -------------------------------------------------------------------------------- /insonmnia/gateway/gateway_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package gateway 4 | 5 | import "context" 6 | 7 | const ( 8 | PlatformSupportIPVS = false 9 | ) 10 | 11 | type Gateway struct{} 12 | 13 | func NewGateway(context.Context) (*Gateway, error) { 14 | return &Gateway{}, nil 15 | } 16 | 17 | func (g *Gateway) Close() {} 18 | -------------------------------------------------------------------------------- /insonmnia/npp/nppc/id.go: -------------------------------------------------------------------------------- 1 | package nppc 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | ) 8 | 9 | type ResourceID struct { 10 | Protocol string 11 | Addr common.Address 12 | } 13 | 14 | func (m ResourceID) String() string { 15 | return fmt.Sprintf("%s://%s", m.Protocol, m.Addr.Hex()) 16 | } 17 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/proto.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Protocol int 8 | 9 | func (m Protocol) String() string { 10 | switch m { 11 | case ProtoAll: 12 | return "all" 13 | case ProtoIP: 14 | return "ip" 15 | default: 16 | return fmt.Sprintf("unknown protocol: %d", m) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /proto/node.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import "fmt" 4 | 5 | func (m *TokenTransferRequest) Validate() error { 6 | if m.GetTo().IsZero() { 7 | return fmt.Errorf("destination address must not be zero") 8 | } 9 | if m.GetAmount().IsZero() { 10 | return fmt.Errorf("SNM amount must not be zero") 11 | } 12 | 13 | return nil 14 | } 15 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sonm-io/Platform 2 | *.go @3Hren @antmat @sshaman1101 @oopcode 3 | /debian @3Hren @antmat @sshaman1101 4 | /blockchain/ @sonm-io/solidity 5 | /insonmnia/dwh/ @oopcode 6 | /cmd/cli/ @sshaman1101 7 | /cmd/pandora/ @3Hren 8 | /optimus/ @3Hren 9 | /cmd/sonmmon/ @kmeaw 10 | -------------------------------------------------------------------------------- /insonmnia/hardware/marshal.go: -------------------------------------------------------------------------------- 1 | package hardware 2 | 3 | import ( 4 | "github.com/sonm-io/core/proto" 5 | ) 6 | 7 | func (h *Hardware) IntoProto() *sonm.DevicesReply { 8 | return &sonm.DevicesReply{ 9 | CPU: h.CPU, 10 | GPUs: h.GPU, 11 | RAM: h.RAM, 12 | Network: h.Network, 13 | Storage: h.Storage, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/decodeLogs.js: -------------------------------------------------------------------------------- 1 | const SolidityEvent = require('web3/lib/web3/event.js'); 2 | 3 | export default function decodeLogs (logs, contract, address) { 4 | return logs.map(log => { 5 | const event = new SolidityEvent(null, contract.events[log.topics[0]], address); 6 | return event.decode(log); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /.ci/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | echo "" > coverage.txt 5 | 6 | for d in $(go list ./... | grep -vE 'vendor|blockchain'); do 7 | go test -race -coverprofile=profile.out -covermode=atomic $d 8 | if [ -f profile.out ]; then 9 | cat profile.out >> coverage.txt 10 | rm profile.out 11 | fi 12 | done 13 | -------------------------------------------------------------------------------- /insonmnia/cgroups/cgroup_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package cgroups 4 | 5 | import ( 6 | "github.com/opencontainers/runtime-spec/specs-go" 7 | ) 8 | 9 | const ( 10 | platformSupportCGroups = false 11 | ) 12 | 13 | func initializeControlGroup(name string, resources *specs.LinuxResources) (CGroup, error) { 14 | return &nilCgroup{}, nil 15 | } 16 | -------------------------------------------------------------------------------- /proto/gpu_ctl.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package sonm; 4 | 5 | import "capabilities.proto"; 6 | 7 | 8 | service RemoteGPUTuner { 9 | rpc Devices(RemoteGPUDeviceRequest) returns (RemoteGPUDeviceReply) {} 10 | } 11 | 12 | message RemoteGPUDeviceRequest {} 13 | 14 | message RemoteGPUDeviceReply { 15 | repeated GPUDevice devices = 1; 16 | } 17 | -------------------------------------------------------------------------------- /cmd/cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/sonm-io/core/cmd/cli/commands" 7 | "github.com/sonm-io/core/insonmnia/version" 8 | ) 9 | 10 | func main() { 11 | root := commands.Root(version.Version) 12 | if err := root.Execute(); err != nil { 13 | commands.ShowError(root, err.Error(), nil) 14 | os.Exit(1) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /insonmnia/worker/storage/common.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type QuotaDescription struct { 8 | Bytes uint64 9 | } 10 | 11 | type Cleanup interface { 12 | Close() error 13 | } 14 | 15 | type StorageQuotaTuner interface { 16 | SetQuota(ctx context.Context, ID string, quotaID string, bytes uint64) (Cleanup, error) 17 | } 18 | -------------------------------------------------------------------------------- /blockchain/source/.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | norpc: true, 3 | copyNodeModules: true, 4 | testCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle test --network coverage', 5 | compileCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle compile --network coverage', 6 | skipFiles: ['contracts/Migrations.sol'] 7 | }; 8 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/assertRevert.js: -------------------------------------------------------------------------------- 1 | export default async promise => { 2 | try { 3 | await promise; 4 | assert.fail('Expected revert not received'); 5 | } catch (error) { 6 | const revertFound = error.message.search('revert') >= 0; 7 | assert(revertFound, `Expected "revert", got ${error} instead`); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /debian/sonm-connor.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Connor 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-connor 9 | Type=simple 10 | ExecStart=/usr/bin/sonmconnor --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /debian/sonm-oracle.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Oracle 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-oracle 9 | Type=simple 10 | ExecStart=/usr/bin/sonmoracle --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /debian/sonm-worker.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Worker 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-worker 9 | Type=simple 10 | ExecStart=/usr/bin/sonmworker --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /secexec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "secexec" 3 | version = "0.1.0" 4 | authors = ["Evgeny Safronov "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | clap = "2" 10 | libc = "0.2" 11 | caps = "0.3" 12 | sha2 = "0.8" 13 | seccomp-sys = "0.1" 14 | serde = { version = "1", features = ["derive"] } 15 | serde_yaml = "0.8" 16 | -------------------------------------------------------------------------------- /debian/sonm-node.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Node 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-node 9 | Type=simple 10 | ExecStart=/usr/bin/sonmnode --config=${CONFIG_PATH} 11 | User=sonm 12 | Restart=on-failure 13 | 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /debian/sonm-optimus.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Optimus 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-optimus 9 | Type=simple 10 | ExecStart=/usr/bin/sonmoptimus --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /debian/sonm-dwh.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM DWH 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-dwh 9 | Type=simple 10 | ExecStart=/usr/bin/sonmdwh --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | LimitNOFILE=65535 13 | 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /proto/volume.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | // Volume describes volume settings. 8 | message Volume { 9 | // Type describes a volume driver. 10 | string type = 1; 11 | // Options describes a place for your volume settings. 12 | map options = 2; 13 | } 14 | -------------------------------------------------------------------------------- /util/action/action.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | // Action is an abstraction of some action that can be rolled back. 8 | type Action interface { 9 | // Execute executes this action, returning error if any. 10 | Execute(ctx context.Context) error 11 | // Rollback rollbacks this action, returning error if any. 12 | Rollback() error 13 | } 14 | -------------------------------------------------------------------------------- /debian/sonm-relay.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Relay 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-relay 9 | Type=simple 10 | ExecStart=/usr/bin/sonmrelay --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | LimitNOFILE=65535 13 | 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /cmd/pandora/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type LoggingConfig struct { 4 | Level string `config:"level"` 5 | } 6 | 7 | type EthereumConfig struct { 8 | Endpoint string `config:"endpoint"` 9 | AccountType string `config:"account_type"` 10 | AccountPath string `config:"account_path"` 11 | AccountPass string `config:"account_pass"` 12 | Registry string `config:"registry"` 13 | } 14 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2018 SONM 2 | 3 | This file is part of sonm-core. 4 | 5 | You should have received a copy of the Apache License Version 2.0 6 | along with this program. If not, see . 7 | 8 | On Debian systems, the complete text of the Apache License Version 2.0 9 | Public License can be found in "/usr/share/common-licenses/Apache-2.0" 10 | -------------------------------------------------------------------------------- /optimus/matrix.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | type row = []float64 4 | type matrix = []row 5 | 6 | func transpose(m matrix) matrix { 7 | if len(m) == 0 { 8 | return m 9 | } 10 | r := make(matrix, len(m[0])) 11 | for x := range r { 12 | r[x] = make(row, len(m)) 13 | } 14 | for y, s := range m { 15 | for x, e := range s { 16 | r[x][y] = e 17 | } 18 | } 19 | return r 20 | } 21 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/assertJump.js: -------------------------------------------------------------------------------- 1 | export default async promise => { 2 | try { 3 | await promise; 4 | assert.fail('Expected invalid opcode not received'); 5 | } catch (error) { 6 | const invalidOpcodeReceived = error.message.search('invalid opcode') >= 0; 7 | assert(invalidOpcodeReceived, `Expected "invalid opcode", got ${error} instead`); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /debian/sonm-rendezvous.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM Rendezvous 3 | Wants=network-online.target 4 | After=network.target network-online.target 5 | 6 | 7 | [Service] 8 | EnvironmentFile=/etc/default/sonm-rendezvous 9 | Type=simple 10 | ExecStart=/usr/bin/sonmrendezvous --config=${CONFIG_PATH} 11 | Restart=on-failure 12 | LimitNOFILE=65535 13 | 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /secexec/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Secured execution of arbitrary commands. 2 | //! 3 | //! This library contains functionality that allows executing processes in a 4 | //! jailed environment, restricting their capabilities and allowed syscalls, 5 | //! to prevent leaking sensitive information. 6 | 7 | pub use crate::{cfg::Config, exec::Executor}; 8 | 9 | mod cfg; 10 | mod exec; 11 | pub mod prctl; 12 | pub mod seccomp; 13 | -------------------------------------------------------------------------------- /insonmnia/hardware/ram/device.go: -------------------------------------------------------------------------------- 1 | package ram 2 | 3 | import ( 4 | "github.com/shirou/gopsutil/mem" 5 | "github.com/sonm-io/core/proto" 6 | ) 7 | 8 | func NewRAMDevice() (*sonm.RAMDevice, error) { 9 | m, err := mem.VirtualMemory() 10 | if err != nil { 11 | return nil, err 12 | } 13 | 14 | return &sonm.RAMDevice{ 15 | Total: m.Total, 16 | Available: m.Total, 17 | Used: m.Used, 18 | }, nil 19 | } 20 | -------------------------------------------------------------------------------- /accounts/config.go: -------------------------------------------------------------------------------- 1 | package accounts 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | ) 6 | 7 | type EthConfig struct { 8 | Passphrase string `required:"false" default:"" yaml:"pass_phrase"` 9 | Keystore string `required:"false" default:"" yaml:"key_store"` 10 | } 11 | 12 | func (c *EthConfig) LoadKey() (*ecdsa.PrivateKey, error) { 13 | return OpenSingleKeystore(c.Keystore, c.Passphrase, NewInteractivePassPhraser()) 14 | } 15 | -------------------------------------------------------------------------------- /cmd/common.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | ) 10 | 11 | func WaitInterrupted(ctx context.Context) error { 12 | sigChan := make(chan os.Signal, 1) 13 | signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) 14 | 15 | select { 16 | case v := <-sigChan: 17 | return errors.New(v.String()) 18 | case <-ctx.Done(): 19 | return ctx.Err() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /insonmnia/worker/gpu/tuner_other.go: -------------------------------------------------------------------------------- 1 | // +build !cl darwin 2 | 3 | package gpu 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | // override all Tuner implementation with NilTuner if we building without GPU support 10 | 11 | func newRadeonTuner(_ context.Context, opts ...Option) (Tuner, error) { 12 | return NilTuner{}, nil 13 | } 14 | 15 | func newNvidiaTuner(_ context.Context, opts ...Option) (Tuner, error) { 16 | return NilTuner{}, nil 17 | } 18 | -------------------------------------------------------------------------------- /insonmnia/dwh/util.go: -------------------------------------------------------------------------------- 1 | package dwh 2 | 3 | import "fmt" 4 | 5 | const ( 6 | CertificateName = 1102 7 | CertificateCountry = 1303 8 | MaxBenchmark uint64 = 1 << 63 9 | ) 10 | 11 | var ( 12 | attributeToString = map[uint64]string{ 13 | CertificateName: "Name", 14 | CertificateCountry: "Country", 15 | } 16 | ) 17 | 18 | func getBenchmarkColumn(id uint64) string { 19 | return fmt.Sprintf("Benchmark%d", id) 20 | } 21 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/hashMessage.js: -------------------------------------------------------------------------------- 1 | import utils from 'ethereumjs-util'; 2 | 3 | // Hash and add same prefix to the hash that testrpc use. 4 | module.exports = function (message) { 5 | const messageHex = Buffer.from(utils.sha3(message).toString('hex'), 'hex'); 6 | const prefix = utils.toBuffer('\u0019Ethereum Signed Message:\n' + messageHex.length.toString()); 7 | return utils.bufferToHex(utils.sha3(Buffer.concat([prefix, messageHex]))); 8 | }; 9 | -------------------------------------------------------------------------------- /blockchain/source/.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:recommended", 3 | "plugins": [ 4 | "security" 5 | ], 6 | "rules": { 7 | "quotes": [ 8 | "error", 9 | "double" 10 | ], 11 | "indentation": [ 12 | "error", 13 | 4 14 | ], 15 | "emit": [ 16 | "off" 17 | ], 18 | "error-reason": [ 19 | "off" 20 | ], 21 | "security/no-block-members": [ 22 | "off" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /insonmnia/worker/storage/quotafactory_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package storage 4 | 5 | import ( 6 | "fmt" 7 | "runtime" 8 | 9 | "github.com/docker/docker/api/types" 10 | ) 11 | 12 | // PlatformSupportsQuota says if the platform supports quota 13 | var PlatformSupportsQuota = false 14 | 15 | func NewQuotaTuner(info types.Info) (StorageQuotaTuner, error) { 16 | return nil, fmt.Errorf("quota not supported by this platform: %s", runtime.GOOS) 17 | } 18 | -------------------------------------------------------------------------------- /blockchain/source/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | const TruffleConfig = require('../truffle'); 3 | 4 | module.exports = function (deployer, network) { 5 | // Deploy the Migrations contract as our only task 6 | if (TruffleConfig.isSidechain(network)) { 7 | deployer.deploy(Migrations, { gasPrice: 0 }); 8 | } else { 9 | deployer.deploy(Migrations, { gas: 500000 }); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/qdisc_test.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestPfifoCmd(t *testing.T) { 10 | qdisc := &PfifoQDisc{ 11 | QDiscAttrs: QDiscAttrs{ 12 | Link: nil, 13 | Handle: NewHandle(0x8001, 0), 14 | Parent: HandleRoot, 15 | }, 16 | Limit: 42, 17 | } 18 | assert.Equal(t, []string{"parent", "root", "handle", "8001:0", "pfifo", "limit", "42"}, qdisc.Cmd()) 19 | } 20 | -------------------------------------------------------------------------------- /proto/optimus.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func (m *PredictSupplierRequest) Validate() error { 8 | if len(m.GetDevices().GetGPUs()) > 16 { 9 | return fmt.Errorf("number of GPUs must be <= 16") 10 | } 11 | 12 | return nil 13 | } 14 | 15 | func (m *PredictSupplierRequest) Normalize() { 16 | for id, dev := range m.GetDevices().GetGPUs() { 17 | dev.GetDevice().ID = fmt.Sprintf("%x", id) 18 | dev.GetDevice().FillHashID() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /etc/secexec/cat.yaml: -------------------------------------------------------------------------------- 1 | checksum: 6af93ff8a2f25940121064d31815ac282c25731febedc63f965c2806d3630204d940210c031dd544e74554138b221ce10bac39214fbd2a018fc721f61a644e5b 2 | syscalls: 3 | read: [] 4 | write: 5 | - arg: 0 6 | op: eq 7 | a: 1 8 | - arg: 0 9 | op: eq 10 | a: 2 11 | close: [] 12 | fstat: [] 13 | mmap: [] 14 | mprotect: [] 15 | munmap: [] 16 | brk: [] 17 | access: [] 18 | arch_prctl: [] 19 | fadvise64: [] 20 | openat: [] 21 | -------------------------------------------------------------------------------- /secsh/config.go: -------------------------------------------------------------------------------- 1 | package secsh 2 | 3 | import ( 4 | "github.com/sonm-io/core/accounts" 5 | "github.com/sonm-io/core/insonmnia/npp" 6 | ) 7 | 8 | type Config struct { 9 | SecExecPath string `yaml:"secexec"` 10 | SeccompPolicyDir string `yaml:"seccomp_policy_dir"` 11 | AllowedKeys []string `yaml:"allowed_keys"` 12 | Eth accounts.EthConfig `yaml:"ethereum"` 13 | NPP npp.Config `yaml:"npp"` 14 | } 15 | -------------------------------------------------------------------------------- /keys/example.key: -------------------------------------------------------------------------------- 1 | {"address":"8125721c2413d99a33e351e1f6bb4e56b6b633fd","crypto":{"cipher":"aes-128-ctr","ciphertext":"ee00310ad9ab03f7b85cbabf72b919c7ed15f80b71f9531c167823995b28057a","cipherparams":{"iv":"67365b4d1ba21d457f3dbb22e46b627a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"0b28c47f7b5cf61be98e157c1f12d52e039120c28f42d50291f4674dc262ef8f"},"mac":"5f370bb0bcc879ed0db74716cbd24861ab0a9839e6985b82f9c2b48a127b6453"},"id":"c0137aac-b22c-42f0-9b42-192af24fe103","version":3} -------------------------------------------------------------------------------- /insonmnia/worker/gpu/dri_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package gpu 4 | 5 | import ( 6 | "fmt" 7 | "syscall" 8 | ) 9 | 10 | func deviceNumber(path string) (uint64, uint64, error) { 11 | stat := syscall.Stat_t{} 12 | err := syscall.Stat(path, &stat) 13 | if err != nil { 14 | return 0, 0, fmt.Errorf("cannot get device major:minor numbers: %v", err) 15 | } 16 | 17 | major := uint64(stat.Rdev / 256) 18 | minor := uint64(stat.Rdev % 256) 19 | 20 | return major, minor, nil 21 | } 22 | -------------------------------------------------------------------------------- /insonmnia/worker/storage/quotafactory_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package storage 4 | 5 | import ( 6 | "github.com/docker/docker/api/types" 7 | ) 8 | 9 | // PlatformSupportsQuota says if the platform supports quota 10 | var PlatformSupportsQuota = true 11 | 12 | func NewQuotaTuner(info types.Info) (StorageQuotaTuner, error) { 13 | switch info.Driver { 14 | case "btrfs": 15 | return newBtrfsQuotaTuner(info) 16 | default: 17 | return nil, ErrDriverNotSupported{driver: info.Driver} 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /secsh/secshc/config.go: -------------------------------------------------------------------------------- 1 | package secshc 2 | 3 | import ( 4 | "github.com/jinzhu/configor" 5 | "github.com/sonm-io/core/accounts" 6 | "github.com/sonm-io/core/insonmnia/npp" 7 | ) 8 | 9 | type RPTYConfig struct { 10 | Eth accounts.EthConfig `yaml:"ethereum"` 11 | NPP npp.Config `yaml:"npp"` 12 | } 13 | 14 | func NewRPTYConfig(path string) (*RPTYConfig, error) { 15 | cfg := &RPTYConfig{} 16 | if err := configor.Load(cfg, path); err != nil { 17 | return nil, err 18 | } 19 | 20 | return cfg, nil 21 | } 22 | -------------------------------------------------------------------------------- /insonmnia/hardware/gpu/device.go: -------------------------------------------------------------------------------- 1 | package gpu 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/sonm-io/core/proto" 7 | ) 8 | 9 | var ( 10 | ErrUnsupportedPlatform = errors.New("the platform is not currently supported to expose GPU devices") 11 | ) 12 | 13 | // GetGPUDevices returns a list of available GPU devices on the machine. 14 | func GetGPUDevices() ([]*sonm.GPUDevice, error) { 15 | devices, err := GetGPUDevicesUsingOpenCL() 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | return devices, nil 21 | } 22 | -------------------------------------------------------------------------------- /util/xgrpc/method.go: -------------------------------------------------------------------------------- 1 | package xgrpc 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | type MethodInfo struct { 8 | Service string 9 | Method string 10 | } 11 | 12 | func (m *MethodInfo) IntoTuple() (string, string) { 13 | return m.Service, m.Method 14 | } 15 | 16 | func ParseMethodInfo(fullMethod string) *MethodInfo { 17 | parts := strings.SplitN(fullMethod, "/", 3) 18 | if len(parts) != 3 { 19 | return nil 20 | } 21 | 22 | m := &MethodInfo{ 23 | Service: parts[1], 24 | Method: parts[2], 25 | } 26 | 27 | return m 28 | } 29 | -------------------------------------------------------------------------------- /debian/sonm-node.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | case $1 in 6 | configure) 7 | if ! getent passwd sonm >/dev/null; then 8 | useradd --user-group --no-create-home --shell /usr/sbin/nologin sonm 9 | fi 10 | 11 | chown -R sonm /var/{lib,run}/sonm 12 | ;; 13 | 14 | abort-upgrade|abort-remove|abort-deconfigure) 15 | ;; 16 | 17 | *) 18 | echo "postinst called with an unknown argument \`$1'" >&2 19 | ;; 20 | esac 21 | 22 | #DEBHELPER# 23 | 24 | exit 0 25 | -------------------------------------------------------------------------------- /blockchain/source/contracts/AddressHashMap.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | 4 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 5 | 6 | 7 | contract AddressHashMap is Ownable { 8 | mapping(bytes32 => address) map; 9 | constructor(){ 10 | owner = msg.sender; 11 | } 12 | 13 | function write(bytes32 _key, address _value) public onlyOwner { 14 | map[_key] = _value; 15 | } 16 | 17 | function read(bytes32 _key) public view returns (address){ 18 | return map[_key]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /blockchain/source/contracts/test/Dummy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | import "../Administratable.sol"; 4 | 5 | contract Dummy is Administratable { 6 | 7 | event Call(string method); 8 | 9 | function testOnlyOwner() public onlyOwner { 10 | emit Call("onlyOwner"); 11 | } 12 | 13 | function testPublic() public returns (bool) { 14 | emit Call("public"); 15 | } 16 | 17 | function testOwnerOrAdministrator() public ownerOrAdministrator returns (bool) { 18 | emit Call("ownerOrAdministrator"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cmd/cli/commands/worker_tasks.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sonm-io/core/proto" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var workerTasksCmd = &cobra.Command{ 11 | Use: "tasks", 12 | Short: "Show tasks running on Worker", 13 | RunE: func(cmd *cobra.Command, args []string) error { 14 | list, err := worker.Tasks(workerCtx, &sonm.Empty{}) 15 | if err != nil { 16 | return fmt.Errorf("cannot get task list: %v", err) 17 | } 18 | 19 | printTaskStatuses(cmd, list.GetInfo()) 20 | return nil 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /util/metadata.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/metadata" 7 | ) 8 | 9 | // ForwardMetadata is a helper function for gRPC proxy that chains incoming 10 | // request with some outgoing request. 11 | // It simply forwards incoming context metadata without changes by toggling 12 | // internal outgoing key. 13 | func ForwardMetadata(ctx context.Context) context.Context { 14 | md, ok := metadata.FromIncomingContext(ctx) 15 | if !ok { 16 | return ctx 17 | } 18 | 19 | return metadata.NewOutgoingContext(ctx, md) 20 | } 21 | -------------------------------------------------------------------------------- /etc/dwh.yaml: -------------------------------------------------------------------------------- 1 | grpc_address: ":15021" 2 | 3 | http_address: ":15022" 4 | 5 | storage: 6 | endpoint: "postgresql://localhost:5432/dwh?user=dwh&password=dwh&sslmode=disable" 7 | 8 | # blockchain-specific settings. 9 | ethereum: 10 | # path to keystore 11 | key_store: "./keys" 12 | # passphrase for keystore 13 | pass_phrase: "any" 14 | 15 | blockchain: 16 | blocks_batch_size: 500000 17 | 18 | logging: 19 | # The desired logging level. 20 | # Allowed values are "debug", "info", "warn", "error", "panic" and "fatal" 21 | level: "info" 22 | 23 | enable_rest: true 24 | -------------------------------------------------------------------------------- /insonmnia/npp/common.go: -------------------------------------------------------------------------------- 1 | package npp 2 | 3 | type connSource int 4 | 5 | const ( 6 | sourceError connSource = iota 7 | sourceDirectConnection 8 | sourceNPPConnection 9 | sourceRelayedConnection 10 | sourceNPPQUICConnection 11 | ) 12 | 13 | func (m connSource) String() string { 14 | switch m { 15 | case sourceDirectConnection: 16 | return "direct" 17 | case sourceNPPConnection: 18 | return "npp" 19 | case sourceRelayedConnection: 20 | return "relay" 21 | case sourceNPPQUICConnection: 22 | return "npp/quic" 23 | default: 24 | return "unknown source" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /optimus/options.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import "go.uber.org/zap" 4 | 5 | type Option func(o *options) 6 | 7 | type options struct { 8 | Version string 9 | Log *zap.SugaredLogger 10 | } 11 | 12 | func newOptions() *options { 13 | return &options{ 14 | Version: "unspecified", 15 | Log: zap.NewNop().Sugar(), 16 | } 17 | } 18 | 19 | func WithVersion(version string) Option { 20 | return func(o *options) { 21 | o.Version = version 22 | } 23 | } 24 | 25 | func WithLog(log *zap.SugaredLogger) Option { 26 | return func(o *options) { 27 | o.Log = log 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | ALex Nikonov 2 | ALex Nikonov Alex Nikonov 3 | Andrew Zavgorodny 4 | Andrew Zavgorodny 5 | Andrew Zavgorodny 6 | Anton Matveenko 7 | Anton Tiurin Anton Tyurin 8 | Antony Shchukin Anton Shchukin 9 | DoctorCotic 10 | DoctorCotic 11 | DoctorCotic 12 | -------------------------------------------------------------------------------- /cmd/cli/task_config/config.go: -------------------------------------------------------------------------------- 1 | package task_config 2 | 3 | import ( 4 | "github.com/sonm-io/core/proto" 5 | "github.com/sonm-io/core/util/config" 6 | ) 7 | 8 | func LoadConfig(path string) (*sonm.TaskSpec, error) { 9 | // Manual renaming from snake_case to lowercase fields here to be able to 10 | // load them directly in the protobuf. 11 | cfg := &sonm.TaskSpec{} 12 | if err := config.LoadWith(cfg, path, config.SnakeToLower); err != nil { 13 | return nil, err 14 | } 15 | 16 | if err := cfg.Validate(); err != nil { 17 | return nil, err 18 | } 19 | 20 | return cfg, nil 21 | } 22 | -------------------------------------------------------------------------------- /optimus/tagging.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sonm-io/core/proto" 7 | ) 8 | 9 | type Tagger struct { 10 | value []byte 11 | } 12 | 13 | func newTagger(version string) *Tagger { 14 | return &Tagger{ 15 | value: makeTag(version), 16 | } 17 | } 18 | 19 | func (m *Tagger) Tag() []byte { 20 | return m.value 21 | } 22 | 23 | func makeTag(version string) []byte { 24 | value := fmt.Sprintf("optimus/%s", version) 25 | 26 | if len(value) < sonm.MaxTagLength { 27 | return []byte(value) 28 | } 29 | 30 | return []byte(value[:sonm.MaxTagLength]) 31 | } 32 | -------------------------------------------------------------------------------- /util/xgrpc/credentials.go: -------------------------------------------------------------------------------- 1 | package xgrpc 2 | 3 | import ( 4 | "crypto/tls" 5 | 6 | . "github.com/sonm-io/core/util" 7 | "google.golang.org/grpc/credentials" 8 | ) 9 | 10 | // TransportCredentials wraps the standard transport credentials, adding an 11 | // ability to obtain the TLS config used. 12 | type TransportCredentials struct { 13 | credentials.TransportCredentials 14 | TLSConfig *tls.Config 15 | } 16 | 17 | func NewTransportCredentials(cfg *tls.Config) *TransportCredentials { 18 | return &TransportCredentials{ 19 | TransportCredentials: NewTLS(cfg), 20 | TLSConfig: cfg, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blockchain/source/contracts/SNM.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | 4 | import "zeppelin-solidity/contracts/token/ERC20/StandardToken.sol"; 5 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 6 | 7 | 8 | contract SNM is StandardToken, Ownable { 9 | 10 | using SafeMath for uint256; 11 | 12 | string public name = "SONM token"; 13 | 14 | string public symbol = "SNM"; 15 | 16 | uint public decimals = 18; 17 | 18 | constructor() public { 19 | owner = msg.sender; 20 | totalSupply_ = 444 * 1e6 * 1e18; 21 | balances[msg.sender] = totalSupply_; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /proto/optimus.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | import "bigint.proto"; 6 | import "insonmnia.proto"; 7 | import "marketplace.proto"; 8 | import "worker.proto"; 9 | 10 | package sonm; 11 | 12 | service OrderPredictor { 13 | rpc Predict(BidResources) returns (Price) {} 14 | rpc PredictSupplier(PredictSupplierRequest) returns (PredictSupplierReply) {} 15 | } 16 | 17 | message PredictSupplierRequest { 18 | DevicesReply devices = 1; 19 | } 20 | 21 | message PredictSupplierReply { 22 | Price price = 1; 23 | repeated BigInt orderIDs = 2; 24 | } 25 | -------------------------------------------------------------------------------- /etc/secexec/grep.yaml: -------------------------------------------------------------------------------- 1 | checksum: 1e6173ba6af22cb209e23dee025f7967f777ba22c64f773131885c2768f7f1d48af7a3fcdf1345f3883647786a723be8556a0cf0a902fbfb18c281da71f51c76 2 | syscalls: 3 | mmap: [] 4 | mprotect: [] 5 | openat: [] 6 | fstat: [] 7 | close: [] 8 | access: [] 9 | read: [] 10 | munmap: [] 11 | brk: [] 12 | write: 13 | - arg: 0 14 | op: eq 15 | a: 1 16 | - arg: 0 17 | op: eq 18 | a: 2 19 | rt_sigaction: [] 20 | stat: [] 21 | rt_sigprocmask: [] 22 | futex: [] 23 | set_tid_address: [] 24 | arch_prctl: [] 25 | set_robust_list: [] 26 | prlimit64: [] 27 | lseek: [] 28 | -------------------------------------------------------------------------------- /util/xdocker/reference_test.go: -------------------------------------------------------------------------------- 1 | package xdocker 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestReferenceMarshalUnmarshal(t *testing.T) { 11 | refStr := "httpd:latest" 12 | ref, err := NewReference(refStr) 13 | require.NoError(t, err) 14 | data, err := json.Marshal(&ref) 15 | require.NoError(t, err) 16 | require.Equal(t, "\"docker.io/library/httpd:latest\"", string(data)) 17 | 18 | ref2 := &Reference{} 19 | err = json.Unmarshal(data, ref2) 20 | require.NoError(t, err) 21 | require.Equal(t, "docker.io/library/httpd:latest", ref2.String()) 22 | } 23 | -------------------------------------------------------------------------------- /blockchain/source/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 3 | 4 | contract Migrations is Ownable { 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | function setCompleted(uint completed) public onlyOwner { 12 | last_completed_migration = completed; 13 | } 14 | 15 | function upgrade(address new_address) public onlyOwner { 16 | Migrations upgraded = Migrations(new_address); 17 | upgraded.setCompleted(last_completed_migration); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tinc_config.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type TincNetworkConfig struct { 4 | Enabled bool `yaml:"enabled"` 5 | ConfigDir string `yaml:"config_dir" default:"/tinc"` 6 | DockerNetPluginSockPath string `yaml:"docker_net_plugin_dir" default:"/run/docker/plugins/tinc/tinc.sock"` 7 | DockerIPAMPluginSockPath string `yaml:"docker_ipam_plugin_dir" default:"/run/docker/plugins/tincipam/tincipam.sock"` 8 | DockerImage string `yaml:"docker_image" default:"sonm/tinc"` 9 | StatePath string `yaml:"state_path" default:"/var/lib/sonm/tinc_network_state"` 10 | } 11 | -------------------------------------------------------------------------------- /proto/net.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | message Addr { 8 | // Protocol describes the underlying transport protocol, for example "tcp" 9 | // or "udp". 10 | string protocol = 1; 11 | SocketAddr addr = 2; 12 | } 13 | 14 | message SocketAddr { 15 | // Addr describes an IP address. 16 | string addr = 1; 17 | // Port describes a port number. 18 | // Actually an `uint16` here. Protobuf is so clear and handy. 19 | uint32 port = 2; 20 | } 21 | 22 | message Endpoints { 23 | repeated SocketAddr endpoints = 1; 24 | } 25 | -------------------------------------------------------------------------------- /proto/timestamp.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | message Timestamp { 8 | // Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. 9 | // Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. 10 | int64 seconds = 1; 11 | 12 | // Non-negative fractions of a second at nanosecond resolution. Negative 13 | // second values with fractions must still have non-negative nanos values 14 | // that count forward in time. Must be from 0 to 999'999'999 15 | // inclusive. 16 | int32 nanos = 2; 17 | } 18 | -------------------------------------------------------------------------------- /ask.yaml: -------------------------------------------------------------------------------- 1 | duration: 8h 2 | price: 23.73 USD/h 3 | 4 | blacklist: 0x8125721c2413d99a33e351e1f6bb4e56b6b633fd 5 | 6 | # optional - restricts selling resources only to specified address 7 | # counterparty: 0x8125721c2413d99a33e351e1f6bb4e56b6b61567 8 | identity: anonymous 9 | 10 | resources: 11 | cpu: 12 | # Number of cores to assign for this plan, can be fractional 13 | cores: 1.5 14 | ram: 15 | size: 2GB 16 | storage: 17 | size: 10GB 18 | gpu: 19 | indexes: [3, 5] 20 | network: 21 | throughputin: 25 Mbit/s 22 | throughputout: 40 Mbit/s 23 | overlay: true 24 | outbound: true 25 | incoming: true 26 | -------------------------------------------------------------------------------- /insonmnia/logging/config.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import "os" 4 | 5 | const ( 6 | StdoutLogOutput = "stdout" 7 | StderrLogOutput = "stderr" 8 | ) 9 | 10 | // Config represents a logging config. 11 | type Config struct { 12 | Level *Level `yaml:"level" required:"true" default:"info"` 13 | Output string `yaml:"output" default:"stdout"` 14 | } 15 | 16 | func (m *Config) LogLevel() Level { 17 | return *m.Level 18 | } 19 | 20 | func fdFromString(out string) *os.File { 21 | switch out { 22 | case StderrLogOutput: 23 | return os.Stderr 24 | case StdoutLogOutput: 25 | return os.Stdout 26 | default: 27 | return nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cmd/cli/task_config/load_order.go: -------------------------------------------------------------------------------- 1 | package task_config 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | 7 | "gopkg.in/yaml.v2" 8 | ) 9 | 10 | func LoadFromFile(path string, into interface{}) error { 11 | data, err := ioutil.ReadFile(path) 12 | if err != nil { 13 | return err 14 | } 15 | 16 | decoder := yaml.NewDecoder(bytes.NewBuffer(data)) 17 | decoder.SetStrict(true) 18 | 19 | if err := decoder.Decode(into); err != nil { 20 | return err 21 | } 22 | 23 | if v, ok := into.(interface { 24 | Validate() error 25 | }); ok { 26 | if err := v.Validate(); err != nil { 27 | return err 28 | } 29 | } 30 | 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /blockchain/source/contracts/OracleUSD.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | 4 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 5 | 6 | 7 | contract OracleUSD is Ownable { 8 | 9 | uint currentPrice = 1; 10 | 11 | event PriceChanged(uint price); 12 | 13 | constructor() public{ 14 | owner = msg.sender; 15 | } 16 | 17 | function setCurrentPrice(uint _price) public onlyOwner{ 18 | require(_price > 0); 19 | currentPrice = _price; 20 | emit PriceChanged(_price); 21 | } 22 | 23 | function getCurrentPrice() public view returns (uint){ 24 | return currentPrice; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /proto/gpu_device.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | var Radeons = []uint64{ 4 | 4098, 5 | // macbook pro 2017 6 | 16915456, 7 | } 8 | 9 | var Nvidias = []uint64{ 10 | 4318, 11 | } 12 | 13 | func TypeFromVendorID(v uint64) GPUVendorType { 14 | for _, id := range Radeons { 15 | if id == v { 16 | return GPUVendorType_RADEON 17 | } 18 | } 19 | 20 | for _, id := range Nvidias { 21 | if id == v { 22 | return GPUVendorType_NVIDIA 23 | } 24 | } 25 | 26 | return GPUVendorType_GPU_UNKNOWN 27 | } 28 | 29 | // VendorType returns GPU vendor type. 30 | func (m *GPUDevice) VendorType() GPUVendorType { 31 | return TypeFromVendorID(m.VendorID) 32 | } 33 | -------------------------------------------------------------------------------- /insonmnia/npp/config.go: -------------------------------------------------------------------------------- 1 | package npp 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sonm-io/core/insonmnia/npp/relay" 7 | "github.com/sonm-io/core/insonmnia/npp/rendezvous" 8 | ) 9 | 10 | // Config represents an NPP (NAT punching protocol) module configuration. 11 | type Config struct { 12 | Rendezvous rendezvous.Config `yaml:"rendezvous"` 13 | Relay relay.Config `yaml:"relay"` 14 | Backlog int `yaml:"backlog" default:"128"` 15 | MinBackoffInterval time.Duration `yaml:"min_backoff_interval" default:"500ms"` 16 | MaxBackoffInterval time.Duration `yaml:"max_backoff_interval" default:"8000ms"` 17 | } 18 | -------------------------------------------------------------------------------- /proto/pty.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | service RemotePTY { 8 | rpc Banner(RemotePTYBannerRequest) returns (RemotePTYBannerResponse) {} 9 | rpc Exec(RemotePTYExecRequest) returns (stream RemotePTYExecResponseChunk) {} 10 | } 11 | 12 | message RemotePTYBannerRequest {} 13 | 14 | message RemotePTYBannerResponse { 15 | string banner = 1; 16 | } 17 | 18 | message RemotePTYExecRequest { 19 | repeated string args = 1; 20 | repeated string envp = 2; 21 | } 22 | 23 | message RemotePTYExecResponseChunk { 24 | bytes out = 1; 25 | bool done = 2; 26 | } 27 | -------------------------------------------------------------------------------- /insonmnia/npp/error.go: -------------------------------------------------------------------------------- 1 | package npp 2 | 3 | type rendezvousError struct { 4 | error 5 | } 6 | 7 | func newRendezvousError(err error) error { 8 | if err == nil { 9 | return nil 10 | } 11 | 12 | return &rendezvousError{err} 13 | } 14 | 15 | type relayError struct { 16 | error 17 | } 18 | 19 | func newRelayError(err error) error { 20 | if err == nil { 21 | return nil 22 | } 23 | 24 | return &relayError{err} 25 | } 26 | 27 | // Temporary returns true if this error is temporary. 28 | // 29 | // Used to trick into submission gRPC's machinery about exponentially delaying 30 | // failed connections. 31 | func (m *relayError) Temporary() bool { 32 | return true 33 | } 34 | -------------------------------------------------------------------------------- /proto/gpu_device_test.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | var deviceIdsTable = []struct { 11 | id uint64 12 | t GPUVendorType 13 | }{ 14 | {id: 4098, t: GPUVendorType_RADEON}, 15 | {id: 16915456, t: GPUVendorType_RADEON}, 16 | {id: 4318, t: GPUVendorType_NVIDIA}, 17 | {id: 16925952, t: GPUVendorType_GPU_UNKNOWN}, 18 | } 19 | 20 | func TestGpuTypeFromVendorID(t *testing.T) { 21 | for _, cc := range deviceIdsTable { 22 | gpuType := TypeFromVendorID(cc.id) 23 | assert.Equal(t, gpuType, cc.t, fmt.Sprintf("required %v, given %v", 24 | cc.t.String(), gpuType.String())) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /secsh/watch.go: -------------------------------------------------------------------------------- 1 | package secsh 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "time" 7 | 8 | "go.uber.org/zap" 9 | ) 10 | 11 | // WatchDir blocks until either the directory on the specified path are made 12 | // exist or the context is canceled. 13 | func WatchDir(ctx context.Context, path string, interval time.Duration, log *zap.SugaredLogger) error { 14 | timer := time.NewTicker(interval) 15 | defer timer.Stop() 16 | 17 | for { 18 | select { 19 | case <-ctx.Done(): 20 | return ctx.Err() 21 | case <-timer.C: 22 | if _, err := os.Stat(path); err == nil { 23 | return nil 24 | } 25 | 26 | log.Infof("path %s not exists, waiting", path) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cmd/cli/commands/completion.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var autoCompleteCmd = &cobra.Command{ 11 | Use: "completion ", 12 | Short: "Generate shell-completion script", 13 | Args: cobra.MinimumNArgs(1), 14 | RunE: func(cmd *cobra.Command, args []string) error { 15 | var err error 16 | shell := args[0] 17 | 18 | switch shell { 19 | case "zsh": 20 | err = rootCmd.GenZshCompletion(os.Stdout) 21 | case "bash": 22 | err = rootCmd.GenBashCompletion(os.Stdout) 23 | default: 24 | err = fmt.Errorf("unknown shell type `%s`", shell) 25 | } 26 | 27 | return err 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /debian/sonm-mon.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SONM monitor 3 | After=plymouth-quit-wait.service getty-pre.target 4 | After=rc-local.service 5 | Before=getty.target 6 | IgnoreOnIsolate=yes 7 | Conflicts=rescue.service 8 | Before=rescue.service 9 | ConditionPathExists=/dev/tty0 10 | 11 | [Service] 12 | ExecStart=-/usr/bin/sonmmon 13 | Type=idle 14 | Restart=always 15 | RestartSec=10 16 | UtmpIdentifier=tty7 17 | TTYPath=/dev/tty7 18 | TTYReset=yes 19 | TTYVHangup=yes 20 | TTYVTDisallocate=yes 21 | IgnoreSIGPIPE=no 22 | # User=sonmmon 23 | PermissionsStartOnly=true 24 | WorkingDirectory=/usr/share/sonmmon 25 | EnvironmentFile=/etc/environment 26 | 27 | [Install] 28 | WantedBy=getty.target 29 | -------------------------------------------------------------------------------- /insonmnia/worker/plugin/config.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import "github.com/sonm-io/core/insonmnia/worker/network" 4 | 5 | type Config struct { 6 | SocketDir string `yaml:"socket_dir" default:"/run/docker/plugins"` 7 | Volumes VolumesConfig `yaml:"volume"` 8 | Overlay OverlayConfig `yaml:"overlay"` 9 | GPUs map[string]map[string]string 10 | } 11 | 12 | type VolumesConfig struct { 13 | Root string `yaml:"root" default:"/var/lib/docker-volumes"` 14 | Drivers map[string]map[string]string 15 | } 16 | 17 | type OverlayConfig struct { 18 | Drivers struct { 19 | Tinc *network.TincNetworkConfig `yaml:"tinc"` 20 | L2TP *network.L2TPConfig `yaml:"l2tp"` 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /util/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | 7 | "gopkg.in/yaml.v2" 8 | ) 9 | 10 | func LoadWith(dst interface{}, path string, fn func(map[interface{}]interface{})) error { 11 | file, err := os.Open(path) 12 | if err != nil { 13 | return err 14 | } 15 | defer file.Close() 16 | 17 | data, err := ioutil.ReadAll(file) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | ty := map[interface{}]interface{}{} 23 | if err := yaml.Unmarshal(data, ty); err != nil { 24 | return err 25 | } 26 | 27 | fn(ty) 28 | 29 | data, err = yaml.Marshal(ty) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | return yaml.Unmarshal(data, dst) 35 | } 36 | -------------------------------------------------------------------------------- /insonmnia/npp/relay/frame_test.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/sonm-io/core/proto" 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestFrameRoundTrip(t *testing.T) { 13 | message := &sonm.HandshakeResponse{ 14 | Error: 42, 15 | Description: "oh, boy", 16 | } 17 | 18 | var err error 19 | wr := bytes.NewBuffer([]byte{}) 20 | err = sendFrame(wr, message) 21 | require.NoError(t, err) 22 | 23 | messageBack := &sonm.HandshakeResponse{} 24 | err = recvFrame(bytes.NewBuffer(wr.Bytes()), messageBack) 25 | require.NoError(t, err) 26 | 27 | assert.Equal(t, message, messageBack) 28 | } 29 | -------------------------------------------------------------------------------- /proto/log_reader.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | ) 7 | 8 | type logReader struct { 9 | cli TaskManagement_LogsClient 10 | buf bytes.Buffer 11 | finished bool 12 | } 13 | 14 | func NewLogReader(client TaskManagement_LogsClient) io.Reader { 15 | return &logReader{cli: client} 16 | } 17 | 18 | func (m *logReader) Read(p []byte) (n int, err error) { 19 | if len(p) > m.buf.Len() && !m.finished { 20 | chunk, err := m.cli.Recv() 21 | if err == io.EOF { 22 | m.finished = true 23 | } else if err != nil { 24 | return 0, err 25 | } 26 | if chunk != nil && chunk.Data != nil { 27 | m.buf.Write(chunk.Data) 28 | } 29 | } 30 | return m.buf.Read(p) 31 | } 32 | -------------------------------------------------------------------------------- /blockchain/source/patches/truffle-resolver+4.0.4.patch: -------------------------------------------------------------------------------- 1 | patch-package 2 | --- a/node_modules/truffle-resolver/fs.js 3 | +++ b/node_modules/truffle-resolver/fs.js 4 | @@ -87,9 +87,10 @@ FS.prototype.resolve = function(import_path, imported_from, callback) { 5 | }; 6 | 7 | // Here we're resolving from local files to local files, all absolute. 8 | +// Fixup by antmat: use relative paths - do not resolve to full paths to maintain smart-contrac bytecode unchanged. 9 | FS.prototype.resolve_dependency_path = function(import_path, dependency_path) { 10 | var dirname = path.dirname(import_path); 11 | - return path.resolve(path.join(dirname, dependency_path)); 12 | + return path.join(dirname, dependency_path); 13 | }; 14 | 15 | 16 | -------------------------------------------------------------------------------- /insonmnia/worker/network/README.l2tp.md: -------------------------------------------------------------------------------- 1 | ### Starting a task (dev mode) 2 | 3 | Sample `task.json`: 4 | 5 | ``` 6 | { 7 | "container": { 8 | "image": "httpd:latest", 9 | "networks": [ 10 | { 11 | "type": "l2tp", 12 | "options": { 13 | "id": "test_1", 14 | "lns_addr": "172.16.1.126", 15 | "subnet": "10.0.5.0/24", 16 | "ppp_username": "any", 17 | "ppp_password": "any" 18 | } 19 | } 20 | ] 21 | } 22 | } 23 | ``` 24 | 25 | After starting worker in dev mode on port `15010`, run: 26 | 27 | ``` 28 | $ make build/autocli && ./autocli worker start --input task.json --remote 8125721C2413d99a33E351e1F6Bb4e56b6b633FD@127.0.0.1:15010 29 | ``` 30 | -------------------------------------------------------------------------------- /blockchain/source/patches/truffle+4.1.14.patch: -------------------------------------------------------------------------------- 1 | patch-package 2 | --- a/node_modules/truffle/build/cli.bundled.js 3 | +++ b/node_modules/truffle/build/cli.bundled.js 4 | @@ -101768,9 +101768,10 @@ FS.prototype.resolve = function(import_path, imported_from, callback) { 5 | }; 6 | 7 | // Here we're resolving from local files to local files, all absolute. 8 | +// Fixup by antmat: use relative paths - do not resolve to full paths to maintain smart-contrac bytecode unchanged. 9 | FS.prototype.resolve_dependency_path = function(import_path, dependency_path) { 10 | var dirname = path.dirname(import_path); 11 | - return path.resolve(path.join(dirname, dependency_path)); 12 | + return path.join(dirname, dependency_path); 13 | }; 14 | 15 | 16 | -------------------------------------------------------------------------------- /insonmnia/hardware/cpu/device.go: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/shirou/gopsutil/cpu" 7 | "github.com/sonm-io/core/proto" 8 | ) 9 | 10 | func GetCPUDevice() (*sonm.CPUDevice, error) { 11 | info, err := cpu.Info() 12 | if err != nil { 13 | return nil, err 14 | } 15 | 16 | if len(info) == 0 { 17 | return nil, errors.New("no CPU detected") 18 | } 19 | 20 | // We've picked up a name of the first CPU because assuming 21 | // that multi-CPU board will have similar CPUs into the sockets. 22 | dev := &sonm.CPUDevice{ 23 | ModelName: info[0].ModelName, 24 | Sockets: uint32(len(info)), 25 | } 26 | 27 | for _, c := range info { 28 | dev.Cores += uint32(c.Cores) 29 | } 30 | 31 | return dev, nil 32 | } 33 | -------------------------------------------------------------------------------- /insonmnia/npp/relay/options.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import "go.uber.org/zap" 4 | 5 | // Option is a function that configures the server. 6 | type Option func(options *options) error 7 | 8 | type options struct { 9 | bufferSize int 10 | log *zap.Logger 11 | } 12 | 13 | func newOptions() *options { 14 | return &options{ 15 | bufferSize: 32 * 1024, 16 | log: zap.NewNop(), 17 | } 18 | } 19 | 20 | // WithLogger is an option that specifies provided logger used for the internal 21 | // logging. 22 | // Nil value is supported and can be passed to deactivate the logging system 23 | // entirely. 24 | func WithLogger(log *zap.Logger) Option { 25 | return func(options *options) error { 26 | options.log = log 27 | return nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /proto/marketplace_test.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "gopkg.in/yaml.v2" 9 | ) 10 | 11 | func TestName(t *testing.T) { 12 | into := struct { 13 | Level IdentityLevel 14 | }{} 15 | 16 | input := []byte(`level: registered`) 17 | err := yaml.Unmarshal(input, &into) 18 | 19 | require.NoError(t, err) 20 | assert.Equal(t, IdentityLevel_REGISTERED, into.Level) 21 | } 22 | 23 | func TestBidOrderValidate(t *testing.T) { 24 | bid := &BidOrder{Tag: "this-string-is-too-long-for-tag-value"} 25 | err := bid.Validate() 26 | require.Error(t, err) 27 | 28 | bid.Tag = "short-and-valid" 29 | err = bid.Validate() 30 | require.NoError(t, err) 31 | } 32 | -------------------------------------------------------------------------------- /insonmnia/worker/gpu/remote_server.go: -------------------------------------------------------------------------------- 1 | package gpu 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/sonm-io/core/proto" 7 | ) 8 | 9 | type remoteTunerService struct { 10 | tun Tuner 11 | } 12 | 13 | func NewRemoteTuner(ctx context.Context, name string) (sonm.RemoteGPUTunerServer, error) { 14 | vendor, err := GetVendorByName(name) 15 | if err != nil { 16 | return nil, err 17 | } 18 | 19 | t, err := New(ctx, vendor) 20 | if err != nil { 21 | return nil, err 22 | } 23 | 24 | return &remoteTunerService{tun: t}, nil 25 | } 26 | 27 | func (m *remoteTunerService) Devices(context.Context, *sonm.RemoteGPUDeviceRequest) (*sonm.RemoteGPUDeviceReply, error) { 28 | return &sonm.RemoteGPUDeviceReply{ 29 | Devices: m.tun.Devices(), 30 | }, nil 31 | } 32 | -------------------------------------------------------------------------------- /blockchain/addresses.go: -------------------------------------------------------------------------------- 1 | package blockchain 2 | 3 | const ( 4 | defaultContractRegistryAddr = "0xd1a6f3d1ae33b4b19565a6b283d7a05c5a0decb0" 5 | 6 | sidechainSNMAddressKey = "sidechainSNMAddress" 7 | masterchainSNMAddressKey = "masterchainSNMAddress" 8 | blacklistAddressKey = "blacklistAddress" 9 | marketAddressKey = "marketAddress" 10 | profileRegistryAddressKey = "profileRegistryAddress" 11 | oracleUsdAddressKey = "oracleUsdAddress" 12 | gatekeeperMasterchainAddressKey = "gatekeeperMasterchainAddress" 13 | gatekeeperSidechainAddressKey = "gatekeeperSidechainAddress" 14 | testnetFaucetAddressKey = "testnetFaucetAddress" 15 | oracleMultiSigAddressKey = "oracleMultiSigAddress" 16 | ) 17 | -------------------------------------------------------------------------------- /util/grpcutil_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "testing" 7 | "time" 8 | 9 | ethcrypto "github.com/ethereum/go-ethereum/crypto" 10 | ) 11 | 12 | func TestTLSGenCerts(t *testing.T) { 13 | priv, err := ethcrypto.GenerateKey() 14 | if err != nil { 15 | t.Fatalf("%v", err) 16 | } 17 | certPEM, keyPEM, err := GenerateCert(priv, time.Second*20) 18 | if err != nil { 19 | t.Fatalf("%v", err) 20 | } 21 | cert, err := tls.X509KeyPair(certPEM, keyPEM) 22 | if err != nil { 23 | t.Fatalf("%v", err) 24 | } 25 | x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) 26 | if err != nil { 27 | t.Fatalf("%v", err) 28 | } 29 | _, err = checkCert(x509Cert) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /etc/secterm.yaml: -------------------------------------------------------------------------------- 1 | # Secure Terminal Configuration. 2 | # ------------------------------ 3 | # Settings for Ethereum keys 4 | ethereum: 5 | # path to keystore 6 | key_store: "./keys" 7 | # passphrase for keystore 8 | pass_phrase: "any" 9 | 10 | # NAT punching settings. 11 | npp: 12 | # Rendezvous settings. 13 | rendezvous: 14 | # Known rendezvous endpoints. 15 | # 16 | # Must be in ETHAddress@Host:Port format. 17 | endpoints: 18 | - 0x5b7d6516fad04e10db726933bcd75447fd7b4b17@rendezvous.livenet.sonm.com:14099 19 | # Relay settings. 20 | relay: 21 | # Known relay endpoints. 22 | # 23 | # The format is Host:Port. 24 | # Can be omitted, meaning that relaying is disabled. 25 | endpoints: 26 | - relay.livenet.sonm.com:12240 27 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tuner.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/docker/docker/api/types/container" 7 | "github.com/docker/docker/api/types/network" 8 | "github.com/sonm-io/core/insonmnia/structs" 9 | ) 10 | 11 | type Cleanup interface { 12 | Close() error 13 | } 14 | 15 | // Tuner is responsible for preparing networking and baking proper options in container.HostConfig and 16 | // network.NetworkingConfig. 17 | type Tuner interface { 18 | Tune(ctx context.Context, net *structs.NetworkSpec, hostConfig *container.HostConfig, netConfig *network.NetworkingConfig) (Cleanup, error) 19 | GenerateInvitation(ID string) (*structs.NetworkSpec, error) 20 | GetCleaner(ctx context.Context, ID string) (Cleanup, error) 21 | Tuned(ID string) bool 22 | } 23 | -------------------------------------------------------------------------------- /optimus/plan_policy.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | planPolicyPrecise = iota 9 | planPolicyEntireMachine 10 | ) 11 | 12 | type planPolicy struct { 13 | Type int 14 | } 15 | 16 | func (m *planPolicy) IsPrecise() bool { 17 | return m.Type == planPolicyPrecise 18 | } 19 | 20 | func (m *planPolicy) IsEntireMachine() bool { 21 | return m.Type == planPolicyEntireMachine 22 | } 23 | 24 | func (m *planPolicy) UnmarshalText(text []byte) error { 25 | ty := string(text) 26 | 27 | switch ty { 28 | case "precise": 29 | *m = planPolicy{Type: planPolicyPrecise} 30 | case "entire_machine": 31 | *m = planPolicy{Type: planPolicyEntireMachine} 32 | default: 33 | return fmt.Errorf("unknown plan policy: %s", ty) 34 | } 35 | 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/advanceToBlock.js: -------------------------------------------------------------------------------- 1 | export function advanceBlock () { 2 | return new Promise((resolve, reject) => { 3 | web3.currentProvider.sendAsync({ 4 | jsonrpc: '2.0', 5 | method: 'evm_mine', 6 | id: Date.now(), 7 | }, (err, res) => { 8 | return err ? reject(err) : resolve(res); 9 | }); 10 | }); 11 | } 12 | 13 | // Advances the block number so that the last mined block is `number`. 14 | export default async function advanceToBlock (number) { 15 | if (web3.eth.blockNumber > number) { 16 | throw Error(`block number ${number} is in the past (current is ${web3.eth.blockNumber})`); 17 | } 18 | 19 | while (web3.eth.blockNumber < number) { 20 | await advanceBlock(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /etc/secexec/ps.yaml: -------------------------------------------------------------------------------- 1 | checksum: 171e9430c1668c2df36e731695dac3ddabe7e67b68c967861795e3e5c038de4e1a30d20ebb75727aa2d4770648806529790b129eec38194053b4f2ab6fdcac5e 2 | syscalls: 3 | read: [] 4 | openat: [] 5 | close: [] 6 | write: 7 | - arg: 0 8 | op: eq 9 | a: 1 10 | - arg: 0 11 | op: eq 12 | a: 2 13 | stat: [] 14 | readlink: [] 15 | getdents: [] 16 | fstat: [] 17 | lseek: [] 18 | mmap: [] 19 | mprotect: [] 20 | munmap: [] 21 | brk: [] 22 | rt_sigaction: [] 23 | rt_sigprocmask: [] 24 | ioctl: [] 25 | access: [] 26 | geteuid: [] 27 | arch_prctl: [] 28 | futex: [] 29 | set_tid_address: [] 30 | set_robust_list: [] 31 | prlimit64: [] 32 | # a 33 | socket: 34 | - arg: 0 35 | op: eq 36 | a: 1 # AF_UNIX 37 | connect: [] 38 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.4.31.{build} 2 | 3 | platform: x86 4 | 5 | branches: 6 | only: 7 | - master 8 | 9 | clone_folder: c:\gopath\src\github.com\sonm-io\core 10 | 11 | environment: 12 | GOPATH: c:\gopath 13 | GO111MODULE: on 14 | 15 | install: 16 | - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% 17 | - set GOOS=windows 18 | - set GOARCH=386 19 | 20 | build_script: 21 | - git submodule update --init --recursive 22 | - c:\MinGW\bin\mingw32-make.exe build/cli 23 | - c:\MinGW\bin\mingw32-make.exe build/node 24 | - c:\MinGW\bin\mingw32-make.exe build/optimus 25 | 26 | artifacts: 27 | - path: target/sonmcli_windows_386.exe 28 | name: CLI 29 | 30 | - path: target/sonmnode_windows_386.exe 31 | name: Node 32 | 33 | - path: target/sonmoptimus_windows_386.exe 34 | name: Optimus 35 | -------------------------------------------------------------------------------- /insonmnia/logging/trace.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/opentracing/basictracer-go" 8 | "github.com/opentracing/opentracing-go" 9 | "go.uber.org/zap" 10 | ) 11 | 12 | const ( 13 | traceIdFieldKey = "span.trace_id" 14 | spanIdFieldKey = "span.span_id" 15 | ) 16 | 17 | func WithTrace(ctx context.Context, log *zap.Logger) *zap.Logger { 18 | span := opentracing.SpanFromContext(ctx) 19 | if span == nil { 20 | return log 21 | } 22 | 23 | spanContext, ok := span.Context().(basictracer.SpanContext) 24 | if ok && spanContext.Sampled { 25 | log = log.With( 26 | zap.String(traceIdFieldKey, fmt.Sprintf("%x", spanContext.TraceID)), 27 | zap.String(spanIdFieldKey, fmt.Sprintf("%x", spanContext.SpanID)), 28 | ) 29 | } 30 | 31 | return log 32 | } 33 | -------------------------------------------------------------------------------- /blockchain/source/test/addressHashMap.js: -------------------------------------------------------------------------------- 1 | const AddressHashMap = artifacts.require('./AddressHashMap.sol'); 2 | 3 | contract('AddressHashMap', async function (accounts) { 4 | let hm; 5 | let owner = accounts[0]; 6 | 7 | before(async function () { 8 | hm = await AddressHashMap.new({ from: owner }); 9 | }); 10 | 11 | it('should write and read', async function () { 12 | await hm.write('market', accounts[2], { from: owner }); 13 | await hm.write('market', accounts[3], { from: owner }); 14 | await hm.write('profiles', accounts[4], { from: owner }); 15 | 16 | let market = await hm.read('market'); 17 | assert.equal(market, accounts[3]); 18 | 19 | let pr = await hm.read('profiles'); 20 | assert.equal(pr, accounts[4]); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /cmd/pandora/main.go: -------------------------------------------------------------------------------- 1 | // How to use it? 2 | // 3 | // Direct usage: `pandora_OS_ARCH etc/pandora.yaml` 4 | 5 | package main 6 | 7 | import ( 8 | "github.com/spf13/afero" 9 | "github.com/yandex/pandora/cli" 10 | importer "github.com/yandex/pandora/core/import" 11 | "github.com/yandex/pandora/core/register" 12 | ) 13 | 14 | func main() { 15 | fs := afero.NewOsFs() 16 | importer.Import(fs) 17 | 18 | AmmoRegistry.Register("sonm.marketplace.GetOrderInfo", newOrderInfoAmmoFactory) 19 | AmmoRegistry.Register("sonm.marketplace.PlaceOrder", newOrderPlaceAmmoFactory) 20 | AmmoRegistry.Register("sonm.DWH.Orders", newDWHOrdersAmmoFactory) 21 | 22 | register.Gun("sonm.marketplace", NewMarketplaceGun) 23 | register.Gun("sonm.DWH", NewDWHGun) 24 | 25 | register.Provider("sonm", NewProvider) 26 | 27 | cli.Run() 28 | } 29 | -------------------------------------------------------------------------------- /insonmnia/worker/storage/btrfs/btrfs_native_api_test.go: -------------------------------------------------------------------------------- 1 | // +build linux,btrfsnative 2 | 3 | package btrfs 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestParseQroupID(t *testing.T) { 14 | require := require.New(t) 15 | id, err := parseQgroupID("1/555") 16 | require.NoError(err) 17 | require.NotZero(id) 18 | } 19 | 20 | func TestE2ENative(t *testing.T) { 21 | path := os.Getenv("BTRFS_PLAYGROUND_PATH") 22 | if path == "" { 23 | t.Skip("BTRFS_PLAYGROUND_PATH must be set for the test") 24 | } 25 | if os.Getenv("SUDO_USER") == "" { 26 | t.Skip("WARNING: root permissions required for that test") 27 | } 28 | 29 | var b btrfsNativeAPI 30 | t.Run(fmt.Sprintf("%T", b), func(t *testing.T) { 31 | testE2EOne(t, b, path) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /insonmnia/worker/options.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/sonm-io/core/insonmnia/logging" 7 | ) 8 | 9 | type Option func(*options) 10 | 11 | type options struct { 12 | ctx context.Context 13 | version string 14 | logWatcher *logging.WatcherCore 15 | } 16 | 17 | func newOptions() *options { 18 | return &options{ 19 | ctx: context.Background(), 20 | version: "unspecified", 21 | } 22 | } 23 | 24 | func WithContext(ctx context.Context) Option { 25 | return func(o *options) { 26 | o.ctx = ctx 27 | } 28 | } 29 | 30 | func WithVersion(v string) Option { 31 | return func(o *options) { 32 | o.version = v 33 | } 34 | } 35 | 36 | func WithLogWatcher(watcher *logging.WatcherCore) Option { 37 | return func(o *options) { 38 | o.logWatcher = watcher 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /connor/antifraud/antifraud_test.go: -------------------------------------------------------------------------------- 1 | package antifraud 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestIsWhitelisted(t *testing.T) { 11 | a := &antiFraud{cfg: Config{ 12 | Whitelist: []common.Address{ 13 | common.HexToAddress("0x38FeB5FE6fb1EECb2e0b990214BC6f0ACa1eCE6A"), 14 | common.HexToAddress("0xeEDC24cdcA34fcDFCeaAd84a7C6bA3301D5D707f"), 15 | common.HexToAddress("0xBAdc46A8ca03bD0D458242E76Bc2810DC5f12908"), 16 | }, 17 | }} 18 | 19 | notInList := a.isAddressWhitelisted(common.HexToAddress("0x2b7D9Af99CE1Bec0dc32aB115B4DA82BF15B501E")) 20 | assert.False(t, notInList) 21 | 22 | inList := a.isAddressWhitelisted(common.HexToAddress("0xeEDC24cdcA34fcDFCeaAd84a7C6bA3301D5D707f")) 23 | assert.True(t, inList) 24 | } 25 | -------------------------------------------------------------------------------- /connor/backends.go: -------------------------------------------------------------------------------- 1 | package connor 2 | 3 | import ( 4 | "github.com/sonm-io/core/connor/antifraud" 5 | "github.com/sonm-io/core/connor/price" 6 | "github.com/sonm-io/core/connor/types" 7 | ) 8 | 9 | type backends struct { 10 | corderFactory types.CorderFactory 11 | dealFactory types.DealFactory 12 | priceProvider price.Provider 13 | processorFactory antifraud.ProcessorFactory 14 | } 15 | 16 | func NewBackends(cfg *Config) *backends { 17 | return &backends{ 18 | processorFactory: antifraud.NewProcessorFactory(&cfg.AntiFraud), 19 | corderFactory: types.NewCorderFactory(cfg.Container.Tag, cfg.Market.benchmarkID, cfg.Market.Counterparty), 20 | dealFactory: types.NewDealFactory(cfg.Market.benchmarkID), 21 | priceProvider: cfg.PriceSource.Init(cfg.Market.PriceControl.Marginality), 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /etc/secexec/ls.yaml: -------------------------------------------------------------------------------- 1 | checksum: 4be40f2440619e990897cf956c32800dc96c2c983bf64519854a3309fa5aa21827991559f9c44595098e27e6f2ee4d64a3fdec6baba8a177881f20e3ec61e26c 2 | syscalls: 3 | read: [] 4 | write: 5 | - arg: 0 6 | op: eq 7 | a: 1 8 | - arg: 0 9 | op: eq 10 | a: 2 11 | close: [] 12 | fstat: [] 13 | mmap: [] 14 | mprotect: [] 15 | munmap: [] 16 | brk: [] 17 | rt_sigaction: [] 18 | rt_sigprocmask: [] 19 | ioctl: [] 20 | access: [] 21 | getdents: [] 22 | statfs: [] 23 | arch_prctl: [] 24 | set_tid_address: [] 25 | openat: [] 26 | set_robust_list: [] 27 | prlimit64: [] 28 | lstat: [] 29 | lgetxattr: [] 30 | getxattr: [] 31 | # -l 32 | sigaltstack: [] 33 | socket: 34 | - arg: 0 35 | op: eq 36 | a: 1 # AF_UNIX 37 | connect: [] 38 | lseek: [] 39 | -------------------------------------------------------------------------------- /optimus/worker_test.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/pkg/errors" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestNamedErrorGroup_Set(t *testing.T) { 11 | errs := newNamedErrorGroup() 12 | errs.Set("0", errors.New("error")) 13 | 14 | assert.EqualError(t, errs, `{"0":"error"}`) 15 | assert.NotNil(t, errs.ErrorOrNil()) 16 | } 17 | 18 | func TestNamedErrorGroup_SetUnique(t *testing.T) { 19 | errs := newNamedErrorGroup() 20 | errs.Set("0", errors.New("error")) 21 | errs.SetUnique([]string{"0", "1", "2"}, errors.New("fail")) 22 | 23 | assert.EqualError(t, errs, `{"0":"error","1":"fail","2":"fail"}`) 24 | assert.NotNil(t, errs.ErrorOrNil()) 25 | } 26 | 27 | func TestNamedErrorGroup_ErrorOrNil(t *testing.T) { 28 | assert.Nil(t, newNamedErrorGroup().ErrorOrNil()) 29 | } 30 | -------------------------------------------------------------------------------- /cmd/pandora/registry.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | var AmmoRegistry = ammoRegistry{ 9 | registry: map[string]func(cfg interface{}) (AmmoFactory, error){}, 10 | } 11 | 12 | type ammoRegistry struct { 13 | mu sync.RWMutex 14 | registry map[string]func(cfg interface{}) (AmmoFactory, error) 15 | } 16 | 17 | func (m *ammoRegistry) Register(ty string, factory func(cfg interface{}) (AmmoFactory, error)) { 18 | m.mu.Lock() 19 | defer m.mu.Unlock() 20 | 21 | m.registry[ty] = factory 22 | } 23 | 24 | func (m *ammoRegistry) Get(ty string, cfg interface{}) (AmmoFactory, error) { 25 | m.mu.RLock() 26 | defer m.mu.RUnlock() 27 | 28 | factory, ok := m.registry[ty] 29 | if !ok { 30 | return nil, fmt.Errorf("`%s` ammo factory not registered", ty) 31 | } 32 | 33 | return factory(cfg) 34 | } 35 | -------------------------------------------------------------------------------- /connor/antifraud/pool_processor_test.go: -------------------------------------------------------------------------------- 1 | package antifraud 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "gopkg.in/oleiade/lane.v1" 8 | ) 9 | 10 | func TestPoolProcessorQueue_Decide(t *testing.T) { 11 | w := &commonPoolProcessor{ 12 | hashrateQueue: &lane.Queue{Deque: lane.NewCappedDeque(60)}, 13 | } 14 | 15 | // empty Q should return true - not enough data to analyze 16 | assert.True(t, w.nonZeroHashrate()) 17 | 18 | // last five non-zero items, hashrate is non-zero 19 | for i := 0; i <= 5; i++ { 20 | w.updateHashRateQueue(float64(i)) 21 | } 22 | assert.True(t, w.nonZeroHashrate()) 23 | 24 | // last five zero items - should decide that there is no 25 | // hashrate 26 | for i := 0; i < 5; i++ { 27 | w.updateHashRateQueue(0) 28 | } 29 | assert.False(t, w.nonZeroHashrate()) 30 | } 31 | -------------------------------------------------------------------------------- /cmd/cli/commands/worker_metrics.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sonm-io/core/proto" 7 | "github.com/spf13/cobra" 8 | "gopkg.in/yaml.v2" 9 | ) 10 | 11 | var workerMetricsCmd = &cobra.Command{ 12 | Use: "metrics", 13 | Short: "Show Worker's hardware monitoring", 14 | RunE: func(cmd *cobra.Command, args []string) error { 15 | metrics, err := worker.Metrics(workerCtx, &sonm.WorkerMetricsRequest{}) 16 | if err != nil { 17 | return fmt.Errorf("cannot get metrics: %v", err) 18 | } 19 | 20 | if isSimpleFormat() { 21 | data, err := yaml.Marshal(metrics) 22 | if err != nil { 23 | return fmt.Errorf("failed to marshal metrics into YAML: %v", err) 24 | } 25 | 26 | cmd.Println(string(data)) 27 | } else { 28 | showJSON(cmd, metrics) 29 | } 30 | 31 | return nil 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /proto/rendezvous.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | DefaultNPPProtocol = "tcp" // Equals to "tcp+grpc". 9 | ) 10 | 11 | func (m *PublishRequest) Validate() error { 12 | if m.Protocol == "" { 13 | m.Protocol = DefaultNPPProtocol 14 | } 15 | 16 | return nil 17 | } 18 | 19 | func (m *ConnectRequest) Validate() error { 20 | if m.Protocol == "" { 21 | m.Protocol = DefaultNPPProtocol 22 | } 23 | if len(m.ID) != 20 { 24 | return fmt.Errorf("destination ID must have exactly 20 bytes format") 25 | } 26 | 27 | return nil 28 | } 29 | 30 | func (m *RendezvousReply) Empty() bool { 31 | return (m.PublicAddr == nil || m.PublicAddr.Addr == nil) && len(m.PrivateAddrs) == 0 32 | } 33 | 34 | func (m *RendezvousReply) GetAddresses() []*Addr { 35 | return append([]*Addr{m.PublicAddr}, m.PrivateAddrs...) 36 | } 37 | -------------------------------------------------------------------------------- /util/xgrpc/server.go: -------------------------------------------------------------------------------- 1 | package xgrpc 2 | 3 | import ( 4 | "github.com/grpc-ecosystem/go-grpc-middleware" 5 | "go.uber.org/zap" 6 | "google.golang.org/grpc" 7 | _ "google.golang.org/grpc/encoding/gzip" 8 | ) 9 | 10 | func NewServer(logger *zap.Logger, extraOpts ...ServerOption) *grpc.Server { 11 | opts := newOptions(logger, extraOpts...) 12 | srv := grpc.NewServer( 13 | append([]grpc.ServerOption{ 14 | grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(opts.interceptors.u...)), 15 | grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(opts.interceptors.s...)), 16 | }, opts.options...)..., 17 | ) 18 | 19 | return srv 20 | } 21 | 22 | func Services(server *grpc.Server) []string { 23 | var names []string 24 | for name := range server.GetServiceInfo() { 25 | names = append(names, name) 26 | } 27 | 28 | return names 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Components version** 2 | Which components are affected and their versions. The version can be obtained using the following: 3 | ```bash 4 | $ --version 5 | ``` 6 | 7 | For example: 8 | ```bash 9 | $ sonmworker --version 10 | worker v0.4.2-365a8fe6 (linux/amd64/go1.10.2) 11 | ``` 12 | 13 | **Describe the bug** 14 | A clear and concise description of what the bug is. 15 | 16 | **Step to reproduce** 17 | Steps to reproduce the bug. 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots and/or terminal logs** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Platform (please complete the following information):** 26 | - OS. 27 | - Arch. 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /cmd/pandora/ammo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | 7 | "github.com/yandex/pandora/core" 8 | ) 9 | 10 | type AmmoType uint8 11 | 12 | type Ammo interface { 13 | core.Ammo 14 | 15 | // Type describes an ammo type used for pooling. 16 | // The returned value must be unique across the entire application and also 17 | // must be constant. 18 | Type() AmmoType 19 | Execute(ctx context.Context, ext interface{}) error 20 | } 21 | 22 | type AmmoFactory interface { 23 | New(id int) Ammo 24 | NewDefault() Ammo 25 | Pool() *sync.Pool 26 | } 27 | 28 | type PoolAmmoFactory struct { 29 | pool *sync.Pool 30 | } 31 | 32 | func newPoolAmmoFactory(fn func() interface{}) PoolAmmoFactory { 33 | return PoolAmmoFactory{ 34 | pool: &sync.Pool{New: fn}, 35 | } 36 | } 37 | 38 | func (m *PoolAmmoFactory) Pool() *sync.Pool { 39 | return m.pool 40 | } 41 | -------------------------------------------------------------------------------- /insonmnia/worker/gpu/detect.go: -------------------------------------------------------------------------------- 1 | package gpu 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | 7 | "github.com/sonm-io/core/proto" 8 | ) 9 | 10 | // hasGPUWithVendor uses OpenCL to check device existence on the Worker's system 11 | func hasGPUWithVendor(v sonm.GPUVendorType, devices []*sonm.GPUDevice) error { 12 | found := false 13 | for _, dev := range devices { 14 | if dev.VendorType() == v { 15 | found = true 16 | } 17 | } 18 | 19 | if !found { 20 | return errors.New("cannot detect required GPU") 21 | } 22 | 23 | return nil 24 | } 25 | 26 | func GetVendorByName(vendor string) (sonm.GPUVendorType, error) { 27 | vendorName := strings.ToUpper(vendor) 28 | t, ok := sonm.GPUVendorType_value[vendorName] 29 | if !ok { 30 | return sonm.GPUVendorType_GPU_UNKNOWN, errors.New("unknown GPU vendor type") 31 | } 32 | 33 | return sonm.GPUVendorType(t), nil 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | *.uuid 6 | target/ 7 | 8 | # Folders 9 | _obj 10 | _test 11 | 12 | # Architecture specific extensions/prefixes 13 | *.[568vq] 14 | [568vq].out 15 | 16 | *.cgo1.go 17 | *.cgo2.c 18 | _cgo_defun.c 19 | _cgo_gotypes.go 20 | _cgo_export.* 21 | 22 | _testmain.go 23 | 24 | *.exe 25 | *.test 26 | *.prof 27 | 28 | coverage* 29 | !.ci/coverage.sh 30 | 31 | target/ 32 | release/ 33 | .idea/ 34 | 35 | # test artifacts 36 | metrics/config_test.json 37 | 38 | # Mock files are not the subject of the repository, because we generate them 39 | # on the fly. 40 | *_mock.go 41 | 42 | # truffle installs OpenZeppelin contracts here 43 | blockchain/node_modules 44 | 45 | blockchain/build 46 | 47 | vendor/github.com/golang/mock/mockgen/mockgen 48 | 49 | token.txt 50 | 51 | keys/state/ 52 | 53 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/common.js: -------------------------------------------------------------------------------- 1 | export async function checkBenchmarks (info, benchmarks) { 2 | let b = info.map((item) => parseInt(item, 10)); 3 | assert.equal(JSON.stringify(benchmarks), JSON.stringify(b), 'Incorrect benchmarks'); 4 | } 5 | 6 | export async function checkOrderStatus (market, key, orderId, status) { 7 | let res = await market.GetOrderParams(orderId, { from: key }); 8 | assert.equal(status, res[0], 'Incorrect order status'); 9 | } 10 | 11 | export async function getDealIdFromOrder (market, key, orderId) { 12 | let orderParams = await market.GetOrderParams(orderId, { from: key }); 13 | return orderParams[1].toNumber(10); 14 | } 15 | 16 | export async function getDealInfoFromOrder (market, key, orderId) { 17 | let dealId = await getDealIdFromOrder(market, key, orderId); 18 | return market.GetDealInfo(dealId, { from: key }); 19 | } 20 | -------------------------------------------------------------------------------- /etc/secexec/lsof.yaml: -------------------------------------------------------------------------------- 1 | checksum: fe1cc7a65327732eaaee89f427c10239ba822430e34177842f4681068d78d404b1830d808a2a71b1efcc5f126c6d8c053512237421173aaa150e215a672da6f0 2 | syscalls: 3 | read: [] 4 | write: [] 5 | close: [] 6 | alarm: [] 7 | rt_sigaction: [] 8 | openat: [] 9 | stat: [] 10 | getdents: [] 11 | mmap: [] 12 | clone: [] 13 | fstat: [] 14 | mprotect: [] 15 | munmap: [] 16 | connect: [] 17 | lstat: [] 18 | access: [] 19 | socket: 20 | - arg: 0 21 | op: eq 22 | a: 1 # AF_UNIX 23 | pipe: [] 24 | wait4: [] 25 | lseek: [] 26 | futex: [] 27 | umask: [] 28 | getuid: [] 29 | getgid: [] 30 | geteuid: [] 31 | getegid: [] 32 | getpid: [] 33 | brk: [] 34 | rt_sigprocmask: [] 35 | readlink: [] 36 | statfs: [] 37 | arch_prctl: [] 38 | set_tid_address: [] 39 | set_robust_list: [] 40 | prlimit64: [] 41 | sigaltstack: [] 42 | -------------------------------------------------------------------------------- /proto/timestamp.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import "time" 4 | 5 | // Unix returns the local time.Time corresponding to the given Unix time 6 | // since January 1, 1970 UTC. 7 | func (m *Timestamp) Unix() time.Time { 8 | if m == nil { 9 | return time.Unix(0, 0).In(time.UTC) 10 | } 11 | return time.Unix(m.Seconds, int64(m.Nanos)).In(time.UTC) 12 | } 13 | 14 | func CurrentTimestamp() *Timestamp { 15 | now := time.Now().UnixNano() 16 | return &Timestamp{ 17 | Seconds: now / 1e9, 18 | Nanos: int32(now % 1e9), 19 | } 20 | } 21 | 22 | func (m Timestamp) MarshalText() (text []byte, err error) { 23 | return m.Unix().MarshalText() 24 | } 25 | 26 | func (m *Timestamp) UnmarshalText(text []byte) error { 27 | t := &time.Time{} 28 | if err := t.UnmarshalText(text); err != nil { 29 | return err 30 | } 31 | m.Seconds = t.Unix() 32 | m.Nanos = int32(t.UnixNano() % 1e9) 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /util/ticker.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type ImmediateTicker struct { 8 | ticker *time.Ticker 9 | C <-chan time.Time // The channel on which the ticks are delivered. 10 | cancelCh chan struct{} 11 | } 12 | 13 | func NewImmediateTicker(d time.Duration) *ImmediateTicker { 14 | ch := make(chan time.Time, 1) 15 | ticker := &ImmediateTicker{ 16 | ticker: time.NewTicker(d), 17 | C: ch, 18 | cancelCh: make(chan struct{}), 19 | } 20 | 21 | go func() { 22 | ch <- time.Now() 23 | for { 24 | select { 25 | case timePoint := <-ticker.ticker.C: 26 | select { 27 | case ch <- timePoint: 28 | default: 29 | } 30 | case <-ticker.cancelCh: 31 | return 32 | } 33 | 34 | } 35 | }() 36 | 37 | return ticker 38 | } 39 | 40 | func (t *ImmediateTicker) Stop() { 41 | t.ticker.Stop() 42 | t.cancelCh <- struct{}{} 43 | } 44 | -------------------------------------------------------------------------------- /insonmnia/logging/logging_test.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "go.uber.org/zap/zapcore" 8 | ) 9 | 10 | func TestParseLogLevel(t *testing.T) { 11 | tests := []struct { 12 | in string 13 | out zapcore.Level 14 | mustFail bool 15 | }{ 16 | // any case must be parsed 17 | {in: "warn", out: zapcore.WarnLevel}, 18 | {in: "Warn", out: zapcore.WarnLevel}, 19 | {in: "WARN", out: zapcore.WarnLevel}, 20 | // any other values must be represented as default debug level 21 | {in: "-1", mustFail: true}, 22 | {in: "5", mustFail: true}, 23 | {in: "666", mustFail: true}, 24 | } 25 | 26 | for _, tt := range tests { 27 | out, err := parseLogLevel(tt.in) 28 | if tt.mustFail { 29 | assert.Error(t, err) 30 | } else { 31 | assert.NoError(t, err) 32 | assert.Equal(t, tt.out, out) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /blockchain/source/scripts/dev.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | trap cleanup EXIT 4 | 5 | pids=() 6 | 7 | blockTime=$1 8 | if [[ -n "$blockTime" ]]; then 9 | blockTime="-b $blockTime" 10 | fi 11 | 12 | cleanup() { 13 | for pid in "${pids[@]}" 14 | do 15 | echo "killing $pid" 16 | kill $pid 17 | done 18 | pids=() 19 | } 20 | 21 | rpc_running() { 22 | nc -z localhost "$1" 23 | } 24 | 25 | run() { 26 | port=$1; 27 | chain=$2 28 | if rpc_running $port; then 29 | echo "rpc is running on $port" 30 | else 31 | echo "running node_modules/.bin/ganache-cli $blockTime -d sonm --port=$port -i $port >> ./$port.log &" 32 | node_modules/.bin/ganache-cli $blockTime -d sonm --port=$port -i $port >> ./$port.log & 33 | pids+=($!) 34 | echo "started ganache on $port (pid $!)" 35 | fi 36 | } 37 | 38 | run 8545 main 39 | run 8525 side 40 | 41 | wait 42 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/handle.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import ( 4 | "github.com/vishvananda/netlink" 5 | ) 6 | 7 | const ( 8 | HandleNone Handle = netlink.HANDLE_NONE 9 | HandleRoot = netlink.HANDLE_ROOT 10 | HandleIngress = netlink.HANDLE_INGRESS 11 | ) 12 | 13 | // Handle specifies both qdisc, class and filter ID. 14 | type Handle uint32 15 | 16 | // NewHandle computes tc handle based on major and minor parts. 17 | func NewHandle(major uint16, minor uint16) Handle { 18 | return Handle(netlink.MakeHandle(major, minor)) 19 | } 20 | 21 | // UInt32 returns internal handle representation as an uint32. 22 | func (m Handle) UInt32() uint32 { 23 | return uint32(m) 24 | } 25 | 26 | func (m Handle) String() string { 27 | return netlink.HandleStr(m.UInt32()) 28 | } 29 | 30 | func (m Handle) WithMinor(minor uint16) Handle { 31 | return NewHandle(uint16((m&0xFFFF0000)>>16), minor) 32 | } 33 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/ask.js: -------------------------------------------------------------------------------- 1 | import { defaultBenchmarks, IdentityLevel, OrderType, testDuration, testPrice } from './constants'; 2 | 3 | export async function Ask ( 4 | { 5 | market, supplier, 6 | counterparty = '0x0', 7 | duration = testDuration, 8 | price = testPrice, 9 | netFlags = [0, 0, 0], 10 | identityLvl = IdentityLevel.ANONIMOUS, 11 | blacklist = 0x0, 12 | tag = '000000', 13 | benchmarks = defaultBenchmarks, 14 | } = {}) { 15 | let tx = await market.PlaceOrder( 16 | OrderType.ASK, 17 | counterparty, 18 | duration, 19 | price, 20 | netFlags, 21 | identityLvl, 22 | blacklist, 23 | tag, 24 | benchmarks, 25 | { from: supplier }); 26 | let orderId = tx.logs[0].args.orderID; 27 | assert.isNotNull(orderId); 28 | return orderId; 29 | } 30 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/bid.js: -------------------------------------------------------------------------------- 1 | import { defaultBenchmarks, IdentityLevel, OrderType, testDuration, testPrice } from './constants'; 2 | 3 | export async function Bid ( 4 | { 5 | market, consumer, 6 | counterparty = '0x0', 7 | duration = testDuration, 8 | price = testPrice, 9 | netFlags = [0, 0, 0], 10 | identityLvl = IdentityLevel.ANONIMOUS, 11 | blacklist = 0x0, 12 | tag = '000000', 13 | benchmarks = defaultBenchmarks, 14 | } = {}) { 15 | let tx = await market.PlaceOrder( 16 | OrderType.BID, 17 | counterparty, 18 | duration, 19 | price, 20 | netFlags, 21 | identityLvl, 22 | blacklist, 23 | tag, 24 | benchmarks, 25 | { from: consumer }); 26 | let orderId = tx.logs[0].args.orderID; 27 | assert.isNotNull(orderId); 28 | return orderId; 29 | } 30 | -------------------------------------------------------------------------------- /insonmnia/node/profiles.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/sonm-io/core/proto" 7 | ) 8 | 9 | type profileAPI struct { 10 | remotes *remoteOptions 11 | } 12 | 13 | func newProfileAPI(opts *remoteOptions) sonm.ProfilesServer { 14 | return &profileAPI{remotes: opts} 15 | } 16 | 17 | func (p *profileAPI) List(ctx context.Context, req *sonm.ProfilesRequest) (*sonm.ProfilesReply, error) { 18 | return p.remotes.dwh.GetProfiles(ctx, req) 19 | } 20 | 21 | func (p *profileAPI) Status(ctx context.Context, addr *sonm.EthID) (*sonm.Profile, error) { 22 | return p.remotes.dwh.GetProfileInfo(ctx, addr) 23 | } 24 | 25 | func (p *profileAPI) RemoveAttribute(ctx context.Context, id *sonm.BigInt) (*sonm.Empty, error) { 26 | if err := p.remotes.eth.ProfileRegistry().RemoveCertificate(ctx, p.remotes.key, id.Unwrap()); err != nil { 27 | return nil, err 28 | } 29 | 30 | return &sonm.Empty{}, nil 31 | } 32 | -------------------------------------------------------------------------------- /insonmnia/sysinit/lsblk.go: -------------------------------------------------------------------------------- 1 | package sysinit 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "os/exec" 8 | ) 9 | 10 | type BlockDevice struct { 11 | Name string `json:"name"` 12 | FsType string `json:"fstype"` 13 | Children []*BlockDevice `json:"children"` 14 | } 15 | 16 | func ListBlockDevices(ctx context.Context) ([]*BlockDevice, error) { 17 | cmd := exec.CommandContext(ctx, "lsblk", "--output", "NAME,FSTYPE", "--json") 18 | 19 | out, err := cmd.Output() 20 | if err != nil { 21 | return nil, fmt.Errorf("failed to execute %v: %v", cmd.Args, err) 22 | } 23 | 24 | type container struct { 25 | BlockDevices []*BlockDevice `json:"blockdevices"` 26 | } 27 | 28 | result := &container{} 29 | if err := json.Unmarshal(out, &result); err != nil { 30 | return nil, fmt.Errorf("failed to decode %v output: %v", cmd.Args, err) 31 | } 32 | 33 | return result.BlockDevices, nil 34 | } 35 | -------------------------------------------------------------------------------- /proto/benchmarks.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | // BenchmarkType describes hardware group for which this benchmark is applicable 8 | enum DeviceType { 9 | DEV_UNKNOWN = 0; 10 | DEV_CPU = 1; 11 | DEV_GPU = 2; 12 | DEV_RAM = 3; 13 | DEV_STORAGE = 4; 14 | DEV_NETWORK_IN = 5; 15 | DEV_NETWORK_OUT = 6; 16 | } 17 | 18 | // SplittingAlgorithm describes how a benchmark is mapped to a device. 19 | enum SplittingAlgorithm { 20 | NONE = 0; 21 | PROPORTIONAL = 1; 22 | MIN = 2; 23 | MAX = 3; 24 | } 25 | 26 | // Benchmark describes a way to measure hardware performance 27 | message Benchmark { 28 | uint64 ID = 1; 29 | string code = 2; 30 | DeviceType type = 3; 31 | string description = 4; 32 | string image = 5; 33 | uint64 result = 6; 34 | SplittingAlgorithm splittingAlgorithm = 7; 35 | } 36 | -------------------------------------------------------------------------------- /util/xconcurrency/cncurrency.go: -------------------------------------------------------------------------------- 1 | package xconcurrency 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | ) 7 | 8 | func Run(concurrency int, t interface{}, cb func(elem interface{})) { 9 | iterable := reflect.ValueOf(t) 10 | 11 | ln := iterable.Len() 12 | if ln < concurrency { 13 | concurrency = ln 14 | } 15 | 16 | ch := make(chan interface{}) 17 | wg := sync.WaitGroup{} 18 | wg.Add(concurrency) 19 | for i := 0; i < concurrency; i++ { 20 | go func() { 21 | defer wg.Done() 22 | for item := range ch { 23 | cb(item) 24 | } 25 | }() 26 | } 27 | 28 | switch iterable.Type().Kind() { 29 | case reflect.Slice: 30 | for i := 0; i < ln; i++ { 31 | ch <- iterable.Index(i).Interface() 32 | } 33 | 34 | case reflect.Map: 35 | for _, key := range iterable.MapKeys() { 36 | ch <- iterable.MapIndex(key).Interface() 37 | } 38 | default: 39 | panic("not a slice") 40 | } 41 | 42 | close(ch) 43 | wg.Wait() 44 | } 45 | -------------------------------------------------------------------------------- /blockchain/source/contracts/TestnetFaucet.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | 4 | import "./SNMMasterchain.sol"; 5 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 6 | 7 | 8 | contract TestnetFaucet is Ownable { 9 | SNMMasterchain token; 10 | 11 | constructor() public { 12 | token = new SNMMasterchain(address(this)); 13 | owner = msg.sender; 14 | token.defrost(); 15 | } 16 | 17 | function getTokens() public returns (bool) { 18 | token.mint(msg.sender, 100*1e18); 19 | return true; 20 | } 21 | 22 | function mintToken(address target, uint256 mintedAmount) public onlyOwner returns (bool) { 23 | token.mint(target, mintedAmount); 24 | return true; 25 | } 26 | 27 | function() public payable{ 28 | getTokens(); 29 | } 30 | 31 | function getTokenAddress() public view returns (address){ 32 | return address(token); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /insonmnia/worker/docker.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "strings" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | type imageID string 14 | 15 | func (m imageID) String() string { 16 | return string(m) 17 | } 18 | 19 | func getImageID(rd io.Reader) (imageID, error) { 20 | resultBytes, err := ioutil.ReadAll(rd) 21 | if err != nil { 22 | return "", err 23 | } 24 | 25 | var result = struct { 26 | ID string `json:"stream"` 27 | Err string `json:"error"` 28 | }{} 29 | 30 | if err := json.Unmarshal(resultBytes, &result); err != nil { 31 | return "", fmt.Errorf("failed to unmarshal Docker response: %v", err) 32 | } 33 | 34 | if len(result.Err) > 0 { 35 | return "", errors.New(result.Err) 36 | } 37 | 38 | result.ID = strings.Replace(result.ID, "Loaded image ID: ", "", -1) 39 | result.ID = strings.Trim(result.ID, "\n") 40 | 41 | return imageID(result.ID), nil 42 | } 43 | -------------------------------------------------------------------------------- /insonmnia/gateway/metrics.go: -------------------------------------------------------------------------------- 1 | package gateway 2 | 3 | // Metrics describes a virtual service metrics. 4 | type Metrics struct { 5 | Connections uint64 6 | InPackets uint64 7 | OutPackets uint64 8 | InBytes uint64 9 | OutBytes uint64 10 | 11 | ConnectionsPerSecond uint64 12 | InPacketsPerSecond uint64 13 | OutPacketsPerSecond uint64 14 | InBytesPerSecond uint64 15 | OutBytesPerSecond uint64 16 | } 17 | 18 | func (m *Metrics) Add(metrics *Metrics) { 19 | m.Connections += metrics.Connections 20 | m.InPackets += metrics.InPackets 21 | m.OutPackets += metrics.OutPackets 22 | m.InBytes += metrics.InBytes 23 | m.OutBytes += metrics.OutBytes 24 | 25 | m.ConnectionsPerSecond += metrics.ConnectionsPerSecond 26 | m.InPacketsPerSecond += metrics.InPacketsPerSecond 27 | m.OutPacketsPerSecond += metrics.OutPacketsPerSecond 28 | m.InBytesPerSecond += metrics.InBytesPerSecond 29 | m.OutBytesPerSecond += metrics.OutBytesPerSecond 30 | } 31 | -------------------------------------------------------------------------------- /connor/price/static.go: -------------------------------------------------------------------------------- 1 | package price 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | ) 7 | 8 | type StaticProviderConfig struct { 9 | Price int64 `yaml:"price" required:"true"` 10 | } 11 | 12 | type StaticFactory struct { 13 | StaticProviderConfig 14 | } 15 | 16 | func (m *StaticFactory) Config() interface{} { 17 | return &m.StaticProviderConfig 18 | } 19 | 20 | func (m *StaticFactory) ValidateConfig() error { 21 | if m.StaticProviderConfig.Price < 0 { 22 | return fmt.Errorf("price value should be positive") 23 | } 24 | 25 | return nil 26 | } 27 | 28 | func (m *StaticFactory) Init(Margin float64) Provider { 29 | return NewStaticProvider(&m.StaticProviderConfig) 30 | } 31 | 32 | type staticProvider struct { 33 | value *big.Int 34 | } 35 | 36 | func NewStaticProvider(cfg *StaticProviderConfig) Provider { 37 | return &staticProvider{value: big.NewInt(cfg.Price)} 38 | } 39 | 40 | func (p *staticProvider) GetPrice() *big.Int { 41 | return p.value 42 | } 43 | -------------------------------------------------------------------------------- /insonmnia/resource/ask_plan_map.go: -------------------------------------------------------------------------------- 1 | package resource 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/pkg/errors" 7 | "github.com/sonm-io/core/proto" 8 | ) 9 | 10 | type askPlanMap map[string]*sonm.AskPlan 11 | 12 | func (m askPlanMap) Sum() (*sonm.AskPlanResources, error) { 13 | sum := &sonm.AskPlanResources{} 14 | for _, askPlan := range m { 15 | if err := sum.Add(askPlan.GetResources()); err != nil { 16 | return nil, err 17 | } 18 | } 19 | return sum, nil 20 | } 21 | 22 | func (m askPlanMap) PopLatest() (*sonm.AskPlan, error) { 23 | if len(m) == 0 { 24 | return nil, errors.New("failed to pop latest ask plan: ask plan map is empty") 25 | } 26 | lastTs := time.Unix(0, 0) 27 | var lastPlan *sonm.AskPlan 28 | for _, plan := range m { 29 | planTime := plan.GetCreateTime().Unix() 30 | if !planTime.Before(lastTs) { 31 | lastTs = planTime 32 | lastPlan = plan 33 | } 34 | } 35 | delete(m, lastPlan.GetID()) 36 | return lastPlan, nil 37 | } 38 | -------------------------------------------------------------------------------- /util/defergroup/mod.go: -------------------------------------------------------------------------------- 1 | package defergroup 2 | 3 | // Just like "defer", but can be canceled. Useful in constructor functions when 4 | // there are multiple resources need to be acquired, but that can fail to be 5 | // allocated itself. 6 | // 7 | // Examples: 8 | // dg := DeferGroup{} 9 | // defer dg.Exec() 10 | // 11 | // resource, err := Allocate() 12 | // if err != nil { 13 | // return err 14 | // } 15 | // dg.Defer(func() { resource.Close() }) 16 | // 17 | // // More allocations. 18 | // 19 | // dg.CancelExec() // Everything is OK, no cleanup required. 20 | // return nil 21 | type DeferGroup struct { 22 | fn []func() 23 | canceled bool 24 | } 25 | 26 | func (m *DeferGroup) Defer(fn func()) { 27 | m.fn = append(m.fn, fn) 28 | } 29 | 30 | func (m *DeferGroup) Exec() { 31 | if m.canceled { 32 | return 33 | } 34 | 35 | for id := range m.fn { 36 | m.fn[len(m.fn)-1-id]() 37 | } 38 | } 39 | 40 | func (m *DeferGroup) CancelExec() { 41 | m.canceled = true 42 | } 43 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/class.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/vishvananda/netlink" 7 | ) 8 | 9 | type ClassAttrs struct { 10 | Link netlink.Link 11 | Handle Handle 12 | Parent Handle 13 | } 14 | 15 | type Class interface { 16 | // Kind returns this class's type. 17 | Kind() string 18 | // Attrs returns basic attributes of this filter. 19 | Attrs() ClassAttrs 20 | // Cmd creates and returns "tc" sub-command using this qdisc. 21 | Cmd() []string 22 | } 23 | 24 | type HTBClass struct { 25 | ClassAttrs 26 | Rate uint64 27 | Ceil uint64 28 | } 29 | 30 | func (m *HTBClass) Kind() string { 31 | return "htb" 32 | } 33 | 34 | func (m *HTBClass) Attrs() ClassAttrs { 35 | return m.ClassAttrs 36 | } 37 | 38 | func (m *HTBClass) Cmd() []string { 39 | return []string{ 40 | "parent", m.Parent.String(), 41 | "classid", m.Handle.String(), 42 | m.Kind(), 43 | "rate", fmt.Sprintf("%d", m.Rate), 44 | "ceil", fmt.Sprintf("%d", m.Ceil), 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cmd/pandora/gun.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/yandex/pandora/core" 7 | "github.com/yandex/pandora/core/aggregate/netsample" 8 | "go.uber.org/zap" 9 | ) 10 | 11 | type Gun interface { 12 | core.Gun 13 | } 14 | 15 | type gun struct { 16 | aggregator core.Aggregator 17 | ext interface{} 18 | log *zap.Logger 19 | } 20 | 21 | func newGun(ext interface{}, log *zap.Logger) Gun { 22 | return &gun{ 23 | ext: ext, 24 | log: log, 25 | } 26 | } 27 | 28 | func (m *gun) Bind(aggregator core.Aggregator) { 29 | m.aggregator = aggregator 30 | } 31 | 32 | func (m *gun) Shoot(ctx context.Context, ammo core.Ammo) { 33 | sample := netsample.Acquire("REQUEST") 34 | 35 | err := ammo.(Ammo).Execute(ctx, m.ext) 36 | 37 | if err == nil { 38 | sample.SetProtoCode(200) 39 | } else { 40 | m.log.Warn("failed to process ammo", zap.Error(err)) 41 | sample.SetErr(err) 42 | sample.SetProtoCode(500) 43 | } 44 | 45 | m.aggregator.Report(sample) 46 | } 47 | -------------------------------------------------------------------------------- /cmd/cli/commands/worker_devices.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sonm-io/core/proto" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var workerDevicesCmd = &cobra.Command{ 11 | Use: "devices", 12 | Short: "Show Worker's hardware", 13 | RunE: func(cmd *cobra.Command, args []string) error { 14 | devices, err := worker.Devices(workerCtx, &sonm.Empty{}) 15 | if err != nil { 16 | return fmt.Errorf("cannot get devices list: %v", err) 17 | } 18 | 19 | printDeviceList(cmd, devices) 20 | return nil 21 | }, 22 | } 23 | 24 | var workerFreeDevicesCmd = &cobra.Command{ 25 | Use: "free_devices", 26 | Short: "Show Worker's hardware with remaining resources available for scheduling", 27 | RunE: func(cmd *cobra.Command, args []string) error { 28 | devices, err := worker.FreeDevices(workerCtx, &sonm.Empty{}) 29 | if err != nil { 30 | return fmt.Errorf("cannot get devices list: %v", err) 31 | } 32 | 33 | printDeviceList(cmd, devices) 34 | return nil 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /cmd/lsgpu/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/sonm-io/core/insonmnia/worker/gpu" 8 | ) 9 | 10 | var appVersion string 11 | 12 | func main() { 13 | fmt.Printf("sonm lspgu %s\r\n", appVersion) 14 | cards, err := gpu.CollectDRICardDevices() 15 | if err != nil { 16 | fmt.Printf("cannot collect card devces: %v\r\n", err) 17 | os.Exit(1) 18 | } 19 | 20 | for _, card := range cards { 21 | fmt.Printf("Card: %s\r\n", card.Path) 22 | if m, err := card.Metrics(); err == nil { 23 | fmt.Printf(" t = %.1f (fan = %.1f%%)\r\n", m.Temperature, m.Fan) 24 | fmt.Printf(" power = %.1fW\r\n", m.Power) 25 | } else { 26 | fmt.Printf(" metrics is not available\r\n") 27 | } 28 | 29 | fmt.Printf(" vid=%d did=%d\r\n", card.VendorID, card.DeviceID) 30 | fmt.Printf(" maj=%d min=%d\r\n", card.Major, card.Minor) 31 | fmt.Printf(" PCI=%s\r\n", card.PCIBusID) 32 | 33 | for _, rel := range card.Devices { 34 | fmt.Printf(" %s\r\n", rel) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/expectThrow.js: -------------------------------------------------------------------------------- 1 | export default async promise => { 2 | try { 3 | await promise; 4 | } catch (error) { 5 | // TODO: Check jump destination to destinguish between a throw 6 | // and an actual invalid jump. 7 | const invalidOpcode = error.message.search('invalid opcode') >= 0; 8 | // TODO: When we contract A calls contract B, and B throws, instead 9 | // of an 'invalid jump', we get an 'out of gas' error. How do 10 | // we distinguish this from an actual out of gas event? (The 11 | // testrpc log actually show an 'invalid jump' event.) 12 | const outOfGas = error.message.search('out of gas') >= 0; 13 | const revert = error.message.search('revert') >= 0; 14 | assert( 15 | invalidOpcode || outOfGas || revert, 16 | 'Expected throw, got \'' + error + '\' instead', 17 | ); 18 | return; 19 | } 20 | assert.fail('Expected throw not received'); 21 | }; 22 | -------------------------------------------------------------------------------- /blockchain/gasLimits.go: -------------------------------------------------------------------------------- 1 | package blockchain 2 | 3 | const ( 4 | getTokensGasLimit = 70000 5 | transferGasLimit = 70000 6 | transferFromGasLimit = 80000 7 | increaseApprovalGasLimit = 70000 8 | decreaseApprovalGasLimit = 70000 9 | approveGasLimit = 70000 10 | placeOrderGasLimit = 650000 11 | cancelOrderGasLimit = 300000 12 | quickBuyGasLimit = 1200000 13 | openDealGasLimit = 600000 14 | closeDealGasLimit = 250000 15 | billGasLimit = 300000 16 | createChangeRequestGasLimit = 300000 17 | cancelChangeRequestGasLimit = 170000 18 | registerWorkerGasLimit = 100000 19 | confirmWorkerGasLimit = 100000 20 | removeWorkerGasLimit = 100000 21 | addMasterGasLimit = 100000 22 | removeMasterGasLimit = 100000 23 | payinGasLimit = 100000 24 | payoutGasLimit = 100000 25 | ) 26 | 27 | func devicesGasLimit(size uint64) uint64 { 28 | return 200000 + size/32*20000 29 | } 30 | -------------------------------------------------------------------------------- /insonmnia/structs/network_spec.go: -------------------------------------------------------------------------------- 1 | package structs 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | 7 | "github.com/pborman/uuid" 8 | "github.com/sonm-io/core/proto" 9 | ) 10 | 11 | type NetworkSpec struct { 12 | *sonm.NetworkSpec 13 | NetID string 14 | } 15 | 16 | func validateNetworkSpec(id string, spec *sonm.NetworkSpec) error { 17 | if len(spec.GetType()) == 0 { 18 | return errors.New("network type is required in network spec") 19 | } 20 | return nil 21 | } 22 | 23 | func NewNetworkSpec(spec *sonm.NetworkSpec) (*NetworkSpec, error) { 24 | id := strings.Replace(uuid.New(), "-", "", -1) 25 | err := validateNetworkSpec(id, spec) 26 | if err != nil { 27 | return nil, err 28 | } 29 | return &NetworkSpec{spec, id}, nil 30 | } 31 | 32 | func NewNetworkSpecs(specs []*sonm.NetworkSpec) ([]*NetworkSpec, error) { 33 | result := make([]*NetworkSpec, 0, len(specs)) 34 | for _, s := range specs { 35 | spec, err := NewNetworkSpec(s) 36 | if err != nil { 37 | return nil, err 38 | } 39 | result = append(result, spec) 40 | } 41 | return result, nil 42 | } 43 | -------------------------------------------------------------------------------- /insonmnia/npp/rendezvous/peer.go: -------------------------------------------------------------------------------- 1 | package rendezvous 2 | 3 | import ( 4 | "github.com/pborman/uuid" 5 | "github.com/sonm-io/core/proto" 6 | "google.golang.org/grpc/peer" 7 | ) 8 | 9 | type Peer struct { 10 | peer.Peer 11 | ID PeerID 12 | privateAddrs []*sonm.Addr 13 | } 14 | 15 | func NewPeer(peerInfo peer.Peer, privateAddrs []*sonm.Addr) Peer { 16 | return Peer{peerInfo, NewPeerID(), privateAddrs} 17 | } 18 | 19 | // PeerID represents an unique peer id generated at the time of either 20 | // publishing or resolving another peer. 21 | // 22 | // This id is used for cleaning resources when a request is finished. Note, 23 | // that we cannot use peer's Ethereum address as an id, because it can be 24 | // shared across multiple servers/clients. 25 | type PeerID string 26 | 27 | // NewPeerID constructs and returns a new unique id used for internal 28 | // identifying peers connected for publishing and resolving each other. 29 | func NewPeerID() PeerID { 30 | return PeerID(uuid.New()) 31 | } 32 | 33 | func (m PeerID) String() string { 34 | return string(m) 35 | } 36 | -------------------------------------------------------------------------------- /proto/tc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | package sonm; 6 | 7 | service QOS { 8 | rpc SetAlias(QOSSetAliasRequest) returns (QOSSetAliasResponse) {} 9 | rpc AddHTBShaping(QOSAddHTBShapingRequest) returns (QOSAddHTBShapingResponse) {} 10 | rpc RemoveHTBShaping(QOSRemoveHTBShapingRequest) returns (QOSRemoveHTBShapingResponse) {} 11 | // Flush completely resets 12 | rpc Flush(QOSFlushRequest) returns (QOSFlushResponse) {} 13 | } 14 | 15 | message QOSSetAliasRequest { 16 | string linkName = 1; 17 | string linkAlias = 2; 18 | } 19 | 20 | message QOSSetAliasResponse {} 21 | 22 | message QOSAddHTBShapingRequest { 23 | string linkName = 1; 24 | string linkAlias = 2; 25 | uint64 rateLimitEgress = 3; 26 | uint64 rateLimitIngress = 4; 27 | } 28 | 29 | message QOSAddHTBShapingResponse {} 30 | 31 | message QOSRemoveHTBShapingRequest { 32 | string linkName = 1; 33 | } 34 | 35 | message QOSRemoveHTBShapingResponse {} 36 | 37 | message QOSFlushRequest {} 38 | 39 | message QOSFlushResponse {} 40 | -------------------------------------------------------------------------------- /insonmnia/worker/cgroup_test.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestParseResources(t *testing.T) { 10 | assertions := assert.New(t) 11 | defer deleteTestConfigFile() 12 | raw := ` 13 | master: 0x0000000000000000000000000000000000000001 14 | endpoint: ":0" 15 | resources: 16 | cgroup: insonmnia 17 | resources: 18 | memory: 19 | limit: 1000 20 | swap: 1024 21 | cpu: 22 | quota: 1024 23 | cpus: "ddd" 24 | logging: 25 | level: debug 26 | ` 27 | err := createTestConfigFile(raw) 28 | assertions.NoError(err) 29 | 30 | conf, err := NewConfig(testWorkerConfigPath) 31 | assertions.NoError(err) 32 | 33 | res := conf.Resources 34 | assertions.NotNil(res) 35 | assertions.NotNil(res.Resources) 36 | assertions.NotNil(res.Resources.Memory) 37 | assertions.Equal(int64(1000), *res.Resources.Memory.Limit) 38 | assertions.Equal(int64(1024), *res.Resources.Memory.Swap) 39 | assertions.Equal(int64(1024), *res.Resources.CPU.Quota) 40 | assertions.Equal("ddd", res.Resources.CPU.Cpus) 41 | } 42 | -------------------------------------------------------------------------------- /proto/container.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/docker/docker/api/types" 9 | "github.com/docker/docker/api/types/container" 10 | ) 11 | 12 | func (m *Registry) Auth() string { 13 | if m == nil { 14 | return "" 15 | } 16 | 17 | data, err := json.Marshal(m.authConfig()) 18 | if err != nil { 19 | return "" 20 | } 21 | 22 | return base64.StdEncoding.EncodeToString(data) 23 | } 24 | 25 | func (m *Registry) authConfig() types.AuthConfig { 26 | return types.AuthConfig{ 27 | Username: m.GetUsername(), 28 | Password: m.GetPassword(), 29 | } 30 | } 31 | 32 | func (m *ContainerRestartPolicy) Unwrap() container.RestartPolicy { 33 | restartPolicy := container.RestartPolicy{} 34 | if m != nil { 35 | restartPolicy.Name = m.Name 36 | restartPolicy.MaximumRetryCount = int(m.MaximumRetryCount) 37 | } 38 | 39 | return restartPolicy 40 | } 41 | 42 | func (m *Container) Validate() error { 43 | if m.GetImage() == "" { 44 | return fmt.Errorf("container image name is required") 45 | } 46 | 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /insonmnia/node/monitoring.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/sonm-io/core/insonmnia/npp" 7 | "github.com/sonm-io/core/proto" 8 | ) 9 | 10 | type monitoringService struct { 11 | nppDialer *npp.Dialer 12 | } 13 | 14 | func newMonitoringAPI(opts *remoteOptions) *monitoringService { 15 | return &monitoringService{ 16 | nppDialer: opts.nppDialer, 17 | } 18 | } 19 | 20 | func (m *monitoringService) MetricsNPP(context.Context, *sonm.Empty) (*sonm.NPPMetricsReply, error) { 21 | metrics, err := m.nppDialer.Metrics() 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | metricsResponse := map[string]*sonm.NamedMetrics{} 27 | 28 | for addr, metric := range metrics { 29 | addrMetrics := make([]*sonm.NamedMetric, 0) 30 | for _, addrMetric := range metric { 31 | addrMetrics = append(addrMetrics, &sonm.NamedMetric{ 32 | Name: addrMetric.Name, 33 | Metric: addrMetric.Metric, 34 | }) 35 | } 36 | 37 | metricsResponse[addr] = &sonm.NamedMetrics{Metrics: addrMetrics} 38 | } 39 | 40 | return &sonm.NPPMetricsReply{Metrics: metricsResponse}, nil 41 | } 42 | -------------------------------------------------------------------------------- /blockchain/source/contracts/DeployList.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | 4 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 5 | 6 | 7 | contract DeployList is Ownable { 8 | address[] deployers; 9 | 10 | event DeployerAdded(address deployer); 11 | 12 | event DeployerRemoved(address deployer); 13 | 14 | constructor(address[] _deployers){ 15 | owner = msg.sender; 16 | deployers = _deployers; 17 | } 18 | 19 | function addDeployer(address _deployer) public onlyOwner { 20 | deployers.push(_deployer); 21 | emit DeployerAdded(_deployer); 22 | } 23 | 24 | function removeDeployer(address _deployer) public onlyOwner { 25 | for (uint i = 0; i < deployers.length - 1; i++) 26 | if (deployers[i] == _deployer) { 27 | deployers[i] = deployers[deployers.length - 1]; 28 | break; 29 | } 30 | deployers.length -= 1; 31 | emit DeployerRemoved(_deployer); 32 | } 33 | 34 | function getDeployers() public view returns (address[]){ 35 | return deployers; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/pandora/gun_dwh.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | 7 | "github.com/sonm-io/core/proto" 8 | "github.com/sonm-io/core/util/xgrpc" 9 | "go.uber.org/zap" 10 | ) 11 | 12 | type DWHExtConfig struct { 13 | Logging LoggingConfig `config:"logging"` 14 | Ethereum EthereumConfig `config:"ethereum"` 15 | DWHEndpoint string `config:"dwh_endpoint"` 16 | } 17 | 18 | type dwhExt struct { 19 | privateKey *ecdsa.PrivateKey 20 | dwh sonm.DWHClient 21 | log *zap.Logger 22 | } 23 | 24 | func NewDWHGun(cfg DWHExtConfig) (Gun, error) { 25 | privateKey := PrivateKey(cfg.Ethereum) 26 | 27 | log, err := NewLogger(cfg.Logging) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | credentials := TransportCredentials(privateKey) 33 | 34 | conn, err := xgrpc.NewClient(context.Background(), cfg.DWHEndpoint, credentials) 35 | if err != nil { 36 | return nil, err 37 | } 38 | dwh := sonm.NewDWHClient(conn) 39 | 40 | ext := &dwhExt{ 41 | privateKey: privateKey, 42 | dwh: dwh, 43 | log: log, 44 | } 45 | return newGun(ext, log), nil 46 | } 47 | -------------------------------------------------------------------------------- /util/certs_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "context" 5 | "crypto/x509" 6 | "testing" 7 | "time" 8 | 9 | ethcrypto "github.com/ethereum/go-ethereum/crypto" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestHitlessRotator(t *testing.T) { 14 | validPeriod := time.Second * 6 15 | require := require.New(t) 16 | priv, err := ethcrypto.GenerateKey() 17 | if err != nil { 18 | t.Fatalf("%v", err) 19 | } 20 | ctx := context.Background() 21 | r, cfg, err := newHitlessCertRotator(ctx, priv, validPeriod) 22 | require.NoError(err) 23 | defer r.Close() 24 | 25 | deadline := time.Now().Add(validPeriod * 2) 26 | for time.Now().Before(deadline) { 27 | tCfg, _ := cfg.GetCertificate(nil) 28 | x509Cert, err := x509.ParseCertificate(tCfg.Certificate[0]) 29 | require.NoError(err) 30 | _, err = checkCert(x509Cert) 31 | require.NoError(err) 32 | 33 | tCfgCl, _ := cfg.GetClientCertificate(nil) 34 | x509CertCl, err := x509.ParseCertificate(tCfgCl.Certificate[0]) 35 | require.NoError(err) 36 | _, err = checkCert(x509CertCl) 37 | require.NoError(err) 38 | 39 | time.Sleep(time.Second) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /insonmnia/oracle/config.go: -------------------------------------------------------------------------------- 1 | package oracle 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/jinzhu/configor" 7 | "github.com/sonm-io/core/accounts" 8 | "github.com/sonm-io/core/blockchain" 9 | "github.com/sonm-io/core/insonmnia/logging" 10 | ) 11 | 12 | type oracleConfig struct { 13 | IsMaster bool `yaml:"is_master" default:"false"` 14 | PriceUpdatePeriod time.Duration `yaml:"price_update_period" default:"15s"` 15 | ContractUpdatePeriod time.Duration `yaml:"contract_update_period" default:"15m"` 16 | Percent float64 `yaml:"deviation_percent" default:"1.0"` 17 | FromNow bool `yaml:"from_now" default:"true"` 18 | } 19 | 20 | type Config struct { 21 | Oracle oracleConfig `yaml:"oracle"` 22 | Log logging.Config `yaml:"log"` 23 | Blockchain *blockchain.Config `yaml:"blockchain"` 24 | Eth accounts.EthConfig `yaml:"ethereum" required:"false"` 25 | } 26 | 27 | func NewConfig(path string) (*Config, error) { 28 | cfg := &Config{} 29 | 30 | err := configor.Load(cfg, path) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return cfg, nil 35 | } 36 | -------------------------------------------------------------------------------- /cmd/cli/commands/version_test.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "testing" 7 | 8 | "github.com/sonm-io/core/cmd/cli/config" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func initRootCmd(t *testing.T, ver string) *bytes.Buffer { 13 | buf := new(bytes.Buffer) 14 | 15 | Root(ver) 16 | 17 | rootCmd.ResetCommands() 18 | rootCmd.ResetFlags() 19 | 20 | rootCmd.SetArgs([]string{""}) 21 | rootCmd.SetOutput(buf) 22 | return buf 23 | } 24 | 25 | func TestGetVersionCmdSimple(t *testing.T) { 26 | cfg = &config.Config{OutFormat: config.OutputModeSimple} 27 | buf := initRootCmd(t, "1.2.3") 28 | 29 | printVersion(rootCmd, version) 30 | out := buf.String() 31 | assert.Contains(t, out, "sonmcli 1.2.3") 32 | } 33 | 34 | func TestGetVersionCmdJson(t *testing.T) { 35 | cfg = &config.Config{OutFormat: config.OutputModeJSON} 36 | buf := initRootCmd(t, "1.2.3") 37 | 38 | printVersion(rootCmd, version) 39 | 40 | v := make(map[string]string) 41 | err := json.Unmarshal(buf.Bytes(), &v) 42 | assert.NoError(t, err) 43 | 44 | assert.Contains(t, v, "version") 45 | assert.Contains(t, v, "platform") 46 | } 47 | -------------------------------------------------------------------------------- /insonmnia/hardware/disk/disk.go: -------------------------------------------------------------------------------- 1 | package disk 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "syscall" 7 | 8 | "github.com/docker/docker/client" 9 | ) 10 | 11 | type Info struct { 12 | TotalBytes uint64 13 | FreeBytes uint64 14 | } 15 | 16 | // FreeDiskSpace returns free bytes for docker root path. 17 | func FreeDiskSpace(ctx context.Context) (*Info, error) { 18 | cli, err := client.NewEnvClient() 19 | if err != nil { 20 | return nil, fmt.Errorf("could not get docker client: %s", err) 21 | } 22 | defer cli.Close() 23 | 24 | info, err := cli.Info(ctx) 25 | if err != nil { 26 | return nil, fmt.Errorf("could not get docker info: %s", err) 27 | } 28 | 29 | path := info.DockerRootDir 30 | var stat syscall.Statfs_t 31 | if err := syscall.Statfs(path, &stat); err != nil { 32 | // if we cannot stat docker root - use system root 33 | if err := syscall.Statfs("/", &stat); err != nil { 34 | return nil, fmt.Errorf("could not perform statfs syscall: %s", err) 35 | } 36 | } 37 | 38 | // blocks * size per block = total size in bytes 39 | return &Info{ 40 | TotalBytes: stat.Blocks * uint64(stat.Bsize), 41 | FreeBytes: stat.Bavail * uint64(stat.Bsize), 42 | }, nil 43 | } 44 | -------------------------------------------------------------------------------- /util/xgrpc/metrics.go: -------------------------------------------------------------------------------- 1 | package xgrpc 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | "google.golang.org/grpc/stats" 8 | ) 9 | 10 | var ( 11 | connectionsGauge = prometheus.NewGauge(prometheus.GaugeOpts{ 12 | Name: "grpc_server_connections_current", 13 | Help: "Number of currently running tasks", 14 | }) 15 | ) 16 | 17 | func init() { 18 | prometheus.MustRegister(connectionsGauge) 19 | } 20 | 21 | type Handler struct{} 22 | 23 | func (h *Handler) TagRPC(ctx context.Context, rpcTagInfo *stats.RPCTagInfo) context.Context { 24 | return ctx 25 | } 26 | 27 | // HandleRPC processes the RPC stats. 28 | func (h *Handler) HandleRPC(context.Context, stats.RPCStats) {} 29 | 30 | func (h *Handler) TagConn(ctx context.Context, connTagInfo *stats.ConnTagInfo) context.Context { 31 | return ctx 32 | } 33 | 34 | // HandleConn processes the Conn stats. 35 | func (h *Handler) HandleConn(ctx context.Context, connStats stats.ConnStats) { 36 | if connStats.IsClient() { 37 | return 38 | } 39 | 40 | switch connStats.(type) { 41 | case *stats.ConnBegin: 42 | connectionsGauge.Inc() 43 | case *stats.ConnEnd: 44 | connectionsGauge.Dec() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cmd/oracle/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "golang.org/x/sync/errgroup" 8 | 9 | "github.com/sonm-io/core/cmd" 10 | "github.com/sonm-io/core/insonmnia/logging" 11 | "github.com/sonm-io/core/insonmnia/oracle" 12 | ) 13 | 14 | func main() { 15 | cmd.NewCmd(run).Execute() 16 | } 17 | 18 | func run(app cmd.AppContext) error { 19 | cfg, err := oracle.NewConfig(app.ConfigPath) 20 | if err != nil { 21 | return fmt.Errorf("failed to load config file: %s", err) 22 | } 23 | 24 | logger, err := logging.BuildLogger(cfg.Log) 25 | if err != nil { 26 | return fmt.Errorf("failed to build logger insance: %s", err) 27 | } 28 | 29 | ctx, cancel := context.WithCancel(context.Background()) 30 | defer cancel() 31 | 32 | o, err := oracle.NewOracle(ctx, logger, cfg) 33 | if err != nil { 34 | return fmt.Errorf("failed to build Oracle instance: %s", err) 35 | } 36 | 37 | wg, ctx := errgroup.WithContext(ctx) 38 | wg.Go(func() error { 39 | return cmd.WaitInterrupted(ctx) 40 | }) 41 | 42 | wg.Go(func() error { 43 | return o.Serve(ctx) 44 | }) 45 | 46 | if err := wg.Wait(); err != nil { 47 | return fmt.Errorf("termination: %s", err) 48 | } 49 | 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/expectEvent.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | 3 | const eventInLogs = (logs, eventName) => { 4 | const event = logs.find(e => e.event === eventName); 5 | assert.exists(event, `event ${eventName} wasn't emitted`); 6 | return event.args; 7 | }; 8 | 9 | const eventInTransaction = async (tx, eventName) => { 10 | const { logs } = await tx; 11 | return eventInLogs(logs, eventName); 12 | }; 13 | 14 | const allEventsInLogs = (logs, eventName) => { 15 | let partLogs; 16 | if (eventName === undefined) { 17 | partLogs = logs; 18 | } else { 19 | partLogs = logs.filter(logs => logs.event === eventName); 20 | } 21 | const events = []; 22 | for (let l of partLogs) { 23 | events.push({ event: l.event, args: l.args }); 24 | } 25 | assert.exists(events, `events ${eventName} wasn't emitted`); 26 | return events; 27 | }; 28 | 29 | const allEventsInTransaction = async (tx, eventName) => { 30 | const { logs } = await tx; 31 | return allEventsInLogs(logs, eventName); 32 | }; 33 | 34 | module.exports = { 35 | eventInLogs, 36 | allEventsInLogs, 37 | eventInTransaction, 38 | allEventsInTransaction, 39 | }; 40 | -------------------------------------------------------------------------------- /insonmnia/worker/ssh_test.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/gliderlabs/ssh" 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestSSHKeyParse(t *testing.T) { 13 | raw := []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCh+u6UN26+nIc42aRhnuDeralPivXZDi3ETSugsNlOfMww5YdqSJc9otSGooPRbXhOVguoEZfBvLNNd4xTkYtaCsWmFGbq3JXCjtH22V3VeqDc1zd3iJGtQU2BInC0HHvR4M5U4ayN4Ur3bEwgBViv7J+2lABmOArVwOlxacI/m2FtmUPrXKLh98eZgvAxd7DLwTjL8DKLJVqk2hqPRbqvX+CVHVZ4EeS63k0ji2mHDDlZrCsm2n6CnOau4sIND4Xiibdtt6dHnXKXxyC1SLQlH1W+6fxdiQSWXK4/Q4ryA0L/t89CoSp+/uRy4xnP3z5ntI7vE+I3Y1kFeTpOy1v9") 14 | 15 | pkey := PublicKey{} 16 | err := pkey.UnmarshalText(raw) 17 | require.NoError(t, err) 18 | 19 | b, err := pkey.MarshalText() 20 | require.NoError(t, err) 21 | 22 | parsed, _, _, _, err := ssh.ParseAuthorizedKey(b) 23 | require.NoError(t, err) 24 | assert.True(t, ssh.KeysEqual(pkey, parsed)) 25 | } 26 | 27 | func TestMarshalEmpty(t *testing.T) { 28 | 29 | var one PublicKey 30 | data, err := json.Marshal(one) 31 | require.NoError(t, err) 32 | 33 | two := PublicKey{} 34 | err = json.Unmarshal(data, &two) 35 | require.NoError(t, err) 36 | } 37 | -------------------------------------------------------------------------------- /debian/sonm-mon.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # summary of how this script can be called: 4 | # * `configure' 5 | # * `abort-upgrade' 6 | # * `abort-remove' `in-favour' 7 | # * `abort-remove' 8 | # * `abort-deconfigure' `in-favour' 9 | # `removing' 10 | # 11 | # 12 | # for details, see dh_installdeb(1) or http://www.debian.org/doc/debian-policy/ 13 | 14 | set -e 15 | 16 | # dh_installdeb will replace this with shell code automatically 17 | # generated by other debhelper scripts. 18 | 19 | #DEBHELPER# 20 | 21 | case "$1" in 22 | configure) 23 | adduser --quiet --system --group --no-create-home --home /var/lib/sonmmon sonmmon 24 | usermod -G video,users,tty,input sonmmon 25 | mkdir -p /var/lib/sonmmon 26 | chown sonmmon /var/lib/sonmmon 27 | ;; 28 | 29 | abort-upgrade|abort-remove|abort-deconfigure) 30 | ;; 31 | 32 | *) 33 | echo "postinst called with unknown argument '$1'" >&2 34 | exit 1 35 | ;; 36 | esac 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /insonmnia/npp/conn.go: -------------------------------------------------------------------------------- 1 | package npp 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | type connResult struct { 8 | conn net.Conn 9 | err error 10 | } 11 | 12 | func newConnResult(conn net.Conn, err error) connResult { 13 | return connResult{conn, err} 14 | } 15 | 16 | func newConnResultOk(conn net.Conn) connResult { 17 | return newConnResult(conn, nil) 18 | } 19 | 20 | func newConnResultErr(err error) connResult { 21 | return newConnResult(nil, err) 22 | } 23 | 24 | func (m *connResult) RemoteAddr() net.Addr { 25 | if m == nil || m.conn == nil { 26 | return nil 27 | } 28 | return m.conn.RemoteAddr() 29 | } 30 | 31 | func (m *connResult) Close() error { 32 | if m == nil || m.conn == nil { 33 | return nil 34 | } 35 | return m.conn.Close() 36 | } 37 | 38 | func (m *connResult) Error() error { 39 | return m.err 40 | } 41 | 42 | func (m *connResult) IsRendezvousError() bool { 43 | if m.err == nil { 44 | return false 45 | } 46 | 47 | _, ok := m.err.(*rendezvousError) 48 | return ok 49 | } 50 | 51 | func (m *connResult) Unwrap() (net.Conn, error) { 52 | return m.conn, m.err 53 | } 54 | 55 | func (m *connResult) UnwrapWithSource(source connSource) (net.Conn, connSource, error) { 56 | return m.conn, source, m.err 57 | } 58 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | sudo: "required" 3 | 4 | language: "go" 5 | 6 | go: 7 | - 1.13.1 8 | 9 | env: 10 | global: 11 | - GO111MODULE=on 12 | - PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 13 | matrix: 14 | - BUILD_TYPE=Tests 15 | - BUILD_TYPE=Debian 16 | - BUILD_TYPE=Contracts 17 | # - BUILD_TYPE=Coverage 18 | 19 | services: 20 | - "docker" 21 | 22 | before_install: 23 | - sudo apt-get update 24 | - sudo apt-get install debhelper devscripts fakeroot dh-systemd ocl-icd-opencl-dev libnl-3-dev libnl-route-3-dev btrfs-tools libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-gfx-dev -y 25 | 26 | script: 27 | - go get github.com/golang/mock/gomock 28 | - go get github.com/golang/mock/mockgen 29 | - | 30 | case "${BUILD_TYPE}" in 31 | Tests) 32 | make all 33 | ;; 34 | Contracts) 35 | make contracts 36 | ;; 37 | Debian) 38 | GO=$(which go) make deb 39 | ;; 40 | Coverage) 41 | make mock 42 | make coverage; 43 | bash <(curl -s https://codecov.io/bash); 44 | ;; 45 | *) 46 | echo "Unknown BUILD_TYPE value" 47 | exit 1 48 | esac 49 | -------------------------------------------------------------------------------- /proto/dwh.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import "strings" 4 | 5 | func NewBenchmarks(benchmarks []uint64) (*Benchmarks, error) { 6 | b := &Benchmarks{ 7 | Values: make([]uint64, len(benchmarks)), 8 | } 9 | copy(b.Values, benchmarks) 10 | if err := b.Validate(); err != nil { 11 | return nil, err 12 | } 13 | return b, nil 14 | } 15 | 16 | func (m *Benchmarks) ToArray() []uint64 { 17 | return m.Values 18 | } 19 | 20 | // GetAttributeName converts profile cert attr number to 21 | // human readable name. 22 | func (m *Certificate) GetAttributeName() string { 23 | attrs := map[uint64]string{ 24 | 1201: "KYC2", 25 | 1301: "KYC3", 26 | 1401: "KYC4", 27 | 1302: "Logo", 28 | 1102: "Name", 29 | 1202: "Website", 30 | 2201: "Phone", 31 | 1303: "Country", 32 | 2202: "E-mail", 33 | 2203: "Social networks", 34 | 1304: "Is corporation", 35 | 1103: "Description", 36 | 1104: "KYC URL", 37 | 1105: "KYC icon", 38 | 1106: "KYC Price", 39 | } 40 | 41 | return attrs[m.GetAttribute()] 42 | } 43 | 44 | // GetAttributeNameNormalized returns GetAttributeName with spaces replaced by underscores. 45 | func (m *Certificate) GetAttributeNameNormalized() string { 46 | return strings.Replace(m.GetAttributeName(), " ", "_", -1) 47 | } 48 | -------------------------------------------------------------------------------- /cmd/pandora/gun_marketplace.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | 7 | "github.com/sonm-io/core/blockchain" 8 | "github.com/sonm-io/core/util" 9 | "go.uber.org/zap" 10 | ) 11 | 12 | type MarketplaceExtConfig struct { 13 | Logging LoggingConfig `config:"logging"` 14 | Ethereum EthereumConfig `config:"ethereum"` 15 | } 16 | 17 | type marketplaceExt struct { 18 | privateKey *ecdsa.PrivateKey 19 | market blockchain.MarketAPI 20 | log *zap.Logger 21 | } 22 | 23 | func NewMarketplaceGun(cfg MarketplaceExtConfig) (Gun, error) { 24 | privateKey := PrivateKey(cfg.Ethereum) 25 | 26 | registryAddr, err := util.HexToAddress(cfg.Ethereum.Registry) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | market, err := blockchain.NewAPI(context.Background(), 32 | blockchain.WithSidechainEndpoint(cfg.Ethereum.Endpoint), 33 | blockchain.WithContractRegistry(registryAddr)) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | log, err := NewLogger(cfg.Logging) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | ext := &marketplaceExt{ 44 | privateKey: privateKey, 45 | market: market.Market(), 46 | log: log, 47 | } 48 | return newGun(ext, log), nil 49 | } 50 | -------------------------------------------------------------------------------- /insonmnia/npp/relay/hashring_test.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestParseEmptyNode(t *testing.T) { 11 | node, err := ParseNode("") 12 | assert.Error(t, err) 13 | assert.Nil(t, node) 14 | } 15 | 16 | func TestParseNode(t *testing.T) { 17 | node, err := ParseNode("uuid@127.0.0.1") 18 | require.NoError(t, err) 19 | require.NotNil(t, node) 20 | 21 | assert.Equal(t, &Node{Name: "uuid", Addr: "127.0.0.1"}, node) 22 | } 23 | 24 | func TestParseNodeEmptyName(t *testing.T) { 25 | node, err := ParseNode("@127.0.0.1") 26 | assert.Error(t, err) 27 | assert.Nil(t, node) 28 | } 29 | 30 | func TestParseNodeEmptyAddr(t *testing.T) { 31 | node, err := ParseNode("uuid@") 32 | assert.Error(t, err) 33 | assert.Nil(t, node) 34 | } 35 | 36 | func TestParseNodeNoSeparator(t *testing.T) { 37 | node, err := ParseNode("uuid") 38 | assert.Error(t, err) 39 | assert.Nil(t, node) 40 | } 41 | 42 | func TestParseNodeSuchMuchSeparator(t *testing.T) { 43 | node, err := ParseNode("sonm@what@127.0.0.1") 44 | require.NoError(t, err) 45 | require.NotNil(t, node) 46 | 47 | assert.Equal(t, &Node{Name: "sonm@what", Addr: "127.0.0.1"}, node) 48 | } 49 | -------------------------------------------------------------------------------- /secexec/src/prctl.rs: -------------------------------------------------------------------------------- 1 | use std::io::Error; 2 | 3 | /// Set the `NO_NEW_PRIVS` attribute to the current thread. 4 | /// 5 | /// Once set, this the `NO_NEW_PRIVS` attribute cannot be unset. 6 | /// The setting of this attribute is inherited by children created 7 | /// by `fork(2)` and `clone(2)`, and preserved across `execve(2)`. 8 | #[inline] 9 | pub fn set_no_new_privs() -> Result<(), Error> { 10 | if unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) } == 0 { 11 | Ok(()) 12 | } else { 13 | Err(Error::last_os_error()) 14 | } 15 | } 16 | 17 | /// Set the state of the "dumpable" flag, which determines whether core dumps 18 | /// are produced for the calling process upon delivery of a signal whose 19 | /// default behavior is to produce a core dump. 20 | /// 21 | /// Processes that are not dumpable can not be attached 22 | /// via `ptrace(2)` `PTRACE_ATTACH`; see `ptrace(2)` for further details. 23 | #[inline] 24 | pub fn set_dumpable(dumpable: bool) -> Result<(), Error> { 25 | let v = if dumpable { 26 | 1 27 | } else { 28 | 0 29 | }; 30 | 31 | if unsafe { libc::prctl(libc::PR_SET_DUMPABLE, v) } == 0 { 32 | Ok(()) 33 | } else { 34 | Err(Error::last_os_error()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /blockchain/source/test/helpers/transactionMined.js: -------------------------------------------------------------------------------- 1 | 2 | // from https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6 3 | module.export = web3.eth.transactionMined = function (txnHash, interval) { 4 | var transactionReceiptAsync; 5 | interval = interval || 500; 6 | transactionReceiptAsync = function (txnHash, resolve, reject) { 7 | try { 8 | var receipt = web3.eth.getTransactionReceipt(txnHash); 9 | if (receipt === null) { 10 | setTimeout(function () { 11 | transactionReceiptAsync(txnHash, resolve, reject); 12 | }, interval); 13 | } else { 14 | resolve(receipt); 15 | } 16 | } catch (e) { 17 | reject(e); 18 | } 19 | }; 20 | 21 | if (Array.isArray(txnHash)) { 22 | var promises = []; 23 | txnHash.forEach(function (oneTxHash) { 24 | promises.push( 25 | web3.eth.getTransactionReceiptMined(oneTxHash, interval)); 26 | }); 27 | return Promise.all(promises); 28 | } else { 29 | return new Promise(function (resolve, reject) { 30 | transactionReceiptAsync(txnHash, resolve, reject); 31 | }); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/filter_test.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestU32Cmd(t *testing.T) { 10 | filter := &U32{ 11 | FilterAttrs: FilterAttrs{ 12 | Link: nil, 13 | Parent: NewHandle(0x8001, 0), 14 | Priority: 7, 15 | Protocol: ProtoAll, 16 | }, 17 | FlowID: NewHandle(0x8001, 1), 18 | Selector: U32Key{ 19 | Val: 0x0, 20 | Mask: 0x0, 21 | Off: 0, 22 | OffMask: 0, 23 | }, 24 | Actions: []Action{}, 25 | } 26 | assert.Equal(t, []string{"parent", "8001:0", "protocol", "all", "prio", "7", "u32", "match", "u32", "0", "0", "flowid", "8001:1"}, filter.Cmd()) 27 | } 28 | 29 | func TestU32CmdIpSelector(t *testing.T) { 30 | filter := &U32{ 31 | FilterAttrs: FilterAttrs{ 32 | Link: nil, 33 | Parent: NewHandle(0x8001, 0), 34 | Priority: 7, 35 | Protocol: ProtoIP, 36 | }, 37 | FlowID: NewHandle(0x8001, 1), 38 | Selector: U32Key{ 39 | Val: 0xac000000, 40 | Mask: 0xff000000, 41 | Off: 0, 42 | OffMask: 0, 43 | }, 44 | Actions: []Action{}, 45 | } 46 | assert.Equal(t, []string{"parent", "8001:0", "protocol", "ip", "prio", "7", "u32", "match", "u32", "ac000000", "ff000000", "flowid", "8001:1"}, filter.Cmd()) 47 | } 48 | -------------------------------------------------------------------------------- /insonmnia/worker/plugin/cleanup.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sonm-io/core/insonmnia/worker/volume" 7 | ) 8 | 9 | // Cleanup describes an interface for resource freeing. 10 | // 11 | // The behavior of Close after the first call is undefined. 12 | type Cleanup interface { 13 | // Close performs cleanup handling for the resource acquired. 14 | Close() error 15 | } 16 | 17 | type nestedCleanup struct { 18 | children []Cleanup 19 | } 20 | 21 | func newNestedCleanup() *nestedCleanup { 22 | return &nestedCleanup{ 23 | children: make([]Cleanup, 0), 24 | } 25 | } 26 | 27 | func (c *nestedCleanup) Add(v Cleanup) { 28 | c.children = append(c.children, v) 29 | } 30 | 31 | func (c *nestedCleanup) Close() error { 32 | errors := make([]error, 0) 33 | for _, v := range c.children { 34 | if err := v.Close(); err != nil { 35 | errors = append(errors, err) 36 | } 37 | } 38 | 39 | // Avoiding double call. 40 | *c = *newNestedCleanup() 41 | 42 | if len(errors) == 0 { 43 | return nil 44 | } else { 45 | return fmt.Errorf("%+v", errors) 46 | } 47 | } 48 | 49 | type volumeCleanup struct { 50 | driver volume.VolumeDriver 51 | id string 52 | } 53 | 54 | func (v volumeCleanup) Close() error { 55 | return v.driver.RemoveVolume(v.id) 56 | } 57 | -------------------------------------------------------------------------------- /util/multierror/error.go: -------------------------------------------------------------------------------- 1 | package multierror 2 | 3 | import ( 4 | "strings" 5 | "sync" 6 | 7 | "github.com/hashicorp/go-multierror" 8 | ) 9 | 10 | func NewMultiError() *multierror.Error { 11 | return &multierror.Error{ErrorFormat: errorFormat} 12 | } 13 | 14 | func NewTSMultiError() *TSMultiError { 15 | return &TSMultiError{inner: &multierror.Error{ErrorFormat: errorFormat}} 16 | } 17 | 18 | func Append(err error, errs ...error) *multierror.Error { 19 | return multierror.Append(err, errs...) 20 | } 21 | 22 | func AppendUnique(err *multierror.Error, other error) *multierror.Error { 23 | for _, e := range err.WrappedErrors() { 24 | if e.Error() == other.Error() { 25 | return err 26 | } 27 | } 28 | return Append(err, other) 29 | } 30 | 31 | func errorFormat(errs []error) string { 32 | var s []string 33 | for _, e := range errs { 34 | s = append(s, e.Error()) 35 | } 36 | 37 | return strings.Join(s, ", ") 38 | 39 | } 40 | 41 | type TSMultiError struct { 42 | mu sync.Mutex 43 | inner *multierror.Error 44 | } 45 | 46 | func (m *TSMultiError) Append(errs ...error) { 47 | m.mu.Lock() 48 | defer m.mu.Unlock() 49 | m.inner = multierror.Append(m.inner, errs...) 50 | } 51 | 52 | func (m *TSMultiError) ErrorOrNil() error { 53 | return m.inner.ErrorOrNil() 54 | } 55 | -------------------------------------------------------------------------------- /insonmnia/gateway/pool.go: -------------------------------------------------------------------------------- 1 | package gateway 2 | 3 | import ( 4 | "errors" 5 | "math/rand" 6 | "sync" 7 | 8 | "gopkg.in/oleiade/lane.v1" 9 | ) 10 | 11 | type PortPool struct { 12 | queue *lane.Queue 13 | used map[string]uint16 14 | mu sync.Mutex 15 | } 16 | 17 | func NewPortPool(init, size uint16) *PortPool { 18 | p := &PortPool{ 19 | queue: lane.NewQueue(), 20 | used: make(map[string]uint16, size), 21 | } 22 | 23 | for _, v := range rand.Perm(int(size)) { 24 | p.queue.Enqueue(init + uint16(v)) 25 | } 26 | 27 | return p 28 | } 29 | 30 | func (p *PortPool) Assign(ID string) (uint16, error) { 31 | p.mu.Lock() 32 | defer p.mu.Unlock() 33 | 34 | if _, exists := p.used[ID]; exists { 35 | return 0, errors.New("named port is already in use") 36 | } 37 | 38 | port := p.queue.Dequeue() 39 | if port == nil { 40 | return 0, errors.New("no ports left for allocation") 41 | } 42 | 43 | p.used[ID] = port.(uint16) 44 | 45 | return port.(uint16), nil 46 | } 47 | 48 | func (p *PortPool) Retain(ID string) error { 49 | p.mu.Lock() 50 | defer p.mu.Unlock() 51 | 52 | if port, exists := p.used[ID]; exists { 53 | p.queue.Enqueue(port) 54 | delete(p.used, ID) 55 | } else { 56 | return errors.New("named port was never assigned") 57 | } 58 | 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /proto/relay.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/btcsuite/btcd/chaincfg/chainhash" 8 | "github.com/ethereum/go-ethereum/crypto" 9 | ) 10 | 11 | // Validate validates the incoming handshake request. 12 | func (m *HandshakeRequest) Validate() error { 13 | if len(m.Addr) != 20 { 14 | return fmt.Errorf("address must have exactly 20 bytes format") 15 | } 16 | 17 | switch m.PeerType { 18 | case PeerType_SERVER: 19 | if len(m.Sign) == 0 { 20 | return fmt.Errorf("sign field must not be empty for server-side handshake") 21 | } 22 | 23 | hash := chainhash.DoubleHashB(m.Addr) 24 | publicKey, err := crypto.SigToPub(hash, m.Sign) 25 | if err != nil { 26 | return fmt.Errorf("invalid signature") 27 | } 28 | 29 | if !bytes.Equal(crypto.PubkeyToAddress(*publicKey).Bytes(), m.Addr) { 30 | return fmt.Errorf("invalid signature for provided ETH address") 31 | } 32 | case PeerType_CLIENT: 33 | if len(m.Sign) != 0 { 34 | return fmt.Errorf("sign field must be empty for client-side handshake") 35 | } 36 | default: 37 | return fmt.Errorf("unknown peer type: %s", m.PeerType) 38 | } 39 | 40 | return nil 41 | } 42 | 43 | // HasUUID returns true if a request has UUID provided. 44 | func (m *HandshakeRequest) HasUUID() bool { 45 | return len(m.UUID) != 0 46 | } 47 | -------------------------------------------------------------------------------- /insonmnia/gateway/pool_test.go: -------------------------------------------------------------------------------- 1 | package gateway 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestPool(t *testing.T) { 10 | p := NewPortPool(10, 2) 11 | 12 | port, err := p.Assign("0") 13 | assert.NoError(t, err) 14 | assert.True(t, port == 10 || port == 11) 15 | 16 | port, err = p.Assign("1") 17 | assert.NoError(t, err) 18 | assert.True(t, port == 10 || port == 11) 19 | 20 | port, err = p.Assign("2") 21 | assert.Error(t, err) 22 | assert.Equal(t, uint16(0), port) 23 | 24 | } 25 | 26 | func TestPoolRetainWhileEmpty(t *testing.T) { 27 | p := NewPortPool(10, 0) 28 | 29 | err := p.Retain("0") 30 | assert.Error(t, err) 31 | } 32 | 33 | func TestPoolDoubleAssign(t *testing.T) { 34 | p := NewPortPool(10, 2) 35 | 36 | port, err := p.Assign("0") 37 | assert.NoError(t, err) 38 | assert.True(t, port == 10 || port == 11) 39 | 40 | port, err = p.Assign("0") 41 | assert.Error(t, err) 42 | assert.True(t, port == 0) 43 | } 44 | 45 | func TestPoolAssignRetainAssign(t *testing.T) { 46 | p := NewPortPool(10, 1) 47 | 48 | port, err := p.Assign("0") 49 | assert.NoError(t, err) 50 | assert.True(t, port == 10) 51 | 52 | err = p.Retain("0") 53 | assert.NoError(t, err) 54 | 55 | port, err = p.Assign("0") 56 | assert.NoError(t, err) 57 | assert.True(t, port == 10) 58 | } 59 | -------------------------------------------------------------------------------- /insonmnia/worker/network/tc/ifb.go: -------------------------------------------------------------------------------- 1 | package tc 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | modprobe = "modprobe" 11 | ifbModuleName = "ifb" 12 | ) 13 | 14 | // IFBInit loads the Intermediate Functional Block device kernel module. 15 | // 16 | // It is used in conjunction with HTB queueing discipline to allow for 17 | // queueing incoming traffic for shaping instead of dropping. 18 | func IFBInit() error { 19 | return execModProbe(ifbModuleName, "numifbs=0") 20 | } 21 | 22 | // IFBClose unloads the Intermediate Functional Block device kernel module. 23 | func IFBClose() error { 24 | return execModProbe(ifbModuleName, "-r") 25 | } 26 | 27 | // IFBFlush completely reloads the Intermediate Functional Block device kernel 28 | // module. 29 | func IFBFlush() error { 30 | if err := IFBClose(); err != nil { 31 | return err 32 | } 33 | if err := IFBInit(); err != nil { 34 | return err 35 | } 36 | 37 | return nil 38 | } 39 | 40 | func execModProbe(args ...string) error { 41 | bin, err := exec.LookPath(modprobe) 42 | if err != nil { 43 | return fmt.Errorf("failed to find `modprobe`: %s", err) 44 | } 45 | 46 | cmd := exec.Command(bin, args...) 47 | 48 | if err := cmd.Run(); err != nil { 49 | return fmt.Errorf("failed to execute `modprobe %s`: %v", strings.Join(args, " "), err) 50 | } 51 | 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /util/debug/pprof.go: -------------------------------------------------------------------------------- 1 | package debug 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "net/http/pprof" 9 | 10 | "go.uber.org/zap" 11 | ) 12 | 13 | const ( 14 | prefix = "/debug/pprof" 15 | ipAddr = "localhost" 16 | ) 17 | 18 | type Config struct { 19 | Port uint16 `yaml:"port" default:"6060"` 20 | } 21 | 22 | // ServePProf starts pprof HTTP server on the specified port, blocking until 23 | // the context is done. 24 | func ServePProf(ctx context.Context, cfg Config, log *zap.Logger) error { 25 | addr := fmt.Sprintf("%s:%d", ipAddr, cfg.Port) 26 | listener, err := net.Listen("tcp", addr) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | defer listener.Close() 32 | 33 | go func() error { 34 | log.Sugar().Infof("starting pprof server on %s", addr) 35 | defer log.Sugar().Infof("stopped pprof server on %s", addr) 36 | 37 | return http.Serve(listener, newHandler(prefix)) 38 | }() 39 | 40 | <-ctx.Done() 41 | return ctx.Err() 42 | } 43 | 44 | func newHandler(prefix string) http.Handler { 45 | handler := http.NewServeMux() 46 | handler.HandleFunc(prefix+"/", pprof.Index) 47 | handler.HandleFunc(prefix+"/cmdline", pprof.Cmdline) 48 | handler.HandleFunc(prefix+"/profile", pprof.Profile) 49 | handler.HandleFunc(prefix+"/symbol", pprof.Symbol) 50 | handler.HandleFunc(prefix+"/trace", pprof.Trace) 51 | 52 | return handler 53 | } 54 | -------------------------------------------------------------------------------- /insonmnia/npp/relay/logging.go: -------------------------------------------------------------------------------- 1 | // This module is used as a glue for connecting our Zap logging with logging 2 | // system of MemberList package. 3 | // 4 | // As an intermediate adapter it parses the written logging event splitting 5 | // the received message into severity and the message itself. Additionally 6 | // all datetime formatting is truncated, because it anyway be replaced with 7 | // Zap one. 8 | 9 | package relay 10 | 11 | import ( 12 | "io" 13 | "regexp" 14 | "strings" 15 | 16 | "go.uber.org/zap" 17 | ) 18 | 19 | type logAdapter struct { 20 | log *zap.Logger 21 | rx *regexp.Regexp 22 | } 23 | 24 | func newLogAdapter(log *zap.Logger) io.Writer { 25 | return &logAdapter{ 26 | log: log.WithOptions(zap.AddCallerSkip(3)), 27 | rx: regexp.MustCompile(`\[(\w+)] \w+:(.*)`), 28 | } 29 | } 30 | 31 | func (m *logAdapter) Write(p []byte) (int, error) { 32 | matches := m.rx.FindSubmatch(p[20:]) 33 | if len(matches) != 3 { 34 | return len(p), nil 35 | } 36 | 37 | level := string(matches[1]) 38 | message := strings.ToLower(strings.TrimSpace(string(matches[2]))) 39 | switch level { 40 | case "DEBUG": 41 | m.log.Debug(message) 42 | case "INFO": 43 | m.log.Info(message) 44 | case "WARN": 45 | m.log.Warn(message) 46 | case "ERROR", "FATAL": 47 | m.log.Error(message) 48 | default: 49 | m.log.Info(message) 50 | } 51 | 52 | return len(p), nil 53 | } 54 | -------------------------------------------------------------------------------- /optimus/knapsack.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "github.com/sonm-io/core/proto" 5 | ) 6 | 7 | type Knapsack struct { 8 | manager *DeviceManager 9 | plans []*sonm.AskPlan 10 | } 11 | 12 | func NewKnapsack(deviceManager *DeviceManager) *Knapsack { 13 | return &Knapsack{ 14 | manager: deviceManager, 15 | } 16 | } 17 | 18 | func (m *Knapsack) Clone() *Knapsack { 19 | plans := make([]*sonm.AskPlan, len(m.plans)) 20 | copy(plans, m.plans) 21 | 22 | return &Knapsack{ 23 | manager: m.manager.Clone(), 24 | plans: plans, 25 | } 26 | } 27 | 28 | func (m *Knapsack) Put(order *sonm.Order) error { 29 | resources, err := m.manager.Consume(*order.GetBenchmarks(), *order.GetNetflags()) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | resources.Network.NetFlags = order.GetNetflags() 35 | 36 | m.plans = append(m.plans, &sonm.AskPlan{ 37 | OrderID: order.GetId(), 38 | Price: &sonm.Price{PerSecond: order.Price}, 39 | Duration: &sonm.Duration{Nanoseconds: 1e9 * int64(order.Duration)}, 40 | Resources: resources, 41 | }) 42 | 43 | return nil 44 | } 45 | 46 | func (m *Knapsack) Price() *sonm.Price { 47 | return sonm.SumPrice(m.plans) 48 | } 49 | 50 | func (m *Knapsack) PPSf64() float64 { 51 | return float64(m.Price().GetPerSecond().Unwrap().Uint64()) * 1e-18 52 | } 53 | 54 | func (m *Knapsack) Plans() []*sonm.AskPlan { 55 | return m.plans 56 | } 57 | -------------------------------------------------------------------------------- /optimus/normalize_test.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestNormalize(t *testing.T) { 11 | values := []float64{ 12 | 0.0, 13 | 1.0, 14 | 5.0, 15 | 10.0, 16 | } 17 | normalizer, err := newNormalizer(values...) 18 | 19 | require.NotNil(t, normalizer) 20 | require.NoError(t, err) 21 | 22 | normalizer.NormalizeBatch(values) 23 | 24 | assert.Equal(t, 0.0, values[0]) 25 | assert.Equal(t, 0.1, values[1]) 26 | assert.Equal(t, 0.5, values[2]) 27 | assert.Equal(t, 1.0, values[3]) 28 | } 29 | 30 | func TestMeanNormalize(t *testing.T) { 31 | values := []float64{ 32 | 0.0, 33 | 1.0, 34 | 5.0, 35 | 10.0, 36 | } 37 | normalizer, err := newMeanNormalizer(values) 38 | 39 | require.NotNil(t, normalizer) 40 | require.NoError(t, err) 41 | 42 | normalizer.NormalizeBatch(values) 43 | 44 | assert.Equal(t, -0.4, values[0]) 45 | assert.Equal(t, -0.3, values[1]) 46 | assert.Equal(t, +0.1, values[2]) 47 | assert.Equal(t, +0.6, values[3]) 48 | } 49 | 50 | func TestMeanNormalizeDegeneratedVector(t *testing.T) { 51 | values := []float64{ 52 | 1.0, 53 | 1.0, 54 | 1.0, 55 | 1.0, 56 | } 57 | normalizer, err := newMeanNormalizer(values) 58 | 59 | require.Nil(t, normalizer) 60 | require.EqualError(t, err, ErrDegenerateVector.Error()) 61 | } 62 | -------------------------------------------------------------------------------- /util/rest/errors.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "net/http" 5 | 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | ) 9 | 10 | func HTTPStatusFromError(err error) int { 11 | switch err.(type) { 12 | case nil: 13 | return http.StatusOK 14 | default: 15 | s, ok := status.FromError(err) 16 | if !ok { 17 | return http.StatusInternalServerError 18 | } 19 | 20 | return HTTPStatusFromCode(s.Code()) 21 | } 22 | } 23 | 24 | func HTTPStatusFromCode(code codes.Code) int { 25 | switch code { 26 | case codes.OK: 27 | return http.StatusOK 28 | case codes.Canceled: 29 | return http.StatusRequestTimeout 30 | case codes.InvalidArgument, codes.OutOfRange: 31 | return http.StatusBadRequest 32 | case codes.DeadlineExceeded: 33 | return http.StatusGatewayTimeout 34 | case codes.NotFound: 35 | return http.StatusNotFound 36 | case codes.PermissionDenied: 37 | return http.StatusForbidden 38 | case codes.Unauthenticated: 39 | return http.StatusUnauthorized 40 | case codes.ResourceExhausted: 41 | return http.StatusTooManyRequests 42 | case codes.Unimplemented: 43 | return http.StatusNotImplemented 44 | case codes.Unavailable: 45 | return http.StatusServiceUnavailable 46 | case codes.Unknown, codes.DataLoss, codes.Internal: 47 | return http.StatusInternalServerError 48 | default: 49 | return http.StatusInternalServerError 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /etc/oracle.yaml: -------------------------------------------------------------------------------- 1 | # Logging settings. 2 | log: 3 | # The desired logging level. 4 | # Allowed values are "debug", "info", "warn", "error", "panic" and "fatal" 5 | level: debug 6 | 7 | # Settings for Ethereum keys 8 | ethereum: 9 | # path to keystore 10 | key_store: "./keys/" 11 | # passphrase for keystore 12 | pass_phrase: "any" 13 | 14 | blockchain: 15 | #endpoint: https://rinkeby.infura.io/00iTrs5PIy0uGODwcsrb 16 | #sidechain_endpoint: https://sidechain-dev.sonm.com 17 | #contract_registry: 0xaf1ffd7f652be7e9a0854a42b2d3046f853f80f1 18 | blocks_batch_size: 50000 19 | 20 | oracle: 21 | # In master mode this instance submitting price changing 22 | # In slave mode this instance confirm changing 23 | is_master: false 24 | # from_now` parameter forces Oracle to process transactions only from the current block, otherwise, it will read whole transaction history from the beginning of times. 25 | # This parameter works only if slave mode is active. 26 | # Default: true. 27 | # from_now: true 28 | # priceUpdatePeriod defines period to update snm/usd price in this oracle instance 29 | #price_update_period: "15s" 30 | # contractUpdatePeriod defines period to update snm/usd price in oracle contract 31 | #contract_update_period: "10s" 32 | # Deviation percent define difference of deviation between actual price and confirming price 33 | #deviation_percent: 1.0 34 | 35 | -------------------------------------------------------------------------------- /insonmnia/auth/common_test.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/ethereum/go-ethereum/common" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestEqualAddresses(t *testing.T) { 12 | cases := []struct { 13 | a string 14 | b string 15 | isEq bool 16 | }{ 17 | { 18 | a: "1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB", 19 | b: "1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", 20 | isEq: true, 21 | }, 22 | { 23 | a: "1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB", 24 | b: "0x1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", 25 | isEq: true, 26 | }, 27 | { 28 | a: "1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB", 29 | b: "2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB", 30 | isEq: false, 31 | }, 32 | { 33 | a: "0x1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB", 34 | b: "0x1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB", 35 | isEq: true, 36 | }, 37 | { 38 | a: "0x0", 39 | b: "0x1", 40 | isEq: false, 41 | }, 42 | { 43 | a: "0", 44 | b: "1", 45 | isEq: false, 46 | }, 47 | { 48 | a: "0x", 49 | b: "0x", 50 | isEq: true, 51 | }, 52 | } 53 | 54 | for _, cc := range cases { 55 | a := common.HexToAddress(cc.a) 56 | b := common.HexToAddress(cc.b) 57 | assert.Equal(t, cc.isEq, equalAddresses(a, b), fmt.Sprintf("compare %s and %s failed", cc.a, cc.b)) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cmd/connor/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/noxiouz/zapctx/ctxlog" 7 | "github.com/sonm-io/core/cmd" 8 | "github.com/sonm-io/core/connor" 9 | "github.com/sonm-io/core/insonmnia/logging" 10 | "github.com/sonm-io/core/util/metrics" 11 | "golang.org/x/net/context" 12 | "golang.org/x/sync/errgroup" 13 | ) 14 | 15 | func main() { 16 | cmd.NewCmd(run).Execute() 17 | } 18 | 19 | func run(app cmd.AppContext) error { 20 | cfg, err := connor.NewConfig(app.ConfigPath) 21 | if err != nil { 22 | return fmt.Errorf("failed to load config file: %s", err) 23 | } 24 | 25 | log, err := logging.BuildLogger(cfg.Log) 26 | if err != nil { 27 | return fmt.Errorf("failed to build logger instance: %s", err) 28 | } 29 | 30 | ctx := ctxlog.WithLogger(context.Background(), log) 31 | 32 | wg, ctx := errgroup.WithContext(ctx) 33 | wg.Go(func() error { 34 | return cmd.WaitInterrupted(ctx) 35 | }) 36 | wg.Go(func() error { 37 | server, err := connor.New(ctx, cfg, log) 38 | if err != nil { 39 | return fmt.Errorf("failed to build Connor instance: %s", err) 40 | } 41 | 42 | return server.Serve(ctx) 43 | }) 44 | wg.Go(func() error { 45 | return metrics.NewPrometheusExporter(cfg.Metrics, metrics.WithLogging(log.Sugar())).Serve(ctx) 46 | }) 47 | 48 | if err := wg.Wait(); err != nil { 49 | return fmt.Errorf("connor termination: %s", err) 50 | } 51 | 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /optimus/cgroup_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package optimus 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | 9 | "github.com/opencontainers/runtime-spec/specs-go" 10 | "github.com/sonm-io/core/insonmnia/cgroups" 11 | ) 12 | 13 | const ( 14 | defaultCPUPeriod = uint64(100000) 15 | ) 16 | 17 | func RestrictUsage(cfg *RestrictionsConfig) (Deleter, error) { 18 | control, _, err := cgroups.NewCgroupManager(cfg.Name, convertLinuxResources(cfg)) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | if err := control.Add(cgroups.Process{Pid: os.Getpid()}); err != nil { 24 | return nil, fmt.Errorf("failed to add Optimus into cgroup: %v", err) 25 | } 26 | 27 | return control, nil 28 | } 29 | 30 | func convertLinuxResources(cfg *RestrictionsConfig) *specs.LinuxResources { 31 | return &specs.LinuxResources{ 32 | CPU: convertCPUConfig(cfg), 33 | Memory: convertMemoryConfig(cfg), 34 | } 35 | } 36 | 37 | func convertCPUConfig(cfg *RestrictionsConfig) *specs.LinuxCPU { 38 | quota := int64(float64(defaultCPUPeriod) * cfg.CPUCount) 39 | period := defaultCPUPeriod 40 | 41 | return &specs.LinuxCPU{ 42 | Quota: "a, 43 | Period: &period, 44 | } 45 | } 46 | 47 | func convertMemoryConfig(cfg *RestrictionsConfig) *specs.LinuxMemory { 48 | if cfg.MemoryLimit == 0 { 49 | return nil 50 | } 51 | 52 | v := int64(cfg.MemoryLimit * (1 << 20)) 53 | 54 | return &specs.LinuxMemory{ 55 | Limit: &v, 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /optimus/watcher.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "context" 5 | "time" 6 | ) 7 | 8 | type Watcher interface { 9 | OnRun() 10 | OnShutdown() 11 | Execute(ctx context.Context) 12 | } 13 | 14 | type managedWatcher struct { 15 | watcher Watcher 16 | timeout time.Duration 17 | } 18 | 19 | func newManagedWatcher(watcher Watcher, timeout time.Duration) *managedWatcher { 20 | return &managedWatcher{ 21 | watcher: watcher, 22 | timeout: timeout, 23 | } 24 | } 25 | 26 | func (m *managedWatcher) Run(ctx context.Context) error { 27 | m.watcher.OnRun() 28 | defer m.watcher.OnShutdown() 29 | 30 | timer := time.NewTicker(m.timeout) 31 | defer timer.Stop() 32 | 33 | m.watcher.Execute(ctx) 34 | 35 | for { 36 | select { 37 | case <-ctx.Done(): 38 | return ctx.Err() 39 | case <-timer.C: 40 | m.watcher.Execute(ctx) 41 | } 42 | } 43 | } 44 | 45 | type reactiveWatcher struct { 46 | channel <-chan struct{} 47 | watcher Watcher 48 | } 49 | 50 | func newReactiveWatcher(channel <-chan struct{}, watcher Watcher) *reactiveWatcher { 51 | return &reactiveWatcher{ 52 | channel: channel, 53 | watcher: watcher, 54 | } 55 | } 56 | 57 | func (m *reactiveWatcher) Run(ctx context.Context) error { 58 | m.watcher.OnRun() 59 | defer m.watcher.OnShutdown() 60 | 61 | for { 62 | select { 63 | case <-ctx.Done(): 64 | return ctx.Err() 65 | case <-m.channel: 66 | m.watcher.Execute(ctx) 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /insonmnia/npp/relay/errors.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sonm-io/core/proto" 7 | ) 8 | 9 | const ( 10 | ErrInvalidHandshake int32 = iota 11 | ErrUnknownPeerType 12 | ErrTimeout 13 | ErrNoPeer 14 | ErrWrongNode 15 | ErrEmptyContinuum 16 | ) 17 | 18 | type protocolError struct { 19 | code int32 20 | description string 21 | } 22 | 23 | func newProtocolError(code int32, err error) *protocolError { 24 | return &protocolError{ 25 | code: code, 26 | description: err.Error(), 27 | } 28 | } 29 | 30 | func (m *protocolError) Error() string { 31 | return fmt.Sprintf("[%d] %s", m.code, m.description) 32 | } 33 | 34 | func errInvalidHandshake(err error) error { 35 | return newProtocolError(ErrInvalidHandshake, fmt.Errorf("invalid handshake: %s", err.Error())) 36 | } 37 | 38 | func errUnknownType(ty sonm.PeerType) error { 39 | return newProtocolError(ErrUnknownPeerType, fmt.Errorf("unknown handshake peer type: %s", ty)) 40 | } 41 | 42 | func errTimeout() error { 43 | return newProtocolError(ErrTimeout, fmt.Errorf("timed out")) 44 | } 45 | 46 | func errNoPeer() error { 47 | return newProtocolError(ErrNoPeer, fmt.Errorf("no peer found")) 48 | } 49 | 50 | func errWrongNode() error { 51 | return newProtocolError(ErrWrongNode, fmt.Errorf("peer connected to wrong node")) 52 | } 53 | 54 | func errEmptyContinuum() error { 55 | return newProtocolError(ErrEmptyContinuum, fmt.Errorf("no nodes in the continuum")) 56 | } 57 | -------------------------------------------------------------------------------- /cmd/secterm/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sonm-io/core/insonmnia/auth" 9 | "github.com/sonm-io/core/secsh/secshc" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var ( 14 | configPath string 15 | ) 16 | 17 | func init() { 18 | rootCmd.Flags().StringVar(&configPath, "config", "etc/secterm.yaml", "Path to the configuration file") 19 | } 20 | 21 | func runSecTerm(v string) error { 22 | addr, err := auth.ParseAddr(v) 23 | if err != nil { 24 | return fmt.Errorf("failed to parse target address: %v", err) 25 | } 26 | 27 | cfg, err := secshc.NewRPTYConfig(configPath) 28 | if err != nil { 29 | return fmt.Errorf("failed to load config: %v", err) 30 | } 31 | 32 | tty, err := secshc.NewRemotePTY(cfg) 33 | if err != nil { 34 | return fmt.Errorf("failed to construct remote PTY: %v", err) 35 | } 36 | 37 | if err := tty.Run(context.Background(), *addr); err != nil { 38 | return fmt.Errorf("failed to run remote PTY: %v", err) 39 | } 40 | 41 | return nil 42 | } 43 | 44 | var rootCmd = &cobra.Command{ 45 | Use: "secterm ADDR", 46 | Short: "Secure PTY", 47 | Args: cobra.ExactArgs(1), 48 | Run: func(cmd *cobra.Command, args []string) { 49 | if err := runSecTerm(args[0]); err != nil { 50 | fmt.Printf("ERROR: %v\n\r", err) 51 | os.Exit(1) 52 | } 53 | }, 54 | } 55 | 56 | func main() { 57 | if err := rootCmd.Execute(); err != nil { 58 | fmt.Printf("ERROR: %v\n\r", err) 59 | os.Exit(1) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /proto/ask_plan.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/sonm-io/core/proto;sonm"; 4 | 5 | import "bigint.proto"; 6 | import "capabilities.proto"; 7 | import "insonmnia.proto"; 8 | import "marketplace.proto"; 9 | import "timestamp.proto"; 10 | 11 | package sonm; 12 | 13 | message AskPlanCPU { 14 | uint64 core_percents = 1; 15 | } 16 | 17 | message AskPlanGPU { 18 | repeated uint64 indexes = 1; 19 | repeated string hashes = 2; 20 | } 21 | 22 | message AskPlanRAM { 23 | DataSize size = 1; 24 | } 25 | 26 | message AskPlanStorage { 27 | DataSize size = 1; 28 | } 29 | 30 | message AskPlanNetwork { 31 | DataSizeRate throughputIn = 1; 32 | DataSizeRate throughputOut = 2; 33 | NetFlags netFlags = 3; 34 | } 35 | 36 | message AskPlanResources { 37 | AskPlanCPU CPU = 1; 38 | AskPlanRAM RAM = 2; 39 | AskPlanStorage storage = 3; 40 | AskPlanGPU GPU = 4; 41 | AskPlanNetwork network = 5; 42 | } 43 | 44 | message AskPlan { 45 | enum Status { 46 | ACTIVE = 0; 47 | PENDING_DELETION = 1; 48 | } 49 | string ID = 1; 50 | BigInt orderID = 2; 51 | BigInt dealID = 3; 52 | Duration duration = 4; 53 | Price price = 5; 54 | EthAddress blacklist = 6; 55 | EthAddress counterparty = 7; 56 | IdentityLevel identity = 8; 57 | bytes tag = 9; 58 | AskPlanResources resources = 10; 59 | Status status = 11; 60 | Timestamp createTime = 12; 61 | Timestamp lastOrderPlacedTime = 13; 62 | } 63 | -------------------------------------------------------------------------------- /connor/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/sonm-io/core/proto" 5 | ) 6 | 7 | type TaskStatus struct { 8 | *sonm.TaskStatusReply 9 | ID string 10 | } 11 | 12 | type OrdersSets struct { 13 | Create []*Corder 14 | Restore []*Corder 15 | Cancel []*Corder 16 | } 17 | 18 | func DivideOrdersSets(existingCorders, targetCorders []*Corder) *OrdersSets { 19 | existingByBenchmark := map[uint64]*Corder{} 20 | for _, ord := range existingCorders { 21 | existingByBenchmark[ord.GetHashrate()] = ord 22 | } 23 | 24 | targetByBenchmark := map[uint64]*Corder{} 25 | for _, ord := range targetCorders { 26 | targetByBenchmark[ord.GetHashrate()] = ord 27 | } 28 | 29 | set := &OrdersSets{ 30 | Create: make([]*Corder, 0), 31 | Restore: make([]*Corder, 0), 32 | Cancel: make([]*Corder, 0), 33 | } 34 | 35 | for _, ord := range targetCorders { 36 | if ex, ok := existingByBenchmark[ord.GetHashrate()]; ok { 37 | if ex.Hash() == ord.Hash() { 38 | set.Restore = append(set.Restore, ex) 39 | } else { 40 | set.Cancel = append(set.Cancel, ex) 41 | set.Create = append(set.Create, ord) 42 | } 43 | } else { 44 | set.Create = append(set.Create, ord) 45 | } 46 | } 47 | 48 | for _, ord := range existingCorders { 49 | // order is exists on market but shouldn't be presented 50 | // in the target orders set. 51 | if _, ok := targetByBenchmark[ord.GetHashrate()]; !ok { 52 | set.Cancel = append(set.Cancel, ord) 53 | } 54 | } 55 | 56 | return set 57 | } 58 | -------------------------------------------------------------------------------- /blockchain/source/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends" : [ 3 | "standard", 4 | "plugin:promise/recommended" 5 | ], 6 | "plugins": [ 7 | "promise" 8 | ], 9 | "env": { 10 | "browser" : true, 11 | "node" : true, 12 | "mocha" : true, 13 | "jest" : true 14 | }, 15 | "globals" : { 16 | "artifacts": false, 17 | "contract": false, 18 | "assert": false, 19 | "web3": false 20 | }, 21 | "rules": { 22 | 23 | // Strict mode 24 | "strict": [2, "global"], 25 | 26 | // Code style 27 | "indent": ["error", 4], 28 | "quotes": [2, "single"], 29 | "semi": ["error", "always"], 30 | "space-before-function-paren": ["error", "always"], 31 | "no-use-before-define": 0, 32 | "eqeqeq": [2, "smart"], 33 | "dot-notation": [2, {"allowKeywords": true, "allowPattern": ""}], 34 | "no-redeclare": [2, {"builtinGlobals": true}], 35 | "no-trailing-spaces": [2, { "skipBlankLines": true }], 36 | "eol-last": 1, 37 | "comma-spacing": [2, {"before": false, "after": true}], 38 | "camelcase": [2, {"properties": "always"}], 39 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"], 40 | "comma-dangle": [1, "always-multiline"], 41 | "no-dupe-args": 2, 42 | "no-dupe-keys": 2, 43 | "no-debugger": 0, 44 | "no-undef": 2, 45 | "object-curly-spacing": [2, "always"], 46 | "max-len": [2, 120, 2], 47 | "generator-star-spacing": ["error", "before"], 48 | "promise/avoid-new": 0, 49 | "promise/always-return": 0 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /cmd/pandora/ammo_dwh.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/mitchellh/mapstructure" 7 | "github.com/sonm-io/core/proto" 8 | "go.uber.org/zap" 9 | ) 10 | 11 | type DWHOrdersAmmo struct { 12 | order *sonm.OrdersRequest 13 | } 14 | 15 | func (m *DWHOrdersAmmo) Type() AmmoType { 16 | return DWHOrders 17 | } 18 | 19 | func (m *DWHOrdersAmmo) Execute(ctx context.Context, ext interface{}) error { 20 | mExt := ext.(*dwhExt) 21 | orders, err := mExt.dwh.GetOrders(ctx, m.order) 22 | if err != nil { 23 | return err 24 | } 25 | 26 | mExt.log.Debug("OK", zap.String("ammo", "DWHOrders"), zap.Any("count", len(orders.Orders))) 27 | 28 | return nil 29 | } 30 | 31 | type dwhOrdersAmmoFactory struct { 32 | PoolAmmoFactory 33 | Orders []*sonm.OrdersRequest 34 | } 35 | 36 | func newDWHOrdersAmmoFactory(cfg interface{}) (AmmoFactory, error) { 37 | config := struct { 38 | Orders []*sonm.OrdersRequest 39 | }{} 40 | if err := mapstructure.Decode(cfg, &config); err != nil { 41 | return nil, err 42 | } 43 | 44 | m := &dwhOrdersAmmoFactory{ 45 | PoolAmmoFactory: newPoolAmmoFactory(func() interface{} { 46 | return &DWHOrdersAmmo{} 47 | }), 48 | Orders: config.Orders, 49 | } 50 | 51 | return m, nil 52 | } 53 | 54 | func (m *dwhOrdersAmmoFactory) New(id int) Ammo { 55 | ammo := m.pool.Get().(*DWHOrdersAmmo) 56 | ammo.order = m.Orders[id%len(m.Orders)] 57 | 58 | return ammo 59 | } 60 | 61 | func (m *dwhOrdersAmmoFactory) NewDefault() Ammo { 62 | return &DWHOrdersAmmo{} 63 | } 64 | -------------------------------------------------------------------------------- /connor/config_test.go: -------------------------------------------------------------------------------- 1 | package connor 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/sonm-io/core/proto" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestApplyEnvTemplate(t *testing.T) { 11 | m1 := map[string]string{ 12 | "a": "b", 13 | "c": "123", 14 | "param": "command", 15 | } 16 | 17 | dealID := sonm.NewBigIntFromInt(123) 18 | 19 | // no templates in map, should not be changed 20 | m1 = applyEnvTemplate(m1, dealID) 21 | assert.Len(t, m1, 3) 22 | assert.Equal(t, "b", m1["a"]) 23 | assert.Equal(t, "123", m1["c"]) 24 | assert.Equal(t, "command", m1["param"]) 25 | 26 | m2 := map[string]string{ 27 | "deal": "{DEAL_ID}", 28 | "worker": "sonm_{DEAL_ID}", 29 | "foo": "{DEAL_ID}_{DEAL_ID}_{DEAL_ID}{DEAL_ID}_c{DEAL_ID}", 30 | } 31 | 32 | // map's values have templates, should be changed 33 | m2 = applyEnvTemplate(m2, dealID) 34 | assert.Len(t, m2, 3) 35 | 36 | assert.Equal(t, "123", m2["deal"]) 37 | assert.Equal(t, "sonm_123", m2["worker"]) 38 | assert.Equal(t, "123_123_123123_c123", m2["foo"]) 39 | } 40 | 41 | func TestApplyEnvTemplate_Copy(t *testing.T) { 42 | root := map[string]string{ 43 | "deal_id": "{DEAL_ID}", 44 | } 45 | 46 | env1 := applyEnvTemplate(root, sonm.NewBigIntFromInt(111)) 47 | assert.Equal(t, "111", env1["deal_id"]) 48 | assert.Equal(t, "{DEAL_ID}", root["deal_id"]) 49 | 50 | env2 := applyEnvTemplate(root, sonm.NewBigIntFromInt(222)) 51 | assert.Equal(t, "222", env2["deal_id"]) 52 | assert.Equal(t, "{DEAL_ID}", root["deal_id"]) 53 | } 54 | -------------------------------------------------------------------------------- /blockchain/unit.go: -------------------------------------------------------------------------------- 1 | package blockchain 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "strings" 7 | ) 8 | 9 | type Unit struct { 10 | *big.Int 11 | } 12 | 13 | var ( 14 | Wei = Unit{Int: big.NewInt(1)} 15 | KWei = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(3), nil)} 16 | MWei = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(6), nil)} 17 | GWei = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)} 18 | Szabo = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(12), nil)} 19 | Finney = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(15), nil)} 20 | Ether = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)} 21 | KEther = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(21), nil)} 22 | MEther = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(24), nil)} 23 | GEther = Unit{Int: new(big.Int).Exp(big.NewInt(10), big.NewInt(27), nil)} 24 | ) 25 | 26 | func UnitFromString(v string) (Unit, error) { 27 | switch strings.ToLower(v) { 28 | case "wei": 29 | return Wei, nil 30 | case "kwei": 31 | return KWei, nil 32 | case "mwei": 33 | return MWei, nil 34 | case "gwei": 35 | return GWei, nil 36 | case "szabo": 37 | return Szabo, nil 38 | case "finney": 39 | return Finney, nil 40 | case "ether": 41 | return Ether, nil 42 | case "kether": 43 | return KEther, nil 44 | case "mether": 45 | return MEther, nil 46 | case "gether": 47 | return GEther, nil 48 | default: 49 | return Unit{}, fmt.Errorf("unknown ETH unit: %s", v) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /cmd/cli/commands/worker_benchmarks.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/sonm-io/core/proto" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func init() { 12 | benchmarkRootCmd.AddCommand( 13 | workerRemoveBenchmarksCmd, 14 | workerPurgeBenchmarksCmd, 15 | ) 16 | } 17 | 18 | var benchmarkRootCmd = &cobra.Command{ 19 | Use: "benchmark", 20 | Short: "Operations with worker benchmarks", 21 | } 22 | 23 | var workerPurgeBenchmarksCmd = &cobra.Command{ 24 | Use: "purge", 25 | Short: "Remove all benchmarks from cache to rebenchmark on next worker restart", 26 | RunE: func(cmd *cobra.Command, args []string) error { 27 | _, err := worker.PurgeBenchmarks(workerCtx, &sonm.Empty{}) 28 | if err != nil { 29 | return fmt.Errorf("failed to purge benchmark cache: %v", err) 30 | } 31 | 32 | showOk(cmd) 33 | return nil 34 | }, 35 | } 36 | 37 | var workerRemoveBenchmarksCmd = &cobra.Command{ 38 | Use: "remove ", 39 | Short: "Remove specified benchmark from cache to rebenchmark on next worker restart", 40 | Args: cobra.MinimumNArgs(1), 41 | RunE: func(cmd *cobra.Command, args []string) error { 42 | id, err := strconv.ParseUint(args[0], 0, 64) 43 | if err != nil { 44 | return fmt.Errorf("failed to parse benchmark id: %v", err) 45 | } 46 | 47 | if _, err := worker.RemoveBenchmark(workerCtx, &sonm.NumericID{Id: id}); err != nil { 48 | return fmt.Errorf("failed to get debug state: %v", err) 49 | } 50 | 51 | showOk(cmd) 52 | return nil 53 | }, 54 | } 55 | -------------------------------------------------------------------------------- /blockchain/source/migrations/3_deploy_devices_storage.js: -------------------------------------------------------------------------------- 1 | const DevicesStorage = artifacts.require('./DevicesStorage.sol'); 2 | const AddressHashMap = artifacts.require('./AddressHashMap.sol'); 3 | const Multisig = artifacts.require('./MultiSigWallet.sol'); 4 | const TruffleConfig = require('../truffle'); 5 | const ContractRegistry = require('../migration_utils/address_hashmap'); 6 | 7 | async function deploySidechain (deployer, network, accounts) { 8 | let registry = new ContractRegistry(AddressHashMap, network, Multisig); 9 | console.log('registry created'); 10 | await registry.init(); 11 | console.log('registry initialized'); 12 | await deployer.deploy(DevicesStorage); 13 | console.log('devices storage deployed'); 14 | let ds = await DevicesStorage.deployed(); 15 | console.log('deployed object fetched'); 16 | await registry.write('devicesStorageAddress', ds.address); 17 | console.log('written to registry'); 18 | let ms = await registry.resolve(Multisig, 'migrationMultSigAddress'); 19 | console.log('ms resolved'); 20 | await ds.transferOwnership(ms.address); 21 | console.log('ownership transferred'); 22 | 23 | await registry.write('migrationMultiSigAddress', ms.address); 24 | } 25 | 26 | module.exports = function (deployer, network, accounts) { 27 | deployer.then(async () => { // eslint-disable-line promise/catch-or-return 28 | if (TruffleConfig.isSidechain(network)) { 29 | await deploySidechain(deployer, network, accounts); 30 | } 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /blockchain/source/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sonm-contracts", 3 | "version": "0.1.1", 4 | "description": "", 5 | "main": "", 6 | "directories": {}, 7 | "scripts": { 8 | "postinstall": "patch-package" 9 | }, 10 | "author": "SONM team", 11 | "license": "MIT", 12 | "dependencies": { 13 | "babel-polyfill": "^6.23.0", 14 | "babel-preset-es2015": "^6.18.0", 15 | "babel-preset-stage-2": "^6.18.0", 16 | "babel-preset-stage-3": "^6.17.0", 17 | "babel-register": "^6.23.0", 18 | "chai": "^4.0.2", 19 | "chai-as-promised": "^7.0.0", 20 | "chai-bignumber": "^2.0.0", 21 | "commander": "^2.15.1", 22 | "coveralls": "^3.0.0", 23 | "dotenv": "^5.0.1", 24 | "eslint": "^4.11.0", 25 | "eslint-config-standard": "^10.2.1", 26 | "eslint-plugin-import": "^2.8.0", 27 | "eslint-plugin-node": "^5.2.1", 28 | "eslint-plugin-promise": "^3.6.0", 29 | "eslint-plugin-standard": "^3.0.1", 30 | "ethereumjs-testrpc-sc": "^6.1.2", 31 | "ethereumjs-util": "^5.2.0", 32 | "ganache-cli": "^6.2.5", 33 | "left-pad": "^1.3.0", 34 | "merkle-tree-solidity": "^1.0.8", 35 | "mocha-junit-reporter": "^1.17.0", 36 | "patch-package": "^5.1.1", 37 | "solidity-coverage": "^0.5.1", 38 | "solidity-sha3": "^0.4.1", 39 | "solium": "^1.1.7", 40 | "truffle": "^4.1.8", 41 | "truffle-contract": "^3.0.5", 42 | "truffle-flattener": "^1.2.5", 43 | "truffle-privatekey-provider": "0.0.6", 44 | "web3": "^0.20.6", 45 | "zeppelin-solidity": "^1.9.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cmd/node/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/noxiouz/zapctx/ctxlog" 8 | "github.com/sonm-io/core/cmd" 9 | "github.com/sonm-io/core/insonmnia/logging" 10 | "github.com/sonm-io/core/insonmnia/node" 11 | "github.com/sonm-io/core/insonmnia/version" 12 | "github.com/sonm-io/core/util/metrics" 13 | "golang.org/x/sync/errgroup" 14 | ) 15 | 16 | func main() { 17 | cmd.NewCmd(run).Execute() 18 | } 19 | 20 | func run(app cmd.AppContext) error { 21 | cfg, err := node.NewConfig(app.ConfigPath) 22 | if err != nil { 23 | return fmt.Errorf("failed to load config file: %s", err) 24 | } 25 | 26 | log, err := logging.BuildLogger(cfg.Log) 27 | if err != nil { 28 | return fmt.Errorf("failed to build logger instance: %s", err) 29 | } 30 | 31 | ctx := ctxlog.WithLogger(context.Background(), log) 32 | version.ValidateVersion(ctx, version.NewLogObserver(log.Sugar())) 33 | 34 | wg, ctx := errgroup.WithContext(ctx) 35 | wg.Go(func() error { 36 | return cmd.WaitInterrupted(ctx) 37 | }) 38 | wg.Go(func() error { 39 | server, err := node.New(ctx, cfg, node.WithLog(log)) 40 | if err != nil { 41 | return fmt.Errorf("failed to build Node instance: %s", err) 42 | } 43 | 44 | return server.Serve(ctx) 45 | }) 46 | wg.Go(func() error { 47 | return metrics.NewPrometheusExporter(cfg.MetricsListenAddr, metrics.WithLogging(log.Sugar())).Serve(ctx) 48 | }) 49 | 50 | if err := wg.Wait(); err != nil { 51 | return fmt.Errorf("node termination: %s", err) 52 | } 53 | 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /etc/qos.yaml: -------------------------------------------------------------------------------- 1 | endpoint: "unix:///var/run/qos.sock" 2 | 3 | # Settings for Ethereum keys 4 | ethereum: ðereum 5 | # path to keystore 6 | key_store: "./keys" 7 | # passphrase for keystore 8 | pass_phrase: "any" 9 | 10 | # NAT punching settings. 11 | npp: &npp 12 | # Rendezvous settings. 13 | rendezvous: 14 | # Known rendezvous endpoints. 15 | # 16 | # Must be in ETHAddress@Host:Port format. 17 | endpoints: 18 | - 0x5b7d6516fad04e10db726933bcd75447fd7b4b17@rendezvous.livenet.sonm.com:14099 19 | # Relay settings. 20 | relay: 21 | # Known relay endpoints. 22 | # 23 | # The format is Host:Port. 24 | # Can be omitted, meaning that relaying is disabled. 25 | endpoints: 26 | - relay.livenet.sonm.com:12240 27 | 28 | # GPU vendor to provide a remote plugin. 29 | # Maybe "nvidia", "radeon" or "fake". 30 | # any other options will be treated as invalid 31 | # what will provide nilTuner without GPU support. 32 | gpu_vendor: "" 33 | 34 | logging: 35 | level: debug 36 | 37 | sysinit: 38 | device: /dev/loop 39 | cipher: somecipher 40 | fs_type: ext4 41 | mount_point: /var/lib/docker 42 | 43 | # Secure Shell settings. 44 | secsh: 45 | # Path to the secexec binary. 46 | secexec: /home/esafronov/code/core/target/release/secexec 47 | # Path to seccomp policy files. 48 | seccomp_policy_dir: /home/esafronov/code/core/etc/secexec 49 | # Allowed ETH keys for login. 50 | allowed_keys: [] 51 | # ETH account settings. 52 | ethereum: *ethereum 53 | # NAT punching settings. 54 | npp: *npp 55 | -------------------------------------------------------------------------------- /insonmnia/worker/volume/options.go: -------------------------------------------------------------------------------- 1 | package volume 2 | 3 | import ( 4 | "fmt" 5 | 6 | "go.uber.org/zap" 7 | ) 8 | 9 | // Option specifies how a Docker plugin can be configured. 10 | type Option func(options interface{}) error 11 | 12 | // Options describes generic volume plugin options. 13 | type options struct { 14 | socketDir string 15 | log *zap.SugaredLogger 16 | } 17 | 18 | func newOptions() *options { 19 | return &options{ 20 | socketDir: defaultPluginSockDir, 21 | log: zap.NewNop().Sugar(), 22 | } 23 | } 24 | 25 | // WithPluginSocketDir constructs an option that specifies the plugin 26 | // directory where Unix sockets live. 27 | func WithPluginSocketDir(path string) Option { 28 | return func(o interface{}) error { 29 | option, ok := o.(*options) 30 | if !ok { 31 | return fmt.Errorf("invalid option type: %T", o) 32 | } 33 | 34 | option.socketDir = path 35 | return nil 36 | } 37 | } 38 | 39 | func WithLogger(log *zap.SugaredLogger) Option { 40 | return func(o interface{}) error { 41 | option, ok := o.(*options) 42 | if !ok { 43 | return fmt.Errorf("invalid option type: %T", o) 44 | } 45 | 46 | option.log = log 47 | return nil 48 | } 49 | } 50 | 51 | // WithOptions constructs an option that forwards the given generic options 52 | // to the plugin. 53 | func WithOptions(opts map[string]string) Option { 54 | return func(o interface{}) error { 55 | switch o.(type) { 56 | case *options: 57 | return nil 58 | default: 59 | return fmt.Errorf("invalid option type: %T", o) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /insonmnia/npp/rendezvous/client.go: -------------------------------------------------------------------------------- 1 | // This package contains a tiny wrapper over the generated gRPC rendezvous 2 | // client that allows to close the client explicitly. 3 | 4 | package rendezvous 5 | 6 | import ( 7 | "context" 8 | 9 | "github.com/sonm-io/core/proto" 10 | "github.com/sonm-io/core/util/xgrpc" 11 | "google.golang.org/grpc" 12 | "google.golang.org/grpc/credentials" 13 | ) 14 | 15 | // Client extends the generated gRPC client allowing to close the underlying 16 | // connection. 17 | // Users should call Client.Close to terminate all the pending operations. 18 | type Client interface { 19 | sonm.RendezvousClient 20 | // Close closes this client freeing the associated resources. 21 | // 22 | // All pending operations will be terminated with error. 23 | Close() error 24 | } 25 | 26 | type client struct { 27 | sonm.RendezvousClient 28 | conn *grpc.ClientConn 29 | } 30 | 31 | // NewRendezvousClient constructs a new rendezvous client. 32 | // 33 | // The address provided will be used for establishing a TCP connection while 34 | // optional credentials - for authentication. Additionally other dial options 35 | // can be specified. 36 | func NewRendezvousClient(ctx context.Context, addr string, credentials credentials.TransportCredentials, opts ...grpc.DialOption) (Client, error) { 37 | conn, err := xgrpc.NewClient(ctx, addr, credentials, opts...) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | return &client{sonm.NewRendezvousClient(conn), conn}, nil 43 | } 44 | 45 | func (m *client) Close() error { 46 | return m.conn.Close() 47 | } 48 | -------------------------------------------------------------------------------- /connor/types/benchmarks.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "github.com/sonm-io/core/proto" 4 | 5 | type Benchmarks sonm.Benchmarks 6 | 7 | func newZeroBenchmarks() Benchmarks { 8 | return Benchmarks{Values: make([]uint64, sonm.MinNumBenchmarks)} 9 | } 10 | 11 | func (b *Benchmarks) setGPUEth(v uint64) { 12 | b.Values[9] = v 13 | } 14 | 15 | func (b *Benchmarks) setGPUZcash(v uint64) { 16 | b.Values[10] = v 17 | } 18 | 19 | func (b *Benchmarks) setGPURedshift(v uint64) { 20 | b.Values[11] = v 21 | } 22 | 23 | func (b *Benchmarks) unwrap() *sonm.Benchmarks { 24 | v := sonm.Benchmarks(*b) 25 | return &v 26 | } 27 | 28 | func (b *Benchmarks) toMap() map[string]uint64 { 29 | // warn: this is shitty crutch, but we should refactor 30 | // CreateOrder method to omit this. 31 | 32 | v := b.unwrap() 33 | return map[string]uint64{ 34 | "cpu-sysbench-multi": v.CPUSysbenchMulti(), 35 | "cpu-sysbench-single": v.CPUSysbenchOne(), 36 | "cpu-cores": v.CPUCores(), 37 | "ram-size": v.RAMSize(), 38 | "storage-size": v.StorageSize(), 39 | "net-download": v.NetTrafficIn(), 40 | "net-upload": v.NetTrafficOut(), 41 | "gpu-count": v.GPUCount(), 42 | "gpu-mem": v.GPUMem(), 43 | "gpu-eth-hashrate": v.GPUEthHashrate(), 44 | "gpu-cash-hashrate": v.GPUCashHashrate(), 45 | "gpu-redshift": v.GPURedshift(), 46 | "cpu-cryptonight": v.CPUCryptonight(), 47 | } 48 | } 49 | 50 | func benchmarksToMap(b *sonm.Benchmarks) map[string]uint64 { 51 | v := Benchmarks(*b) 52 | return v.toMap() 53 | } 54 | -------------------------------------------------------------------------------- /optimus/model_lls.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | 8 | "github.com/cdipaolo/goml/base" 9 | "github.com/cdipaolo/goml/linear" 10 | "go.uber.org/zap" 11 | ) 12 | 13 | type llsModelConfig struct { 14 | Alpha float64 `yaml:"alpha" default:"1e-3"` 15 | Regularization float64 `yaml:"regularization" default:"6.0"` 16 | MaxIterations int `yaml:"max_iterations" default:"1000"` 17 | } 18 | 19 | func (m *llsModelConfig) Config() interface{} { 20 | return m 21 | } 22 | 23 | func (m *llsModelConfig) Create(log *zap.SugaredLogger) Model { 24 | return &llsModel{ 25 | cfg: *m, 26 | output: ioutil.Discard, 27 | } 28 | } 29 | 30 | type llsModel struct { 31 | cfg llsModelConfig 32 | output io.Writer 33 | } 34 | 35 | func (m *llsModel) Train(trainingSet [][]float64, expectation []float64) (TrainedModel, error) { 36 | model := linear.NewLeastSquares(base.BatchGA, m.cfg.Alpha, m.cfg.Regularization, m.cfg.MaxIterations, trainingSet, expectation) 37 | //model.Output = m.output 38 | if err := model.Learn(); err != nil { 39 | return nil, err 40 | } 41 | 42 | return &trainedLLSModel{ 43 | model: model, 44 | }, nil 45 | } 46 | 47 | type trainedLLSModel struct { 48 | model *linear.LeastSquares 49 | } 50 | 51 | func (m *trainedLLSModel) Predict(vec []float64) (float64, error) { 52 | prediction, err := m.model.Predict(vec) 53 | if err != nil { 54 | return 0.0, err 55 | } 56 | 57 | if len(prediction) == 0 { 58 | return 0.0, fmt.Errorf("no prediction made") 59 | } 60 | 61 | return prediction[0], nil 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | SONM preview 3 |

SONM Core

4 |

Official core client

5 |

6 | 7 | --- 8 | 9 | [![Build Status](https://travis-ci.org/sonm-io/core.svg?branch=master)](https://travis-ci.org/sonm-io/core) 10 | [![Build status](https://ci.appveyor.com/api/projects/status/01d7cpccwi8scwqp/branch/master?svg=true)](https://ci.appveyor.com/project/Sokel/core/branch/master) 11 | [![codecov](https://codecov.io/gh/sonm-io/core/branch/master/graph/badge.svg)](https://codecov.io/gh/sonm-io/core) 12 | [![docs](https://svg-badge.appspot.com/badge/docs/ready?color=1578b6)](https://docs.sonm.io/getting-started) 13 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sonm-io_core/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link) 14 | [![Go Report Card](https://goreportcard.com/badge/github.com/sonm-io/core)](https://goreportcard.com/report/github.com/sonm-io/core) 15 | 16 | 17 | ### Documentation 18 | 19 | Full documentation and frequently asked questions are available [here](https://docs.sonm.io/). 20 | 21 | 22 | ### Install 23 | 24 | You can download binaries from the [releases page](https://github.com/sonm-io/core/releases/latest). 25 | 26 | Packages for Debian and Ubuntu are available at [packagecloud](https://packagecloud.io/SONM/core). 27 | 28 | ### Build 29 | 30 | If you want to build all components by yourself: 31 | 32 | ``` 33 | git clone https://github.com/sonm-io/core.git 34 | make build 35 | ``` 36 | -------------------------------------------------------------------------------- /util/config/retag_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestConvertToSnakeCase(t *testing.T) { 10 | batch := map[string]string{ 11 | "": "", 12 | "t": "t", 13 | "test": "test", 14 | "testC": "test_c", 15 | "testCase": "test_case", 16 | "TestCase": "test_case", 17 | "Test Case": "test_case", 18 | " TestCase\t": "test_case", 19 | " Test Case": "test_case", 20 | "Test Case ": "test_case", 21 | " Test Case ": "test_case", 22 | "test_case": "test_case", 23 | "Test": "test", 24 | "HTTPStatusCode": "http_status_code", 25 | "ParseURL.DoParse": "parse_url.do_parse", 26 | "Convert Space": "convert_space", 27 | "Convert-dash": "convert_dash", 28 | "Skip___MultipleUnderscores": "skip_multiple_underscores", 29 | "Skip MultipleSpaces": "skip_multiple_spaces", 30 | "Skip---MultipleDashes": "skip_multiple_dashes", 31 | "ManyManyWords": "many_many_words", 32 | "manyManyWords": "many_many_words", 33 | "AnyKind of_string": "any_kind_of_string", 34 | "JSONData": "json_data", 35 | "userID": "user_id", 36 | } 37 | 38 | for s, expected := range batch { 39 | assert.Equal(t, expected, toSnakeCase(s)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cmd/optimus/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/noxiouz/zapctx/ctxlog" 8 | "github.com/sonm-io/core/cmd" 9 | "github.com/sonm-io/core/insonmnia/version" 10 | "github.com/sonm-io/core/optimus" 11 | "go.uber.org/zap" 12 | "go.uber.org/zap/zapcore" 13 | ) 14 | 15 | func main() { 16 | cmd.NewCmd(run).Execute() 17 | } 18 | 19 | func run(app cmd.AppContext) error { 20 | cfg, err := optimus.LoadConfig(app.ConfigPath) 21 | if err != nil { 22 | return fmt.Errorf("failed to parse config: %v", err) 23 | } 24 | 25 | if cfg.Restrictions != nil { 26 | control, err := optimus.RestrictUsage(cfg.Restrictions) 27 | if err != nil { 28 | return err 29 | } 30 | defer control.Delete() 31 | } 32 | 33 | zapConfig := zap.Config{ 34 | Level: zap.NewAtomicLevelAt(cfg.Logging.LogLevel().Zap()), 35 | Development: false, 36 | Encoding: "console", 37 | EncoderConfig: zap.NewDevelopmentEncoderConfig(), 38 | OutputPaths: []string{"stdout"}, 39 | ErrorOutputPaths: []string{"stderr"}, 40 | } 41 | zapConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder 42 | 43 | log, err := zapConfig.Build() 44 | if err != nil { 45 | return err 46 | } 47 | 48 | ctx := ctxlog.WithLogger(context.Background(), log) 49 | version.ValidateVersion(ctx, version.NewLogObserver(log.Sugar())) 50 | bot, err := optimus.NewOptimus(cfg, optimus.WithVersion(app.Version), optimus.WithLog(log.Sugar())) 51 | if err != nil { 52 | return fmt.Errorf("failed to create Optimus: %v", err) 53 | } 54 | 55 | return bot.Run(ctx) 56 | } 57 | -------------------------------------------------------------------------------- /insonmnia/structs/image.go: -------------------------------------------------------------------------------- 1 | package structs 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/sonm-io/core/proto" 7 | "google.golang.org/grpc/codes" 8 | "google.golang.org/grpc/metadata" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | type ImagePush struct { 13 | sonm.Worker_PushTaskServer 14 | 15 | dealId string 16 | imageSize int64 17 | } 18 | 19 | func requireHeader(md metadata.MD, name string) (string, error) { 20 | value, ok := md[name] 21 | if !ok { 22 | return "", status.Errorf(codes.InvalidArgument, "`%s` required", name) 23 | } 24 | 25 | return value[len(value)-1], nil 26 | } 27 | 28 | func RequireHeaderInt64(md metadata.MD, name string) (int64, error) { 29 | value, err := requireHeader(md, name) 30 | if err != nil { 31 | return 0, err 32 | } 33 | 34 | valueInt64, err := strconv.ParseInt(value, 10, 64) 35 | if err != nil { 36 | return 0, err 37 | } 38 | 39 | return valueInt64, nil 40 | } 41 | 42 | func NewImagePush(stream sonm.Worker_PushTaskServer) (*ImagePush, error) { 43 | md, ok := metadata.FromIncomingContext(stream.Context()) 44 | if !ok { 45 | return nil, status.Errorf(codes.InvalidArgument, "metadata required") 46 | } 47 | 48 | dealId, err := requireHeader(md, "deal") 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | imageSize, err := RequireHeaderInt64(md, "size") 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | return &ImagePush{stream, dealId, imageSize}, nil 59 | } 60 | 61 | func (p *ImagePush) DealId() string { 62 | return p.dealId 63 | } 64 | 65 | func (p *ImagePush) ImageSize() int64 { 66 | return p.imageSize 67 | } 68 | -------------------------------------------------------------------------------- /insonmnia/worker/gpu/fake_tuner.go: -------------------------------------------------------------------------------- 1 | package gpu 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/docker/docker/api/types/container" 8 | "github.com/noxiouz/zapctx/ctxlog" 9 | "github.com/sonm-io/core/proto" 10 | "go.uber.org/zap" 11 | ) 12 | 13 | type fakeGPUTuner struct { 14 | log *zap.Logger 15 | devices []*sonm.GPUDevice 16 | } 17 | 18 | func newFakeTuner(ctx context.Context, opts ...Option) (Tuner, error) { 19 | options := fakeDefaultOptions() 20 | for _, f := range opts { 21 | f(options) 22 | } 23 | 24 | var devices []*sonm.GPUDevice 25 | for i := 0; i < options.DeviceCount; i++ { 26 | dev := &sonm.GPUDevice{ 27 | ID: fmt.Sprintf("PCI:%04d", i), 28 | VendorID: uint64(sonm.GPUVendorType_FAKE), 29 | VendorName: "FAKE", 30 | DeviceID: uint64(i), 31 | DeviceName: fmt.Sprintf("Fake GPU slot%d", i), 32 | MajorNumber: uint64(100 + i), 33 | MinorNumber: uint64(200 + i), 34 | Memory: 4294967296, 35 | } 36 | 37 | dev.FillHashID() 38 | devices = append(devices, dev) 39 | } 40 | 41 | return &fakeGPUTuner{ 42 | log: ctxlog.GetLogger(ctx), 43 | devices: devices, 44 | }, nil 45 | } 46 | 47 | func (f *fakeGPUTuner) Tune(hostconfig *container.HostConfig, ids []GPUID) error { 48 | f.log.Debug("tuning container with fake GPU driver", zap.Any("device_ids", ids)) 49 | return nil 50 | } 51 | 52 | func (f *fakeGPUTuner) Devices() []*sonm.GPUDevice { 53 | f.log.Debug("requesting devices from fake GPU driver") 54 | return f.devices 55 | } 56 | 57 | func (f *fakeGPUTuner) Close() error { 58 | f.log.Debug("closing fake GPU driver") 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /optimus/model.go: -------------------------------------------------------------------------------- 1 | package optimus 2 | 3 | import ( 4 | "fmt" 5 | 6 | "go.uber.org/zap" 7 | ) 8 | 9 | type RegressionModelFactory interface { 10 | Config() interface{} 11 | Create(log *zap.SugaredLogger) Model 12 | } 13 | 14 | // Model represents a ML model that can be trained using provided training set 15 | // with some expectation. 16 | type Model interface { 17 | // Train runs the training process, returning the trained model on success. 18 | // The "trainingSet" argument is a MxN matrix, while "expectation" must be 19 | // a M-length vector. 20 | Train(trainingSet [][]float64, expectation []float64) (TrainedModel, error) 21 | } 22 | 23 | type TrainedModel interface { 24 | Predict(vec []float64) (float64, error) 25 | } 26 | 27 | type regressionModelFactory struct { 28 | RegressionModelFactory 29 | } 30 | 31 | func (m *regressionModelFactory) MarshalYAML() (interface{}, error) { 32 | return m.Config(), nil 33 | } 34 | 35 | func (m *regressionModelFactory) UnmarshalYAML(unmarshal func(interface{}) error) error { 36 | ty, err := typeofInterface(unmarshal) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | factory := regressionFactory(ty) 42 | if factory == nil { 43 | return fmt.Errorf("unknown regression model: %s", ty) 44 | } 45 | 46 | if err := unmarshal(factory.Config()); err != nil { 47 | return err 48 | } 49 | 50 | m.RegressionModelFactory = factory 51 | 52 | return nil 53 | } 54 | 55 | func regressionFactory(ty string) RegressionModelFactory { 56 | switch ty { 57 | case "lls": 58 | return &llsModelConfig{} 59 | case "nnls": 60 | return &SCAKKTModel{} 61 | default: 62 | return nil 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /proto/worker.go: -------------------------------------------------------------------------------- 1 | package sonm 2 | 3 | import ( 4 | "unicode/utf8" 5 | ) 6 | 7 | const ( 8 | MetricsKeyDiskFree = "disk_free" 9 | MetricsKeyDiskFreePercent = "disk_free_percent" 10 | MetricsKeyDiskTotal = "disk_total" 11 | MetricsKeyRAMFree = "ram_free" 12 | MetricsKeyRAMFreePercent = "ram_free_percent" 13 | MetricsKeyRAMTotal = "ram_total" 14 | MetricsKeyCPUUtilization = "cpu_utilization" 15 | MetricsKeyGPUPrefix = "gpu" 16 | MetricsKeyGPUTemperature = "temp" 17 | MetricsKeyGPUFan = "fan" 18 | MetricsKeyGPUPower = "power" 19 | ) 20 | 21 | func (m *TaskTag) MarshalYAML() (interface{}, error) { 22 | if m.GetData() == nil { 23 | return nil, nil 24 | } 25 | if utf8.Valid(m.GetData()) { 26 | return string(m.GetData()), nil 27 | } 28 | return m.GetData(), nil 29 | } 30 | 31 | func (m *TaskTag) UnmarshalYAML(unmarshal func(interface{}) error) error { 32 | if err := unmarshal(&m.Data); err == nil { 33 | return nil 34 | } 35 | var str string 36 | if err := unmarshal(&str); err != nil { 37 | return err 38 | } 39 | m.Data = []byte(str) 40 | return nil 41 | } 42 | 43 | func (m *WorkerMetricsResponse) Append(x ...map[string]float64) *WorkerMetricsResponse { 44 | if m.Metrics == nil { 45 | m.Metrics = make(map[string]float64) 46 | } 47 | 48 | for _, item := range x { 49 | for k, v := range item { 50 | m.Metrics[k] = v 51 | } 52 | } 53 | 54 | return m 55 | } 56 | 57 | func IsTaskStatusTerminated(status TaskStatusReply_Status) bool { 58 | return status == TaskStatusReply_FINISHED || status == TaskStatusReply_BROKEN || status == TaskStatusReply_KILLED_OOM 59 | } 60 | -------------------------------------------------------------------------------- /util/xdocker/xdocker.go: -------------------------------------------------------------------------------- 1 | package xdocker 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "encoding/json" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | type spoolResponseProtocol struct { 12 | Error string `json:"error"` 13 | Status string `json:"status"` 14 | } 15 | 16 | // DecodeImagePull detects Error of an image pulling process 17 | // by decoding reply from Docker 18 | // Although Docker should reply with JSON Encoded items 19 | // one per line, in different versions it could vary. 20 | // This decoders can detect error even in mixed replies: 21 | // {"Status": "OK"}\n{"Status": "OK"} 22 | // {"Status": "OK"}{"Error": "error"} 23 | func DecodeImagePull(r io.Reader) error { 24 | more := true 25 | 26 | rd := bufio.NewReader(r) 27 | for more { 28 | line, err := rd.ReadBytes('\n') 29 | switch err { 30 | case nil: 31 | // pass 32 | case io.EOF: 33 | if len(line) == 0 { 34 | return nil 35 | } 36 | more = false 37 | default: 38 | return err 39 | } 40 | 41 | if len(line) == 0 { 42 | return fmt.Errorf("empty response line") 43 | } 44 | 45 | if line[len(line)-1] == '\n' { 46 | line = line[:len(line)-1] 47 | } 48 | 49 | if err = decodePullLine(line); err != nil { 50 | return err 51 | } 52 | } 53 | return nil 54 | } 55 | 56 | func decodePullLine(line []byte) error { 57 | var resp spoolResponseProtocol 58 | decoder := json.NewDecoder(bytes.NewReader(line)) 59 | for { 60 | if err := decoder.Decode(&resp); err != nil { 61 | if err == io.EOF { 62 | return nil 63 | } 64 | 65 | return err 66 | } 67 | 68 | if len(resp.Error) != 0 { 69 | return fmt.Errorf(resp.Error) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /blockchain/source/migration_utils/address_hashmap.js: -------------------------------------------------------------------------------- 1 | const TruffleConfig = require('../truffle'); 2 | const Multisig = require('./multisig'); 3 | 4 | class ContractRegistry { 5 | constructor (ahm, network, multisigContract) { 6 | this.ahmContract = ahm; 7 | this.network = network; 8 | this.multisigContract = multisigContract; 9 | } 10 | async init () { 11 | if (TruffleConfig.isSidechain(this.network)) { 12 | this.hm = await this.ahmContract.deployed(); 13 | this.multisig = await Multisig.new(this.multisigContract, this, this.network, this.hm); 14 | } else { 15 | let alt = this.ahmContract.clone(); 16 | let sideNet = TruffleConfig.networks[this.network].side_network_id; 17 | alt.setNetwork(sideNet); 18 | alt.setProvider(TruffleConfig.networks[TruffleConfig.oppositeNetName(this.network)].provider()); 19 | this.hm = await alt.deployed(); 20 | let sideNetName = TruffleConfig.oppositeNetName(this.network); 21 | this.multisig = await Multisig.new(this.multisigContract, this, sideNetName, this.hm); 22 | } 23 | } 24 | 25 | async resolve (contract, name) { 26 | let address = await this.hm.read(name); 27 | console.log('resolved', name, 'to', address); 28 | return contract.at(address); 29 | } 30 | 31 | async write (name, value) { 32 | if (this.multisig !== undefined) { 33 | return this.multisig.call('write', name, value); 34 | } 35 | return this.hm.write(name, value); 36 | } 37 | } 38 | 39 | module.exports = ContractRegistry; 40 | --------------------------------------------------------------------------------