swap integration test

* add bzz.syncEnabled (hive.syncEnabled -> testapi/SyncEnabled | bzznosync param)) triggers nil sync State request to peer
* syncEnabled false then historical items are not delivered
* add swap initial scenarios, no funds, no retrieval; chequebook autodeployment; available funds -> retrieval
* remove -ipcexp option from swarm script
* tweaks to swarm/cmd files
* add Balance to chequebook api
* set chequebook balance from blockchain
* fix chequebook tests after balance check
* log balance when chequebook created
* fix state setting in ethereum backend
* add balanceAt to backend
This commit is contained in:
zelig 2016-02-05 13:53:52 +08:00
parent 863fbb4c37
commit 5714724bab
22 changed files with 360 additions and 163 deletions

View file

@ -318,6 +318,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.WhisperEnabledFlag, utils.WhisperEnabledFlag,
utils.SwarmConfigPathFlag, utils.SwarmConfigPathFlag,
utils.SwarmSwapDisabled, utils.SwarmSwapDisabled,
utils.SwarmSyncDisabled,
utils.SwarmPortFlag, utils.SwarmPortFlag,
utils.SwarmAccountAddrFlag, utils.SwarmAccountAddrFlag,
utils.ChequebookAddrFlag, utils.ChequebookAddrFlag,

View file

@ -357,6 +357,10 @@ var (
Name: "bzznoswap", Name: "bzznoswap",
Usage: "Swarm SWAP disabled (false)", Usage: "Swarm SWAP disabled (false)",
} }
SwarmSyncDisabled = cli.BoolFlag{
Name: "bzznosync",
Usage: "Swarm Syncing disabled (false)",
}
// ATM the url is left to the user and deployment to // ATM the url is left to the user and deployment to
JSpathFlag = cli.StringFlag{ JSpathFlag = cli.StringFlag{
Name: "jspath", Name: "jspath",
@ -788,9 +792,10 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
if len(bzzport) > 0 { if len(bzzport) > 0 {
bzzconfig.Port = bzzport bzzconfig.Port = bzzport
} }
swap := ctx.GlobalBool(SwarmSwapDisabled.Name) swapEnabled := !ctx.GlobalBool(SwarmSwapDisabled.Name)
syncEnabled := !ctx.GlobalBool(SwarmSyncDisabled.Name)
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return swarm.NewSwarm(ctx, bzzconfig, swap) return swarm.NewSwarm(ctx, bzzconfig, swapEnabled, syncEnabled)
}); err != nil { }); err != nil {
Fatalf("Failed to register the Swarm service: %v", err) Fatalf("Failed to register the Swarm service: %v", err)
} }

View file

@ -1,6 +1,7 @@
package chequebook package chequebook
import ( import (
"errors"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -8,22 +9,44 @@ import (
const Version = "1.0" const Version = "1.0"
var errNoChequebook = errors.New("no chequebook")
type Api struct { type Api struct {
ch *Chequebook chequebookf func() *Chequebook
} }
func NewApi(ch *Chequebook) *Api { func NewApi(ch func() *Chequebook) *Api {
return &Api{ch} return &Api{ch}
} }
func (self *Api) Balance() (string, error) {
ch := self.chequebookf()
if ch == nil {
return "", errNoChequebook
}
return ch.Balance().String(), nil
}
func (self *Api) Issue(beneficiary common.Address, amount *big.Int) (cheque *Cheque, err error) { func (self *Api) Issue(beneficiary common.Address, amount *big.Int) (cheque *Cheque, err error) {
return self.ch.Issue(beneficiary, amount) ch := self.chequebookf()
if ch == nil {
return nil, errNoChequebook
}
return ch.Issue(beneficiary, amount)
} }
func (self *Api) Cash(cheque *Cheque) (txhash string, err error) { func (self *Api) Cash(cheque *Cheque) (txhash string, err error) {
return self.ch.Cash(cheque) ch := self.chequebookf()
if ch == nil {
return "", errNoChequebook
}
return ch.Cash(cheque)
} }
func (self *Api) Deposit(amount *big.Int) (txhash string, err error) { func (self *Api) Deposit(amount *big.Int) (txhash string, err error) {
return self.ch.Deposit(amount) ch := self.chequebookf()
if ch == nil {
return "", errNoChequebook
}
return ch.Deposit(amount)
} }

View file

@ -54,6 +54,7 @@ type Backend interface {
Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, string, error) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, string, error)
GetTxReceipt(txhash common.Hash) *types.Receipt GetTxReceipt(txhash common.Hash) *types.Receipt
CodeAt(address string) string CodeAt(address string) string
BalanceAt(address common.Address) string
} }
// rlp serialised cheque model for use with the chequebook // rlp serialised cheque model for use with the chequebook
@ -165,13 +166,25 @@ func NewChequebook(path string, contract common.Address, prvKey *ecdsa.PrivateKe
owner: owner, owner: owner,
} }
if (contract != common.Address{}) { if (contract != common.Address{}) {
glog.V(logger.Detail).Infof("[CHEQUEBOOK] new chequebook initialised from %v (owner: %v)", contract.Hex(), owner.Hex()) err = self.setBalanceFromBlockChain()
if err != nil {
return nil, err
}
glog.V(logger.Detail).Infof("[CHEQUEBOOK] new chequebook initialised from %v (owner: %v, balance: %s)", contract.Hex(), owner.Hex(), self.balance.String())
} }
return return
} }
func (self *Chequebook) setBalanceFromBlockChain() error {
balanceString := self.backend.BalanceAt(self.contract)
if _, ok := self.balance.SetString(balanceString, 10); !ok {
return fmt.Errorf("Incorrect balance: %s", balanceString)
}
return nil
}
// LoadChequebook(path, prvKey, backend) loads a chequebook from disk (file path) // LoadChequebook(path, prvKey, backend) loads a chequebook from disk (file path)
func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend) (self *Chequebook, err error) { func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend, checkBalance bool) (self *Chequebook, err error) {
var data []byte var data []byte
data, err = ioutil.ReadFile(path) data, err = ioutil.ReadFile(path)
if err != nil { if err != nil {
@ -184,7 +197,14 @@ func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend) (sel
if err != nil { if err != nil {
return nil, err return nil, err
} }
glog.V(logger.Detail).Infof("[CHEQUEBOOK] loaded chequebook (%s, owner: %v) initialised from %v", self.contract.Hex(), self.owner.Hex(), path) if checkBalance {
err = self.setBalanceFromBlockChain()
if err != nil {
return nil, err
}
}
glog.V(logger.Detail).Infof("[CHEQUEBOOK] loaded chequebook (%s, owner: %v, balance: %v) initialised from %v", self.contract.Hex(), self.owner.Hex(), self.balance, path)
return return
} }

View file

@ -45,6 +45,10 @@ func (b *testBackend) CodeAt(address string) string {
return "" return ""
} }
func (b *testBackend) BalanceAt(address common.Address) string {
return "0"
}
func genAddr() common.Address { func genAddr() common.Address {
prvKey, _ := crypto.GenerateKey() prvKey, _ := crypto.GenerateKey()
return crypto.PubkeyToAddress(prvKey.PublicKey) return crypto.PubkeyToAddress(prvKey.PublicKey)
@ -54,21 +58,21 @@ func TestIssueAndReceive(t *testing.T) {
prvKey, _ := crypto.GenerateKey() prvKey, _ := crypto.GenerateKey()
sender := genAddr() sender := genAddr()
path := "/tmp/checkbook.json" path := "/tmp/checkbook.json"
chbook, err := NewChequebook(path, sender, prvKey, nil) chbook, err := NewChequebook(path, sender, prvKey, newTestBackend())
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
recipient := genAddr() recipient := genAddr()
chbook.sent[recipient] = new(big.Int).SetUint64(42) chbook.sent[recipient] = new(big.Int).SetUint64(42)
amount := common.Big1 amount := common.Big1
ch, err := chbook.Issue(recipient, amount) ch, err := chbook.Issue(recipient, amount)
if err == nil { if err == nil {
t.Errorf("expected insufficient funds error, got none") t.Fatalf("expected insufficient funds error, got none")
} }
chbook.balance = new(big.Int).Set(common.Big1) chbook.balance = new(big.Int).Set(common.Big1)
if chbook.Balance().Cmp(common.Big1) != 0 { if chbook.Balance().Cmp(common.Big1) != 0 {
t.Errorf("expected: %v, got %v", "0", chbook.Balance()) t.Fatalf("expected: %v, got %v", "0", chbook.Balance())
} }
ch, err = chbook.Issue(recipient, amount) ch, err = chbook.Issue(recipient, amount)
@ -102,9 +106,9 @@ func TestCheckbookFile(t *testing.T) {
prvKey, _ := crypto.GenerateKey() prvKey, _ := crypto.GenerateKey()
sender := genAddr() sender := genAddr()
path := "/tmp/checkbook.json" path := "/tmp/checkbook.json"
chbook, err := NewChequebook(path, sender, prvKey, nil) chbook, err := NewChequebook(path, sender, prvKey, newTestBackend())
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
recipient := genAddr() recipient := genAddr()
chbook.sent[recipient] = new(big.Int).SetUint64(42) chbook.sent[recipient] = new(big.Int).SetUint64(42)
@ -112,7 +116,7 @@ func TestCheckbookFile(t *testing.T) {
chbook.Save() chbook.Save()
chbook, err = LoadChequebook(path, prvKey, nil) chbook, err = LoadChequebook(path, prvKey, newTestBackend(), false)
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
@ -139,12 +143,12 @@ func TestVerifyErrors(t *testing.T) {
sender0 := genAddr() sender0 := genAddr()
sender1 := genAddr() sender1 := genAddr()
path0 := "/tmp/checkbook0.json" path0 := "/tmp/checkbook0.json"
chbook0, err := NewChequebook(path0, sender0, prvKey, nil) chbook0, err := NewChequebook(path0, sender0, prvKey, newTestBackend())
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Errorf("expected no error, got %v", err)
} }
path1 := "/tmp/checkbook1.json" path1 := "/tmp/checkbook1.json"
chbook1, err := NewChequebook(path1, sender1, prvKey, nil) chbook1, err := NewChequebook(path1, sender1, prvKey, newTestBackend())
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Errorf("expected no error, got %v", err)
} }
@ -179,7 +183,7 @@ func TestVerifyErrors(t *testing.T) {
} }
received, err = chbox.Receive(ch1) received, err = chbox.Receive(ch1)
t.Log(err) t.Logf("correct error: %v", err)
if err == nil { if err == nil {
t.Fatalf("expected receiver error, got none") t.Fatalf("expected receiver error, got none")
} }
@ -189,19 +193,19 @@ func TestVerifyErrors(t *testing.T) {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
received, err = chbox.Receive(ch2) received, err = chbox.Receive(ch2)
t.Log(err) t.Logf("correct error: %v", err)
if err == nil { if err == nil {
t.Fatalf("expected sender error, got none") t.Fatalf("expected sender error, got none")
} }
_, err = chbook1.Issue(recipient0, new(big.Int).SetInt64(-1)) _, err = chbook1.Issue(recipient0, new(big.Int).SetInt64(-1))
t.Log(err) t.Logf("correct error: %v", err)
if err == nil { if err == nil {
t.Fatalf("expected incorrect amount error, got none") t.Fatalf("expected incorrect amount error, got none")
} }
received, err = chbox.Receive(ch0) received, err = chbox.Receive(ch0)
t.Log(err) t.Logf("correct error: %v", err)
if err == nil { if err == nil {
t.Fatalf("expected incorrect amount error, got none") t.Fatalf("expected incorrect amount error, got none")
} }
@ -365,7 +369,7 @@ func TestCash(t *testing.T) {
prvKey, _ := crypto.GenerateKey() prvKey, _ := crypto.GenerateKey()
sender := genAddr() sender := genAddr()
path := "/tmp/checkbook.json" path := "/tmp/checkbook.json"
chbook, err := NewChequebook(path, sender, prvKey, nil) chbook, err := NewChequebook(path, sender, prvKey, newTestBackend())
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Errorf("expected no error, got %v", err)
} }

View file

@ -527,6 +527,18 @@ web3._extend({
params: 1, params: 1,
inputFormatter: [null] inputFormatter: [null]
}), }),
new web3._extend.Method({
name: 'syncEnabled',
call: 'bzz_syncEnabled',
params: 1,
inputFormatter: [null]
}),
new web3._extend.Method({
name: 'swapEnabled',
call: 'bzz_swapEnabled',
params: 1,
inputFormatter: [null]
}),
new web3._extend.Method({ new web3._extend.Method({
name: 'resolve', name: 'resolve',
call: 'bzz_resolve', call: 'bzz_resolve',
@ -580,12 +592,11 @@ web3._extend({
params: 1, params: 1,
inputFormatter: [null] inputFormatter: [null]
}), }),
new web3._extend.Method({ new web3._extend.Property({
name: 'info', name: 'balance',
call: 'chequebook_info', getter: 'chequebook_balance',
params: 1, outputFormatter: web3._extend.utils.toDecimal
inputFormatter: [null] }),
}),
new web3._extend.Method({ new web3._extend.Method({
name: 'cash', name: 'cash',
call: 'chequebook_cash', call: 'chequebook_cash',

View file

@ -56,7 +56,7 @@ func NewEthApi(ethereum *eth.Ethereum) *ethApi {
// Note: this is not threadsafe, only called in JS single process and tests // Note: this is not threadsafe, only called in JS single process and tests
func (self *ethApi) UpdateState() (wait chan *big.Int) { func (self *ethApi) UpdateState() (wait chan *big.Int) {
wait = make(chan *big.Int) wait = make(chan *big.Int)
self.state, _ = state.New(self.eth.BlockChain().GetBlockByNumber(0).Root(), self.eth.ChainDb()) self.state, _ = state.New(self.eth.BlockChain().CurrentBlock().Root(), self.eth.ChainDb())
go func() { go func() {
eventSub := self.eth.EventMux().Subscribe(core.ChainHeadEvent{}) eventSub := self.eth.EventMux().Subscribe(core.ChainHeadEvent{})
@ -130,6 +130,10 @@ func (self *ethApi) StorageAt(addr, storageAddr string) string {
return self.state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex() return self.state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex()
} }
func (self *ethApi) BalanceAt(address common.Address) string {
return self.state.GetBalance(address).String()
}
func (self *ethApi) CodeAt(address string) string { func (self *ethApi) CodeAt(address string) string {
return common.ToHex(self.state.GetCode(common.HexToAddress(address))) return common.ToHex(self.state.GetCode(common.HexToAddress(address)))
} }

View file

@ -16,5 +16,13 @@ func NewControl(api *Api, hive *network.Hive) *Control {
} }
func (self *Control) BlockNetworkRead(on bool) { func (self *Control) BlockNetworkRead(on bool) {
self.hive.BlockNetworkRead(true) self.hive.BlockNetworkRead(on)
}
func (self *Control) SyncEnabled(on bool) {
self.hive.SyncEnabled(on)
}
func (self *Control) SwapEnabled(on bool) {
self.hive.SwapEnabled(on)
} }

View file

@ -13,6 +13,8 @@ shift
# created to the latest, so that monitoring be easier with the same filename # created to the latest, so that monitoring be easier with the same filename
# TODO: use this if GETH not set # TODO: use this if GETH not set
# GETH=geth # GETH=geth
echo "ls -l $GETH"
ls -l $GETH
# geth CLI params e.g., (dd=04, run=09) # geth CLI params e.g., (dd=04, run=09)
datetag=`date "+%c%y%m%d-%H%M%S"|cut -d ' ' -f 5` datetag=`date "+%c%y%m%d-%H%M%S"|cut -d ' ' -f 5`
@ -21,37 +23,46 @@ log=$root/log/$id.$datetag.log # /tmp/eth/04.09.log
linklog=$root/log/$id.current.log # /tmp/eth/04.09.log linklog=$root/log/$id.current.log # /tmp/eth/04.09.log
stablelog=$root/log/$id.log # /tmp/eth/04.09.log stablelog=$root/log/$id.log # /tmp/eth/04.09.log
password=$id # 04 password=$id # 04
port=345$id # 34504 port=303$id # 34504
bzzport=622$id # 62204 bzzport=322$id # 32204
rpcport=62$id # 6204 rpcport=32$id # 3204
mkdir -p $root/data mkdir -p $root/data
mkdir -p $root/enodes
mkdir -p $root/pids
mkdir -p $root/log mkdir -p $root/log
ln -sf "$log" "$linklog" ln -sf "$log" "$linklog"
# if we do not have an account, create one # if we do not have an account, create one
# will not prompt for password, we use the double digit instance id as passwd # will not prompt for password, we use the double digit instance id as passwd
# NEVER EVER USE THESE ACCOUNTS FOR INTERACTING WITH A LIVE CHAIN # NEVER EVER USE THESE ACCOUNTS FOR INTERACTING WITH A LIVE CHAIN
if [ ! -d "$root/keystore/$id" ]; then keystoredir="$datadir/keystore/"
# echo "create an account with password $id" echo "KeyStore dir: $keystoredir"
# echo "create an account with password $id [DO NOT EVER USE THIS ON LIVE]" if [ ! -d "$keystoredir" ]; then
mkdir -p $root/keystore/$id echo "create an account with password $id [DO NOT EVER USE THIS ON LIVE]"
# mkdir -p $datadir/keystore
$GETH --datadir $datadir --password <(echo -n $id) account new >/dev/null 2>&1 $GETH --datadir $datadir --password <(echo -n $id) account new >/dev/null 2>&1
# create account with password 00, 01, ... # create account with password 00, 01, ...
# note that the account key will be stored also separately outside # note that the account key will be stored also separately outside
# datadir # datadir
# this way you can safely clear the data directory and still keep your key # this way you can safely clear the data directory and still keep your key
# under `<rootdir>/keystore/dd # under `<rootdir>/keystore/dd
# LS=`ls $datadir/keystore`
cp -R "$datadir/keystore" $root/keystore/$id # echo $LS
while [ ! -d "$keystoredir" ]; do
echo "."
((i++))
if ((i>10)); then break; fi
sleep 1
done
echo "copying keys $datadir/keystore $root/keystore/$id"
mkdir -p $root/keystore/$id
cp -R "$datadir/keystore/" $root/keystore/$id
fi fi
# echo "copying keys $root/keystore/$id $datadir/keystore" # # mkdir -p $datadir/keystore
# ls $root/keystore/$id/keystore/ $datadir/keystore
# mkdir -p $datadir/keystore
# if [ ! -d "$datadir/keystore" ]; then # if [ ! -d "$datadir/keystore" ]; then
# echo "copying keys $root/keystore/$id $datadir/keystore" # echo "copying keys $root/keystore/$id $datadir/keystore"
cp -R $root/keystore/$id/keystore/ $datadir/keystore/ # cp -R $root/keystore/$id/keystore/ $datadir/keystore/
# fi # fi
@ -63,10 +74,10 @@ else
pattern='\[\:\:\]' pattern='\[\:\:\]'
fi fi
# echo -n "enode for instance $id... " geth="$GETH --datadir $datadir --port $port"
# echo -n "enode for instance $id... "
if [ ! "$GETH" = "" ] && [ ! -f $root/enodes/$id.enode ]; then if [ ! "$GETH" = "" ] && [ ! -f $root/enodes/$id.enode ]; then
geth="$GETH --datadir $root/data/$id --port $port"
cmd="$geth js <(echo 'console.log(admin.nodeInfo.enode); exit();') " cmd="$geth js <(echo 'console.log(admin.nodeInfo.enode); exit();') "
# echo $cmd '2>/dev/null |grep enode | perl -pe "s/'$pattern'/'$ip_addr'/g" | perl -pe "s/^/\"/; s/\s*$/\"/;" > '$root/enodes/$id.enode # echo $cmd '2>/dev/null |grep enode | perl -pe "s/'$pattern'/'$ip_addr'/g" | perl -pe "s/^/\"/; s/\s*$/\"/;" > '$root/enodes/$id.enode
eval $cmd 2>/dev/null |grep enode | perl -pe "s/$pattern/$ip_addr/g" | perl -pe "s/^/\"/; s/\s*\$/\"/;" > $root/enodes/$id.enode eval $cmd 2>/dev/null |grep enode | perl -pe "s/$pattern/$ip_addr/g" | perl -pe "s/^/\"/; s/\s*\$/\"/;" > $root/enodes/$id.enode
@ -86,17 +97,17 @@ if [ ! -f $root/pids/$id.pid ]; then
# - listening on port 303dd, (like 30300, 30301, ...) # - listening on port 303dd, (like 30300, 30301, ...)
# - with the account unlocked # - with the account unlocked
# - launching json-rpc server on port 81dd (like 8100, 8101, 8102, ...) # - launching json-rpc server on port 81dd (like 8100, 8101, 8102, ...)
BZZKEY=`$GETH --datadir=$datadir account list|head -n1|perl -ne '/([a-f0-9]{40})/ && print $1'` # echo "BZZKEY=$geth account list|head -n1|perl -ne '/([a-f0-9]{40})/ && print \$1'"
BZZKEY=`$geth account list|head -n1|perl -ne '/([a-f0-9]{40})/ && print \$1'`
echo -n "starting instance $id ($BZZKEY @ $datadir )..." echo -n "starting instance $id ($BZZKEY @ $datadir )..."
# echo "$GETH --datadir=$datadir \ echo "$geth \
# --identity=$id \ --identity=$id \
# --bzzaccount=$BZZKEY --bzzport=$bzzport \ --bzzaccount=$BZZKEY --bzzport=$bzzport \
# --port=$port \ --unlock=$BZZKEY \
# --unlock=$BZZKEY \ --password=<(echo -n $id) \
# --password=<(echo -n $id) \ --rpc --rpcport=$rpcport --rpccorsdomain='*' $* \
# --rpc --rpcport=$rpcport --rpccorsdomain='*' $* \ 2>&1 | tee "$stablelog" > "$log" & # comment out if you pipe it to a tty etc.
# 2>&1 | tee "$stablelog" > "$log" & # comment out if you pipe it to a tty etc. " >&2
# " >&2
if [ -f $log ] && [ -f $root/stablelog ]; then if [ -f $log ] && [ -f $root/stablelog ]; then
cp $stablelog `cat $root/prevlog` cp $stablelog `cat $root/prevlog`
@ -118,6 +129,7 @@ if [ ! -f $root/pids/$id.pid ]; then
# echo $pid > $root/pids/$id.pid # echo $pid > $root/pids/$id.pid
#echo $! > $root/pids/$id.pid #echo $! > $root/pids/$id.pid
while true; do while true; do
# echo $GETH --ipcpath=$datadir/geth.ipc --exec="net" attach
$GETH --ipcpath=$datadir/geth.ipc --exec="net" attach > /dev/null 2>&1 && break $GETH --ipcpath=$datadir/geth.ipc --exec="net" attach > /dev/null 2>&1 && break
sleep 1 sleep 1
echo -n "." echo -n "."

View file

@ -1,8 +1,8 @@
# !/bin/bash # !/bin/bash
# bash intelligence <destination_app_json_path> <number_of_nodes> <name_prefix> <ws_server> <ws_secret> # bash netstatconf.sh <number_of_nodes> <name_prefix> <ws_server> <ws_secret>
# sets up a eth-net-intelligence app.json for a local ethereum network cluster of nodes # sets up a eth-net-intelligence app.json for a local ethereum network cluster of nodes
# - <number_of_clusters> is the number of clusters # - <number_of_nodes> is the number of nodes in the cluster
# - <name_prefix> is a prefix for the node names as will appear in the listing # - <name_prefix> is a prefix for the node names as will appear in the listing
# - <ws_server> is the eth-netstats server # - <ws_server> is the eth-netstats server
# - <ws_secret> is the eth-netstats secret # - <ws_secret> is the eth-netstats secret

View file

@ -37,31 +37,8 @@ shift
# ip_addr=`curl ipecho.net/plain 2>/dev/null;echo ` # ip_addr=`curl ipecho.net/plain 2>/dev/null;echo `
# echo "external IP: $ip_addr" # echo "external IP: $ip_addr"
swarmoptions='--vmdebug=false --maxpeers=20 --dev --shh=false --nodiscover --ipcexp' swarmoptions='--vmdebug=false --maxpeers=20 --dev --shh=false --nodiscover'
tmpdir=/tmp
function needs {
id=$1
keyfile=$2
target=$3
dir=`dirname $3`
dest=$dir/down
mkdir -p $dest
file=$dest/`basename $target`
rm -f $file
echo -n "download to '$file'...waiting for root hash in '$keyfile'..."
while true; do
if [ -f $keyfile ] && [ ! -z $keyfile ]; then
break
fi
sleep 1
echo -n "."
done
key=`cat $keyfile`
echo " => $key"
download $id $key $dest && cmp --silent $file $target && echo "PASS" || echo "FAIL"
# && ls -l $keyfile $file $target
}
function attach { function attach {
id=$1 id=$1
@ -145,7 +122,6 @@ function init {
reset all reset all
cluster $* cluster $*
stop all stop all
sleep 5
cluster $* cluster $*
} }
@ -163,7 +139,7 @@ function reset {
function cluster { function cluster {
N=$1 N=$1
shift shift
# --vmodule=netstore=6,depo=6,forwarding=6,hive=5,dpa=6,dpa=6,http=6,syncb=6,syncer=6,protocol=6,swap=6,chequebook=6 vmodule='--vmodule=network/*=6,syncb=6,syncer=6,protocol=6,swap=6,chequebook=6'
echo "launching cluster of $N instances" echo "launching cluster of $N instances"
# cmd="bash $srcdir/gethcluster.sh $root $network_id $N '' $swarmoptions $*" # cmd="bash $srcdir/gethcluster.sh $root $network_id $N '' $swarmoptions $*"
# echo $cmd # echo $cmd
@ -192,22 +168,46 @@ function cluster {
id=`printf "%02d" $i` id=`printf "%02d" $i`
mkdir -p $dir/data/$id mkdir -p $dir/data/$id
echo "launching node $i/$N ---> tail-f $dir/log/$id.log" echo "launching node $i/$N ---> tail-f $dir/log/$id.log"
start $id $* start $id $vmodule $*
done done
} }
function needs {
id=$1
keyfile=$2
target=$3
dir=`dirname $3`
dest=$tmpdir/down
mkdir -p $dest
file=$dest/`basename $target`
rm -f $file
echo -n "waiting for root hash in '$keyfile'..."
while true; do
if [ -f $keyfile ] && [ ! -z $keyfile ]; then
break
fi
sleep 1
echo -n "."
done
key=`cat $keyfile|tr -d \"`
echo " => $key"
download $id $key $dest && cmp --silent $file $target && echo "PASS" || echo "FAIL"
# && ls -l $keyfile $file $target
}
function up { #port, file function up { #port, file
echo "Upload file '$2' to node $1... " 1>&2 echo "Upload file '$2' to node $1... " 1>&2
file=`basename $2` file=`basename $2`
key=`attach $1 "--exec 'bzz.upload(\"$2\", \"$file\")'"|tail -n1` attach $1 "--exec 'bzz.upload(\"$2\", \"$file\")'"|tail -n1> /tmp/key
# key=`bash swarm/cmd/bzzup.sh $2 86$1` # key=`bash swarm/cmd/bzzup.sh $2 86$1`
echo "-> $key" cat /tmp/key
echo -n `eval echo $key`
} }
function download { function download {
echo "download to '$3'" echo "download to '$3'"
echo attach $1 "--exec 'bzz.download(\"$2\", \"$3\")'"
attach $1 "--exec 'bzz.download(\"$2\", \"$3\")'" > /dev/null attach $1 "--exec 'bzz.download(\"$2\", \"$3\")'" > /dev/null
} }
@ -234,14 +234,22 @@ function clean { #index
} }
function info { function info {
echo "swarm node information"
echo "ROOTDIR: $root" echo "ROOTDIR: $root"
echo "DATADIR: $root/data/$1" echo "DATADIR: $root/$network_id/data/$1"
echo "LOGFILE: $root/log/$1.log" echo "LOGFILE: $root/$network_id/log/$1.log"
echo "HTTPAPI: http://localhost:32$1"
echo "ETHPORT: 302$1"
echo "RPCPORT: 322$1"
echo "ACCOUNT:" 0x`ls -1 $root/$network_id/data/$1/bzz`
echo "CHEQUEB:" `cat $root/$network_id/data/$1/bzz/*/config.json|grep Contract|awk -F\" '{print $4}'`
} }
case $cmd in case $cmd in
"info" ) "info" )
info $*;; info $*;;
"clean" )
clean $*;;
"needs" ) "needs" )
needs $*;; needs $*;;
"up" ) "up" )
@ -264,4 +272,6 @@ case $cmd in
attach $*;; attach $*;;
"log" ) "log" )
log $*;; log $*;;
"less" )
less $*;;
esac esac

View file

@ -5,14 +5,12 @@ TEST_NAME=`basename $0 .sh`
export SWARM_BIN=$TEST_DIR/../../cmd/swarm export SWARM_BIN=$TEST_DIR/../../cmd/swarm
export GETH=$SWARM_BIN/../../../geth export GETH=$SWARM_BIN/../../../geth
export NETWORKID=622$TEST_NAME export NETWORKID=322$TEST_NAME
export TMPDIR=/tmp/swarm-test export TMPDIR=~/BZZ/swarm-test
export DATA_ROOT=$TMPDIR/$NETWORKID export DATA_ROOT=$TMPDIR/$NETWORKID
# alias swarm='bash $SWARM_BIN/swarm.sh $DATA_ROOT $NETWORKID' # alias swarm='bash $SWARM_BIN/swarm.sh $DATA_ROOT $NETWORKID'
EXTRA_ARGS=$* EXTRA_ARGS=$*
rm -rf $DATA_ROOT
wait=1 wait=1
function swarm { function swarm {

View file

@ -5,9 +5,9 @@ import (
"encoding/binary" "encoding/binary"
"time" "time"
"github.com/ethereum/go-ethereum/swarm/storage"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/swarm/storage"
) )
// Handler for storage/retrieval related protocol requests // Handler for storage/retrieval related protocol requests
@ -51,6 +51,7 @@ func (self *Depo) HandleUnsyncedKeysMsg(req *unsyncedKeysMsgData, p *peer) error
if err != nil { if err != nil {
return err return err
} }
// set peers state to persist
p.syncState = req.State p.syncState = req.State
return nil return nil
} }

View file

@ -42,25 +42,26 @@ var searchTimeout = 3 * time.Second
func (self *forwarder) Retrieve(chunk *storage.Chunk) { func (self *forwarder) Retrieve(chunk *storage.Chunk) {
peers := self.hive.getPeers(chunk.Key, 0) peers := self.hive.getPeers(chunk.Key, 0)
glog.V(logger.Detail).Infof("[BZZ] forwarder.Retrieve: %v - received %d peers from KΛÐΞMLIΛ...", chunk.Key.Log(), len(peers)) glog.V(logger.Detail).Infof("[BZZ] forwarder.Retrieve: %v - received %d peers from KΛÐΞMLIΛ...", chunk.Key.Log(), len(peers))
OUT:
for _, p := range peers { for _, p := range peers {
glog.V(logger.Detail).Infof("[BZZ] forwarder.Retrieve: sending retrieveRequest %v to peer [%v]", chunk.Key.Log(), p) glog.V(logger.Detail).Infof("[BZZ] forwarder.Retrieve: sending retrieveRequest %v to peer [%v]", chunk.Key.Log(), p)
var req *retrieveRequestMsgData
OUT:
for _, recipients := range chunk.Req.Requesters { for _, recipients := range chunk.Req.Requesters {
for _, recipient := range recipients { for _, recipient := range recipients {
req := recipient.(*retrieveRequestMsgData) req := recipient.(*retrieveRequestMsgData)
if req.from.Addr() == p.Addr() { if req.from.Addr() == p.Addr() {
break OUT continue OUT
} }
} }
} }
if req != nil { req := &retrieveRequestMsgData{
if err := p.swap.Add(-1); err == nil { Key: chunk.Key,
p.retrieve(req) Id: generateId(),
break }
} else { if err := p.swap.Add(-1); err == nil {
glog.V(logger.Warn).Infof("[BZZ] forwarder.Retrieve: unable to send retrieveRequest to peer [%v]: %v", chunk.Key.Log(), err) p.retrieve(req)
} break OUT
} else {
glog.V(logger.Warn).Infof("[BZZ] forwarder.Retrieve: unable to send retrieveRequest to peer [%v]: %v", chunk.Key.Log(), err)
} }
} }
} }

View file

@ -32,8 +32,12 @@ type Hive struct {
path string path string
toggle chan bool toggle chan bool
more chan bool more chan bool
blockRead bool
blockWrite bool // for testing only
swapEnabled bool
syncEnabled bool
blockRead bool
blockWrite bool
} }
const ( const (
@ -62,16 +66,26 @@ func NewHiveParams(path string) *HiveParams {
} }
} }
func NewHive(addr common.Hash, params *HiveParams) *Hive { func NewHive(addr common.Hash, params *HiveParams, swapEnabled, syncEnabled bool) *Hive {
kad := kademlia.New(kademlia.Address(addr), params.KadParams) kad := kademlia.New(kademlia.Address(addr), params.KadParams)
return &Hive{ return &Hive{
callInterval: params.CallInterval, callInterval: params.CallInterval,
kad: kad, kad: kad,
addr: kad.Addr(), addr: kad.Addr(),
path: params.KadDbPath, path: params.KadDbPath,
swapEnabled: swapEnabled,
syncEnabled: syncEnabled,
} }
} }
func (self *Hive) SyncEnabled(on bool) {
self.syncEnabled = on
}
func (self *Hive) SwapEnabled(on bool) {
self.swapEnabled = on
}
func (self *Hive) BlockNetworkRead(on bool) { func (self *Hive) BlockNetworkRead(on bool) {
self.blockRead = on self.blockRead = on
} }

View file

@ -109,7 +109,7 @@ type retrieveRequestMsgData struct {
MaxSize uint64 // maximum size of delivery accepted MaxSize uint64 // maximum size of delivery accepted
MaxPeers uint64 // maximum number of peers returned MaxPeers uint64 // maximum number of peers returned
Timeout uint64 // the longest time we are expecting a response Timeout uint64 // the longest time we are expecting a response
timeout *time.Time // [not serialied]} timeout *time.Time // [not serialised]}
from *peer // from *peer //
} }
@ -234,7 +234,7 @@ peer/protocol instance when the node is registered by hive as online{
*/ */
type syncRequestMsgData struct { type syncRequestMsgData struct {
SyncState *syncState `rlp:"nil"` SyncState *syncState `rlp:nil`
} }
func (self *syncRequestMsgData) String() string { func (self *syncRequestMsgData) String() string {

View file

@ -78,11 +78,11 @@ type bzz struct {
swap *swap.Swap // swap instance for the peer connection swap *swap.Swap // swap instance for the peer connection
swapParams *bzzswap.SwapParams // swap settings both local and remote swapParams *bzzswap.SwapParams // swap settings both local and remote
swapEnabled bool // flag to switch off SWAP (will be via Caps in handshake) swapEnabled bool // flag to enable SWAP (will be set via Caps in handshake)
syncEnabled bool // flag to enable SYNC (will be set via Caps in handshake)
syncer *syncer // syncer instance for the peer connection syncer *syncer // syncer instance for the peer connection
syncParams *SyncParams // syncer params syncParams *SyncParams // syncer params
syncState *syncState // outgoing syncronisation state (contains reference to remote peers db counter) syncState *syncState // outgoing syncronisation state (contains reference to remote peers db counter)
syncEnabled bool // flag to enable syncing
} }
// interface type for handler of storage/retrieval related requests coming // interface type for handler of storage/retrieval related requests coming
@ -152,7 +152,7 @@ func run(requestDb *storage.LDBDatabase, depo StorageHandler, hive *Hive, dbacce
}, },
swapParams: sp, swapParams: sp,
syncParams: sy, syncParams: sy,
swapEnabled: true, swapEnabled: hive.swapEnabled,
syncEnabled: true, syncEnabled: true,
} }
@ -273,8 +273,6 @@ func (self *bzz) handle() error {
if err != nil { if err != nil {
return self.protoError(ErrDecode, "->msg %v: %v", msg, err) return self.protoError(ErrDecode, "->msg %v: %v", msg, err)
} }
// set peers state to persist
self.syncState = req.State
case deliveryRequestMsg: case deliveryRequestMsg:
// response to syncKeysMsg hashes filtered not existing in db // response to syncKeysMsg hashes filtered not existing in db
@ -291,12 +289,14 @@ func (self *bzz) handle() error {
case paymentMsg: case paymentMsg:
// swap protocol message for payment, Units paid for, Cheque paid with // swap protocol message for payment, Units paid for, Cheque paid with
var req paymentMsgData if self.swapEnabled {
if err := msg.Decode(&req); err != nil { var req paymentMsgData
return self.protoError(ErrDecode, "->msg %v: %v", msg, err) if err := msg.Decode(&req); err != nil {
return self.protoError(ErrDecode, "->msg %v: %v", msg, err)
}
glog.V(logger.Debug).Infof("[BZZ] incoming payment: %s", req.String())
self.swap.Receive(int(req.Units), req.Promise)
} }
glog.V(logger.Debug).Infof("[BZZ] incoming payment: %s", req.String())
self.swap.Receive(int(req.Units), req.Promise)
default: default:
// no other message is allowed // no other message is allowed
@ -366,10 +366,9 @@ func (self *bzz) handleStatus() (err error) {
self.hive.addPeer(&peer{bzz: self}) self.hive.addPeer(&peer{bzz: self})
// hive sets syncstate so sync should start after node added // hive sets syncstate so sync should start after node added
if self.syncEnabled { glog.V(logger.Info).Infof("[BZZ] syncronisation request sent with %v", self.syncState)
glog.V(logger.Info).Infof("[BZZ] syncronisation request sent with %v", self.syncState) self.syncRequest()
self.syncRequest()
}
return nil return nil
} }
@ -382,9 +381,10 @@ func (self *bzz) sync(state *syncState) error {
cnt := self.dbAccess.counter() cnt := self.dbAccess.counter()
remoteaddr := self.remoteAddr.Addr remoteaddr := self.remoteAddr.Addr
start, stop := self.hive.kad.KeyRange(remoteaddr) start, stop := self.hive.kad.KeyRange(remoteaddr)
// an explicitly received nil syncstate disables syncronisation
if state == nil { if state == nil {
state = newSyncState(start, stop, cnt) self.syncEnabled = false
glog.V(logger.Warn).Infof("[BZZ] peer %08x provided no sync state, setting up full sync: %v\n", remoteaddr[:4], state)
} else { } else {
state.synced = make(chan bool) state.synced = make(chan bool)
state.SessionAt = cnt state.SessionAt = cnt
@ -399,7 +399,7 @@ func (self *bzz) sync(state *syncState) error {
storage.Key(remoteaddr[:]), storage.Key(remoteaddr[:]),
self.dbAccess, self.dbAccess,
self.unsyncedKeys, self.store, self.unsyncedKeys, self.store,
self.syncParams, state, self.syncParams, state, func() bool { return self.syncEnabled },
) )
if err != nil { if err != nil {
return self.protoError(ErrSync, "%v", err) return self.protoError(ErrSync, "%v", err)
@ -448,8 +448,9 @@ func (self *bzz) store(req *storeRequestMsgData) error {
} }
func (self *bzz) syncRequest() error { func (self *bzz) syncRequest() error {
req := &syncRequestMsgData{ req := &syncRequestMsgData{}
SyncState: self.syncState, if self.hive.syncEnabled {
req.SyncState = self.syncState
} }
return self.send(syncRequestMsg, req) return self.send(syncRequestMsg, req)
} }

View file

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"github.com/ethereum/go-ethereum/common/kademlia"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/swarm/storage" "github.com/ethereum/go-ethereum/swarm/storage"
@ -133,6 +132,7 @@ func NewSyncParams(bzzdir string) *SyncParams {
// syncer is the agent that manages content distribution/storage replication/chunk storeRequest forwarding // syncer is the agent that manages content distribution/storage replication/chunk storeRequest forwarding
type syncer struct { type syncer struct {
*SyncParams // sync parameters *SyncParams // sync parameters
syncF func() bool // if syncing is needed
key storage.Key // remote peers address key key storage.Key // remote peers address key
state *syncState // sync state for our dbStore state *syncState // sync state for our dbStore
syncStates chan *syncState // different stages of sync syncStates chan *syncState // different stages of sync
@ -165,6 +165,7 @@ func newSyncer(
store func(*storeRequestMsgData) error, store func(*storeRequestMsgData) error,
params *SyncParams, params *SyncParams,
state *syncState, state *syncState,
syncF func() bool,
) (*syncer, error) { ) (*syncer, error) {
syncBufferSize := params.SyncBufferSize syncBufferSize := params.SyncBufferSize
@ -172,6 +173,7 @@ func newSyncer(
dbBatchSize := params.RequestDbBatchSize dbBatchSize := params.RequestDbBatchSize
self := &syncer{ self := &syncer{
syncF: syncF,
key: remotekey, key: remotekey,
dbAccess: dbAccess, dbAccess: dbAccess,
syncStates: make(chan *syncState, 20), syncStates: make(chan *syncState, 20),
@ -191,35 +193,19 @@ func newSyncer(
// initialise a syncdb instance for each priority queue // initialise a syncdb instance for each priority queue
self.queues[i] = newSyncDb(db, remotekey, uint(i), syncBufferSize, dbBatchSize, self.deliver(uint(i))) self.queues[i] = newSyncDb(db, remotekey, uint(i), syncBufferSize, dbBatchSize, self.deliver(uint(i)))
} }
self.state = state
glog.V(logger.Info).Infof("[BZZ] syncer started: %v", state) glog.V(logger.Info).Infof("[BZZ] syncer started: %v", state)
// launch chunk delivery service // launch chunk delivery service
go self.syncDeliveries() go self.syncDeliveries()
// launch sync task manager // launch sync task manager
go self.sync() if self.syncF() {
go self.sync()
}
// process unsynced keys to broadcast // process unsynced keys to broadcast
go self.syncUnsyncedKeys() go self.syncUnsyncedKeys()
return self, nil return self, nil
} }
// newSyncState returns a default sync state given local and remote
// addresses and db count
func newSyncState(start, stop kademlia.Address, count uint64) *syncState {
// -> (] keyrange for db iterator -- interval open from the left
// storage count range --- interval open from the right
return &syncState{
DbSyncState: &storage.DbSyncState{
Start: storage.Key(start[:]),
Stop: storage.Key(stop[:]),
First: 0,
Last: count,
},
SessionAt: count,
synced: make(chan bool),
}
}
// metadata serialisation // metadata serialisation
func encodeSync(state *syncState) (*json.RawMessage, error) { func encodeSync(state *syncState) (*json.RawMessage, error) {
data, err := json.MarshalIndent(state, "", " ") data, err := json.MarshalIndent(state, "", " ")
@ -238,7 +224,7 @@ func decodeSync(meta *json.RawMessage) (*syncState, error) {
if len(data) == 0 { if len(data) == 0 {
return nil, fmt.Errorf("unable to deserialise sync state from <nil>") return nil, fmt.Errorf("unable to deserialise sync state from <nil>")
} }
state := newSyncState(kademlia.Address{}, kademlia.Address{}, 0) state := &syncState{}
err := json.Unmarshal(data, state) err := json.Unmarshal(data, state)
return state, err return state, err
} }
@ -625,10 +611,12 @@ func (self *syncer) addRequest(req interface{}, ty int) {
priority := self.SyncPriorities[ty] priority := self.SyncPriorities[ty]
// sync mode for this type ON // sync mode for this type ON
if self.SyncModes[ty] { if self.syncF() || ty == DeliverReq {
self.addKey(req, priority, self.quit) if self.SyncModes[ty] {
} else { self.addKey(req, priority, self.quit)
self.addDelivery(req, priority, self.quit) } else {
self.addDelivery(req, priority, self.quit)
}
} }
} }

View file

@ -254,7 +254,7 @@ func (self *SwapParams) newChequebookFromContract(path string, backend chequeboo
} }
chbookpath := filepath.Join(path, "chequebooks", hexkey+".json") chbookpath := filepath.Join(path, "chequebooks", hexkey+".json")
self.chbook, err = chequebook.LoadChequebook(chbookpath, self.privateKey, backend) self.chbook, err = chequebook.LoadChequebook(chbookpath, self.privateKey, backend, true)
if err != nil { if err != nil {
self.chbook, err = chequebook.NewChequebook(chbookpath, self.Contract, self.privateKey, backend) self.chbook, err = chequebook.NewChequebook(chbookpath, self.Contract, self.privateKey, backend)

View file

@ -43,7 +43,7 @@ type Swarm struct {
// creates a new swarm service instance // creates a new swarm service instance
// implements node.Service // implements node.Service
func NewSwarm(stack *node.ServiceContext, config *api.Config, swapEnabled bool) (self *Swarm, err error) { func NewSwarm(stack *node.ServiceContext, config *api.Config, swapEnabled, syncEnabled bool) (self *Swarm, err error) {
if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) { if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) {
return nil, fmt.Errorf("empty public key") return nil, fmt.Errorf("empty public key")
@ -77,6 +77,8 @@ func NewSwarm(stack *node.ServiceContext, config *api.Config, swapEnabled bool)
self.hive = network.NewHive( self.hive = network.NewHive(
common.HexToHash(self.config.BzzKey), // key to hive (kademlia base address) common.HexToHash(self.config.BzzKey), // key to hive (kademlia base address)
config.HiveParams, // configuration parameters config.HiveParams, // configuration parameters
swapEnabled, // SWAP enabled
syncEnabled, // syncronisation enabled
) )
glog.V(logger.Debug).Infof("[BZZ] Set up swarm network with Kademlia hive") glog.V(logger.Debug).Infof("[BZZ] Set up swarm network with Kademlia hive")
@ -110,12 +112,15 @@ func NewSwarm(stack *node.ServiceContext, config *api.Config, swapEnabled bool)
glog.V(logger.Debug).Infof("[BZZ] -> Web3 virtual server API") glog.V(logger.Debug).Infof("[BZZ] -> Web3 virtual server API")
// set chequebook // set chequebook
if swapEnabled { if swapEnabled {
err = self.SetChequebook(backend) err = self.SetChequebook(backend)
if err != nil { if err != nil {
return nil, fmt.Errorf("Unable to set chequebook for SWAP: %v", err) return nil, fmt.Errorf("Unable to set chequebook for SWAP: %v", err)
} }
glog.V(logger.Debug).Infof("[BZZ] -> cheque book for SWAP") glog.V(logger.Debug).Infof("[BZZ] -> cheque book for SWAP: %v", self.config.Swap.Chequebook())
} else {
glog.V(logger.Debug).Infof("[BZZ] SWAP disabled: no cheque book set")
} }
return self, nil return self, nil
} }
@ -206,7 +211,7 @@ func (self *Swarm) APIs() []rpc.API {
rpc.API{Namespace, Version, api.NewControl(self.api, self.hive), false}, rpc.API{Namespace, Version, api.NewControl(self.api, self.hive), false},
// rpc.API{Namespace, Version, api.NewAdmin(self), false}, // rpc.API{Namespace, Version, api.NewAdmin(self), false},
// TODO: external apis exposed // TODO: external apis exposed
rpc.API{"chequebook", chequebook.Version, chequebook.NewApi(self.config.Swap.Chequebook()), true}, rpc.API{"chequebook", chequebook.Version, chequebook.NewApi(self.config.Swap.Chequebook), true},
} }
} }

29
swarm/test/swap/00.sh Normal file
View file

@ -0,0 +1,29 @@
#!/bin/bash
echo "TEST swap/00:"
echo " two nodes that do not sync and do not have any funds"
echo " cannot retrieve content from each other"
dir=`dirname $0`
source $dir/../../cmd/swarm/test.sh
FILE_00=/tmp/1K.0
randomfile 1 > $FILE_00
ls -l $FILE_00
mininginterval=50
key=/tmp/key
swarm init 2
sleep $wait
swarm attach 00 -exec "'bzz.noSync(true)'"
swarm attach 01 -exec "'bzz.noSync(true)'"
swarm up 00 $FILE_00|tail -n1 > $key
swarm needs 00 $key $FILE_00
swarm needs 01 $key $FILE_00 | tail -1| grep -ql "PASS" && echo "FAIL" || echo "PASS <3"
FILE_01=/tmp/1K.1
randomfile 1 > $FILE_01
swarm up 01 $FILE_01|tail -1 > $key
swarm needs 01 $key $FILE_01
swarm needs 00 $key $FILE_01 | tail -1| grep -ql "PASS" && echo "FAIL" || echo "PASS <3"
swarm stop all

62
swarm/test/swap/01.sh Normal file
View file

@ -0,0 +1,62 @@
echo "TEST swap/01:"
echo " two nodes that do not sync but have enough funds"
echo " after syncing, can retrieve content from each other"
dir=`dirname $0`
source $dir/../../cmd/swarm/test.sh
file=/tmp/test.file
mininginterval=120
key=/tmp/key
logargs="--verbosity=0 --vmodule='miner/*=0,swarm/services/*=6,swarm/swarm=6,common/chequebook/*=6,swarm/network/depo=6,swarm/network/forwarding=6'"
# logargs='--verbosity=6'
# swarm init 2 --mine --bzznosync $logargs
# swarm stop all
swarm start 00 --mine --bzznosync $logargs
swarm start 01 --mine --bzznosync $logargs
# echo "Mining some ether..."
# sleep $mininginterval
swarm attach 00 -exec "'eth.getBalance(eth.accounts[0])'"
swarm attach 01 -exec "'eth.getBalance(eth.accounts[0])'"
swarm attach 00 -exec "'eth.getBalance(bzz.info().Swap.Contract)'"
swarm attach 01 -exec "'eth.getBalance(bzz.info().Swap.Contract)'"
swarm attach 00 -exec "'chequebook.balance'"
swarm attach 01 -exec "'chequebook.balance'"
randomfile 10 > $file
swarm up 00 $file|tail -n1 > $key
swarm needs 01 $key $file
swarm info 01
swarm attach 00 -exec "'eth.getBalance(eth.accounts[0])'"
swarm attach 01 -exec "'eth.getBalance(eth.accounts[0])'"
swarm attach 00 -exec "'eth.getBalance(bzz.info().Swap.Contract)'"
swarm attach 01 -exec "'eth.getBalance(bzz.info().Swap.Contract)'"
swarm attach 00 -exec "'chequebook.balance'"
swarm attach 01 -exec "'chequebook.balance'"
# randomfile 20 > $file
# swarm up 01 $file|tail -n1 > $key
# swarm needs 00 $key $file
# swarm attach 00 -exec "'eth.getBalance(eth.accounts[0])'"
# swarm attach 01 -exec "'eth.getBalance(eth.accounts[0])'"
# swarm attach 00 -exec "'eth.getBalance(bzz.info().Swap.Contract)'"
# swarm attach 01 -exec "'eth.getBalance(bzz.info().Swap.Contract)'"
# swarm attach 00 -exec "'chequebook.balance'"
# swarm attach 01 -exec "'chequebook.balance'"
# randomfile 10 > $file
# swarm up 00 $file|tail -n1 > $key
# swarm needs 01 $key $file | tail -1| grep -ql "PASS" && echo "FAIL" || echo "PASS <3"
# randomfile 10 > $file
# swarm up 01 $file|tail -n1 > $key
# swarm needs 00 $key $file | tail -1| grep -ql "PASS" && echo "FAIL" || echo "PASS <3"
swarm stop all