HP smart contract nodejs library. (#101)

This commit is contained in:
Ravin Perera
2020-07-20 13:38:08 +05:30
committed by GitHub
parent 09e72ef8bb
commit 311d20aba6
33 changed files with 154 additions and 528 deletions

View File

@@ -1,17 +0,0 @@
FROM hpcore:latest as hpcore-nodejs
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y curl
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install -y nodejs
FROM hpcore-nodejs
RUN /hp/hpcore new /echo_contract
COPY ./examples/echo_contract/contract.js /echo_contract/bin/contract.js
RUN mv /echo_contract/cfg/hp.cfg /echo_contract/cfg/hp.json
RUN node -p "JSON.stringify({...require('/echo_contract/cfg/hp.json'), binary:'/usr/bin/node', binargs:'./bin/contract.js' }, null, 2)" > /echo_contract/cfg/hp.cfg
RUN rm /echo_contract/cfg/hp.json
ENTRYPOINT ["/hp/hpcore", "run", "/echo_contract"]

View File

@@ -1,48 +0,0 @@
process.on('uncaughtException', (err) => {
console.error('There was an uncaught error', err)
})
const fs = require('fs')
//console.log("===Sample contract started===");
const hpargs = JSON.parse(fs.readFileSync(0, 'utf8'));
//console.log(hpargs);
// We just save execution args as an example state file change.
if (!hpargs.readonly)
fs.appendFileSync("exects.txt", "ts:" + hpargs.ts + "\n");
Object.keys(hpargs.usrfd).forEach(function (key) {
const userfds = hpargs.usrfd[key];
if (userfds[0] != -1) {
const userinput = fs.readFileSync(userfds[0], 'utf8');
// Append user input to a state file if not in read only mode.
if (!hpargs.readonly)
fs.appendFileSync("userinputs.txt", userinput + "\n");
if (userinput == "ts")
fs.writeSync(userfds[1], fs.readFileSync("exects.txt"));
else
fs.writeSync(userfds[1], "Echoing: " + userinput);
}
});
if (!hpargs.readonly) {
if (hpargs.nplfd[0] != -1) {
const nplinput = fs.readFileSync(hpargs.nplfd[0], 'utf8');
console.log("Input received from peers:");
console.log(nplinput);
fs.writeSync(hpargs.nplfd[1], "Echoing: " + nplinput);
}
if (hpargs.hpfd[0] != -1) {
const hpinput = fs.readFileSync(hpargs.hpfd[0], 'utf8');
console.log("Input received from hp:");
console.log(hpinput);
fs.writeSync(hpargs.hpfd[1], "Echoing: " + hpinput);
}
}
//console.log("===Sample contract ended===");

View File

@@ -1 +0,0 @@
node_modules

View File

@@ -0,0 +1,30 @@
const { HotPocketContract } = require("./hp-contract-lib");
const fs = require('fs');
const hpc = new HotPocketContract();
//console.log("===Echo contract started===");
// We just save execution timestamp as an example state file change.
if (!hpc.readonly)
fs.appendFileSync("exects.txt", "ts:" + hpc.timestamp + "\n");
Object.keys(hpc.users).forEach(function (key) {
const user = hpc.users[key];
const inputBuf = user.readInput();
if (inputBuf) {
const userInput = inputBuf.toString("utf8");
// Append user input to a state file if not in read only mode.
if (!hpc.readonly)
fs.appendFileSync("userinputs.txt", userInput + "\n");
if (userInput == "ts")
user.sendOutput(fs.readFileSync("exects.txt"));
else
user.sendOutput("Echoing: " + userInput);
}
});
//console.log("===Echo contract ended===");

View File

@@ -0,0 +1,27 @@
const fs = require('fs');
function HotPocketContract() {
const hpargs = JSON.parse(fs.readFileSync(0, 'utf8'));
this.readonly = hpargs.readonly;
this.timestamp = hpargs.ts;
this.users = {};
Object.keys(hpargs.usrfd).forEach((userPubKey) => {
const userfds = hpargs.usrfd[userPubKey];
this.users[userPubKey] = new HotPocketChannel(userfds[0], userfds[1]);
});
}
function HotPocketChannel(infd, outfd) {
this.readInput = function () {
return infd == -1 ? null : fs.readFileSync(infd);
}
this.sendOutput = function (output) {
fs.writeFileSync(outfd, output);
}
}
module.exports = {
HotPocketContract
}

View File

@@ -1,2 +0,0 @@
bin
obj

View File

@@ -1,19 +0,0 @@
using Microsoft.EntityFrameworkCore;
namespace ToDoContract
{
public class DataContext : DbContext
{
public DbSet<ToDoEntry> ToDoEntries { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=state/todo.db");
}
public class ToDoEntry
{
public int Id { get; set; }
public string Content { get; set; }
public string CreatedBy { get; set; }
}
}

View File

@@ -1,68 +0,0 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Mono.Unix.Native;
using Newtonsoft.Json;
namespace HotPocket
{
public static class HotPocketHelper
{
const int FD_READ_BUFFER_LEN = 1024;
public static async Task<ContractArgs> GetContractArgsAsync()
{
using (var s = new StreamReader(Console.OpenStandardInput()))
{
var input = await s.ReadToEndAsync();
var contractArgs = JsonConvert.DeserializeObject<ContractArgs>(input);
return contractArgs;
}
}
public static string ReadStringFromFD(int fd)
{
return Encoding.UTF8.GetString(ReadBytesFromFD(fd));
}
public static void WriteStringToFD(int fd, string str)
{
WriteBytesToFD(fd, Encoding.UTF8.GetBytes(str));
}
public static unsafe byte[] ReadBytesFromFD(int fd)
{
// Keep reading the fd bytes and fill the memory stream until no more bytes.
using (var ms = new MemoryStream())
{
int readbytes = 0;
do
{
var buffer = new byte[FD_READ_BUFFER_LEN];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
readbytes = (int)Syscall.read(fd, ptr, FD_READ_BUFFER_LEN);
}
ms.Write(buffer, 0, readbytes);
} while (readbytes == FD_READ_BUFFER_LEN);
return ms.ToArray();
}
}
public static unsafe void WriteBytesToFD(int fd, byte[] buffer)
{
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
Syscall.write(fd, ptr, (ulong)buffer.Length);
}
}
}
}

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace HotPocket
{
public class ContractArgs
{
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("pubkey")]
public string PubKey { get; set; }
[JsonProperty("ts")]
public string Timestamp { get; set; }
[JsonProperty("hpfd")]
public IOPipe HotPocketPipe { get; set; }
[JsonProperty("nplfd")]
public IOPipe NplPipe { get; set; }
[JsonProperty("usrfd")]
public Dictionary<string, IOPipe> UserPipes { get; set; }
[JsonProperty("unl")]
public string[] Unl { get; set; }
}
[JsonConverter(typeof(IOPipeJsonConverter))]
public class IOPipe
{
public int ReadFD { get; set; }
public int WriteFD { get; set; }
}
public class IOPipeJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IOPipe);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var array = JArray.Load(reader);
var pipe = (existingValue as IOPipe ?? new IOPipe());
pipe.ReadFD = (int)array.ElementAtOrDefault(0);
pipe.WriteFD = (int)array.ElementAtOrDefault(1);
return pipe;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var pipe = (IOPipe)value;
serializer.Serialize(writer, new[] { pipe.ReadFD, pipe.WriteFD });
}
}
}

View File

@@ -1,39 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using ToDoContract;
namespace ToDoContract.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20200114133142_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.0");
modelBuilder.Entity("ToDoContract.ToDoEntry", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Content")
.HasColumnType("TEXT");
b.Property<string>("CreatedBy")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("ToDoEntries");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,30 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace ToDoContract.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ToDoEntries",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Content = table.Column<string>(nullable: true),
CreatedBy = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ToDoEntries", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ToDoEntries");
}
}
}

View File

@@ -1,37 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using ToDoContract;
namespace ToDoContract.Migrations
{
[DbContext(typeof(DataContext))]
partial class DataContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.0");
modelBuilder.Entity("ToDoContract.ToDoEntry", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Content")
.HasColumnType("TEXT");
b.Property<string>("CreatedBy")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("ToDoEntries");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,136 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using HotPocket;
using System.Linq;
namespace ToDoContract
{
/*
* This is a simple multi-user ToDo list contract which uses sqlite database as storage.
* In order to run this .Net Core should be installed on the system. If using docker,
* mcr.microsoft.com/dotnet/core/sdk:3.1 docker image must be used.
*
* Produce deployable output with: dotnet publish -c Release
*
* User inputs can be submitted in the following format.
* Insert a new ToDo record: add <title>
* Retrieve all records owned by user: get all
* Retrieve record by ID: get <id>
* Delete all records owned by user: delete all
* Delete record by ID: delete <id>
*/
public class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Starting .Net ToDo contract");
using (var dataContext = new DataContext())
{
dataContext.Database.Migrate();
}
ContractArgs contractArgs = await HotPocketHelper.GetContractArgsAsync();
foreach (var user in contractArgs.UserPipes)
{
var pubkey = user.Key;
var pipe = user.Value;
var input = HotPocketHelper.ReadStringFromFD(pipe.ReadFD);
if (string.IsNullOrEmpty(input))
continue;
var output = await HandleUserInputAsync(pubkey, input);
HotPocketHelper.WriteStringToFD(pipe.WriteFD, output);
}
}
static async Task<string> HandleUserInputAsync(string userId, string input)
{
var parts = input.Trim().Split(' ', 2);
if (parts.Length < 2)
return "Invalid input format";
var command = parts[0].ToLower();
var param = parts[1];
using (var dataContext = new DataContext())
{
if (command == "add") // add new record.
{
var entry = new ToDoEntry
{
Content = param,
CreatedBy = userId
};
dataContext.ToDoEntries.Add(entry);
await dataContext.SaveChangesAsync();
return "Added entry with id " + entry.Id;
}
else if (command == "get" || command == "delete")
{
if (param == "all") // get/delete all records.
{
// Get all entries belonging to this user.
var entries = await dataContext.ToDoEntries.Where(e => e.CreatedBy == userId).OrderBy(e => e.Id).ToListAsync();
if (command == "get")
{
return JsonConvert.SerializeObject(entries.Select(e => $"ID-{e.Id}: {e.Content}"));
}
else
{
// Delete all records for this user.
dataContext.RemoveRange(entries);
await dataContext.SaveChangesAsync();
return $"{entries.Count} record(s) deleted";
}
}
else // get/delete by ID.
{
int id = 0;
if (int.TryParse(param, out id))
{
var entry = await dataContext.ToDoEntries.FirstOrDefaultAsync(e => e.Id == id);
if (entry == null)
{
return $"Record id {id} does not exist";
}
else if (entry.CreatedBy != userId)
{
return $"You do not have permission for record id {id}";
}
else
{
if (command == "get")
{
return entry.Content;
}
else
{
dataContext.Remove(entry);
await dataContext.SaveChangesAsync();
return $"Record id {id} deleted";
}
}
}
else
{
return "Invalid record id";
}
}
}
else
{
return "Invalid command";
}
}
}
}
}

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0" />
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project>

View File

@@ -176,7 +176,8 @@ namespace sc
* "hpfd": [fd0, fd1],
* "usrfd":{ "<pkhex>":[fd0, fd1], ... },
* "nplfd":[fd0, fd1],
* "unl":[ "pkhex", ... ]
* "unl":[ "pkhex", ... ],
* "readonly": <true|false>
* }
*/
int write_contract_args(const execution_context &ctx)

View File

@@ -47,12 +47,12 @@ do
# Update contract config.
node -p "JSON.stringify({...require('./tmp.json'), \
binary: '/usr/local/bin/node', \
binargs: '/contract/bin/contract.js', \
binargs: '/contract/bin/echo_contract.js', \
appbill: '', \
appbillargs: '', \
peerport: ${peerport}, \
pubport: ${pubport}, \
roundtime: 1000, \
roundtime: 2000, \
loglevel: 'debug', \
loggers:['console', 'file'] \
}, null, 2)" > hp.cfg
@@ -65,9 +65,12 @@ do
# Copy the contract executable and appbill.
mkdir ./node$n/bin
cp ../../../examples/echo_contract/contract.js ./node$n/bin/contract.js
cp ../../../examples/nodejs_contract/{package.json,echo_contract.js,hp-contract-lib.js} ./node$n/bin/
cp ../bin/appbill ./node$n/bin/
# cp -r ../../../examples/todo_contract/bin/Release/netcoreapp3.1/publish/* ./node$n/bin/
pushd ./node$n/bin > /dev/null 2>&1
npm install
popd
done
# Function to generate JSON array string while skiping a given index.

View File

@@ -1,3 +1,4 @@
cfg
vmpass.txt
iplist.txt
iplist.txt
hpfiles

View File

@@ -1,10 +1,15 @@
#!/bin/bash
# HotPocket VM cluster setup script.
# Usage example: ./cluster.sh run 1
# Usage examples:
# ./cluster.sh new
# ./cluster.sh update
# ./cluster.sh run 1
# VM login password must exist in vmpass.txt
# All VMs must use same SSH password with username 'geveo'
vmpass=$(cat vmpass.txt)
# List vm IP addresses of the cluster must exist in iplist.txt
# List of vm IP addresses/domain names of the cluster must exist in iplist.txt
# (This list will be treated as the node numbers 1,2.3... from topmost IP to the bottom)
readarray -t vmips < iplist.txt
@@ -13,18 +18,19 @@ mode=$1
hpcore=$(realpath ../..)
if [ "$mode" = "new" ] || [ "$mode" = "update" ] || [ "$mode" = "run" ] || [ "$mode" = "check" ] || \
[ "$mode" = "monitor" ] || [ "$mode" = "kill" ] || [ "$mode" = "reboot" ] || [ "$mode" = "ssh" ] || \
[ "$mode" = "dns" ] || [ "$mode" = "ssl" ]; then
if [ "$mode" = "new" ] || [ "$mode" = "update" ] || [ "$mode" = "reconfig" ] || [ "$mode" = "run" ] || \
[ "$mode" = "check" ] || [ "$mode" = "monitor" ] || [ "$mode" = "kill" ] || [ "$mode" = "reboot" ] || \
[ "$mode" = "ssh" ] || [ "$mode" = "dns" ] || [ "$mode" = "ssl" ]; then
echo "mode: $mode"
else
echo "Invalid command. [ new | update | run <N> | check <N> | monitor <N> | kill <N> | reboot <N> | ssh <N> <custom command> | dns <N> <zerossl file> | ssl <N> ] expected."
echo "Invalid command. [ new | update | reconfig | run <N> | check <N> | monitor <N> | kill <N> | reboot <N> | ssh <N> <custom command> | dns <N> <zerossl file> | ssl <N> ] expected."
exit 1
fi
# Command modes:
# new - Install hot pocket dependencies and hot pocket with example contracts to each vm.
# update - Deploy updated hot pocket and example binaries into each vm.
# reconfig - Reconfigures the entire cluster using already uploaded HP binaries.
# run - Run hot pocket of specified vm node.
# check - Check hot pocket running status of specified vm node.
# monitor - Monitor streaming hot pocket console output (if running) of specified vm node.
@@ -37,7 +43,7 @@ fi
if [ $mode = "run" ]; then
let nodeid=$2-1
vmip=${vmips[$nodeid]}
sshpass -f vmpass.txt ssh geveo@$vmip 'nohup sudo ./hpcore run contract'
sshpass -f vmpass.txt ssh geveo@$vmip 'nohup sudo ~/hpfiles/bin/hpcore run ~/contract'
sshpass -f vmpass.txt ssh geveo@$vmip 'tail -f nohup.out'
exit 0
fi
@@ -108,17 +114,19 @@ if [ $mode = "ssl" ]; then
sshpass -f vmpass.txt scp ~/Downloads/$vmip/certs/* geveo@$vmip:~/contract/cfg/
rm -r ~/Downloads/$vmip
echo "Done"
exit 0
fi
mkdir ./cfg > /dev/null 2>&1
for (( i=0; i<$vmcount; i++ ))
do
vmip=${vmips[i]}
let n=$i+1
/bin/bash ./setup-vm.sh $mode $n $vmpass $vmip $hpcore &
done
# Run binary file setup for entire cluster.
if [ $mode = "new" ] || [ $mode = "update" ]; then
for (( i=0; i<$vmcount; i++ ))
do
vmip=${vmips[i]}
let n=$i+1
/bin/bash ./setup-vm.sh $mode $n $vmpass $vmip $hpcore &
done
fi
wait
@@ -126,7 +134,22 @@ if [ $mode = "update" ]; then
exit 0
fi
# Following code will only be executed in 'new' mode.
# All code below this will only execute in 'new' or 'reconfig' mode.
# Update all nodes hp.cfg files to be part of the same UNL cluster.
if [ $mode = "reconfig" ]; then
mkdir ./cfg > /dev/null 2>&1
for (( i=0; i<$vmcount; i++ ))
do
# Run hp setup script on the VM and download the generated hp.cfg
vmip=${vmips[i]}
let nodeid=$i+1
sshpass -f vmpass.txt ssh geveo@$vmip '~/hpfiles/setup-hp.sh'
sshpass -f vmpass.txt scp geveo@$vmip:~/contract/cfg/hp.cfg ./cfg/node$nodeid.json
done
fi
# Locally update values of download hp.cfg files.
for (( i=0; i<$vmcount; i++ ))
do
@@ -172,9 +195,17 @@ do
mypeers=$(joinarr peers $j)
myunl=$(joinarr pubkeys $j)
node -p "JSON.stringify({...require('./cfg/node$n.json'),binary:'/usr/bin/node',binargs:'/home/geveo/contract.js',peers:${mypeers},unl:${myunl},loggers:['console', 'file']}, null, 2)" > ./cfg/node$n.cfg
node -p "JSON.stringify({...require('./cfg/node$n.json'), \
binary:'/usr/bin/node', \
binargs:'/home/geveo/hpfiles/nodejs_contract/echo_contract.js', \
peers:${mypeers}, \
unl:${myunl}, \
roundtime: 2000, \
loglevel: 'debug', \
loggers:['console', 'file'] \
}, null, 2)" > ./cfg/node$n.cfg
# Copy local cfg file back to remote vm.
# Upload local hp.cfg file back to remote vm.
vmip=${vmips[j]}
sshpass -f vmpass.txt scp ./cfg/node$n.cfg geveo@$vmip:~/contract/cfg/hp.cfg
done

View File

@@ -1,5 +1,14 @@
#!/bin/bash
if [[ ! -f /swapfile ]]
then
echo "Adding 5GB swap space..."
sudo fallocate -l 5G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
fi
if [ -x "$(command -v node)" ]; then
echo "NodeJs already installed."
else
@@ -15,14 +24,18 @@ if [ -x "$(command -v fusermount3)" ]; then
else
echo "Installing FUSE and other shared libraries..."
sudo apt-get -y install libgomp1
sudo cp ./libfuse3.so.3 ./libb2.so.1 /usr/local/lib/
sudo cp ~/hpfiles/bin/{libfuse3.so.3,libb2.so.1} /usr/local/lib/
sudo ldconfig
sudo cp ./fusermount3 /usr/local/bin/
sudo cp ~/hpfiles/bin/fusermount3 /usr/local/bin/
fi
sudo rm -r ~/contract > /dev/null 2>&1
./hpcore new ./contract
pushd ./contract/cfg > /dev/null 2>&1
echo "Creating new contract directory..."
~/hpfiles/bin/hpcore new ~/contract
pushd ~/contract/cfg > /dev/null 2>&1
echo "Generating default ssl certs..."
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout tlskey.pem -out tlscert.pem \
-subj "/C=AU/ST=ST/L=L/O=O/OU=OU/CN=localhost/emailAddress=hp@example" > /dev/null 2>&1
popd > /dev/null 2>&1

View File

@@ -8,27 +8,27 @@ hpcore=$5
echo $nodeid. $vmip
# Copy required files to hpfiles dir.
mkdir -p hpfiles/{bin,nodejs_contract}
strip $hpcore/build/hpcore
cp $hpcore/build/hpcore hpfiles/bin/
cp $hpcore/examples/nodejs_contract/{package.json,echo_contract.js,hp-contract-lib.js} hpfiles/nodejs_contract/
if [ $mode = "new" ]; then
cp ../bin/{libfuse3.so.3,libb2.so.1,fusermount3,websocketd,websocat,hpfs} hpfiles/bin/
cp ./setup-hp.sh hpfiles/
fi
echo "Uploading hp files..."
sshpass -f vmpass.txt scp -rp hpfiles geveo@$vmip:~/
echo "Upload finished."
if [ $mode = "new" ]; then
sshpass -f vmpass.txt scp $hpcore/build/hpcore \
$hpcore/examples/echo_contract/contract.js \
../bin/libfuse3.so.3 \
../bin/libb2.so.1 \
../bin/fusermount3 \
../bin/websocketd \
../bin/websocat \
../bin/hpfs \
./consensus-test-continuous.sh \
./setup-hp.sh \
geveo@$vmip:~/
sshpass -f vmpass.txt ssh geveo@$vmip 'chmod 700 ~/consensus-test-continuous.sh && chmod 700 ~/setup-hp.sh && ~/setup-hp.sh'
# Run hp setup script on the VM and download the generated hp.cfg
sshpass -f vmpass.txt ssh geveo@$vmip '~/hpfiles/setup-hp.sh && cd ~/hpfiles/nodejs_contract && npm install'
sshpass -f vmpass.txt ssh geveo@$vmip 'echo sudo ~/hpfiles/bin/hpcore run ~/contract > ~/run.sh && sudo chmod +x ~/run.sh'
mkdir ./cfg > /dev/null 2>&1
sshpass -f vmpass.txt scp geveo@$vmip:~/contract/cfg/hp.cfg ./cfg/node$nodeid.json
else
sshpass -f vmpass.txt scp $hpcore/build/hpcore \
$hpcore/examples/echo_contract/contract.js \
./consensus-test-continuous.sh \
geveo@$vmip:~/
fi
fi
rm -r hpfiles