Skip to content
Snippets Groups Projects
Unverified Commit 8bdd0043 authored by jkrvivian's avatar jkrvivian
Browse files

feat: Add first value transfer integration test

parent 9039716c
No related branches found
No related tags found
No related merge requests found
Showing with 303 additions and 6 deletions
......@@ -17,6 +17,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/metrics"
"github.com/iotaledger/goshimmer/plugins/portcheck"
"github.com/iotaledger/goshimmer/plugins/profiling"
"github.com/iotaledger/goshimmer/plugins/testsnapshots"
"github.com/iotaledger/goshimmer/plugins/sync"
"github.com/iotaledger/hive.go/node"
......@@ -40,4 +41,5 @@ var PLUGINS = node.Plugins(
metrics.Plugin,
drng.Plugin,
valuetransfers.App,
testsnapshots.Plugin,
)
package testsnapshots
import (
"github.com/iotaledger/goshimmer/dapps/valuetransfers"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
"github.com/iotaledger/hive.go/logger"
"github.com/iotaledger/hive.go/node"
)
const (
// PluginName is the plugin name of the bootstrap plugin.
PluginName = "TestSnapshots"
)
var (
// Plugin is the plugin instance of the bootstrap plugin.
Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
log *logger.Logger
// addresses for snapshots
address0, _ = address.FromBase58("JaMauTaTSVBNc13edCCvBK9fZxZ1KKW5fXegT1B7N9jY")
)
func configure(_ *node.Plugin) {
log = logger.NewLogger(PluginName)
valuetransfers.Tangle.LoadSnapshot(map[transaction.ID]map[address.Address][]*balance.Balance{
transaction.GenesisID: {
address0: []*balance.Balance{
balance.New(balance.ColorIOTA, 10000000),
},
},
})
log.Infof("load snapshots to tangle")
}
func run(_ *node.Plugin) {}
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"strings"
"time"
"github.com/docker/docker/api/types"
......@@ -83,10 +84,14 @@ func (d *DockerContainer) CreateGoShimmerPeer(config GoShimmerConfig) error {
"--logger.level=debug",
fmt.Sprintf("--node.disablePlugins=%s", config.DisabledPlugins),
fmt.Sprintf("--node.enablePlugins=%s", func() string {
var plugins []string
if config.Bootstrap {
return "Bootstrap"
plugins = append(plugins, "Bootstrap")
}
return ""
if config.Faucet {
plugins = append(plugins, "faucet")
}
return strings.Join(plugins[:], ",")
}()),
fmt.Sprintf("--bootstrap.initialIssuance.timePeriodSec=%d", config.BootstrapInitialIssuanceTimePeriodSec),
"--webapi.bindAddress=0.0.0.0:8080",
......
......@@ -55,7 +55,7 @@ func (n *DRNGNetwork) CreatePeer(c GoShimmerConfig, publicKey hive_ed25519.Publi
return nil, err
}
peer, err := newPeer(name, identity.New(publicKey), container, n.network)
peer, err := newPeer(name, identity.New(publicKey), container, nil, n.network)
if err != nil {
return nil, err
}
......
......@@ -84,6 +84,7 @@ func (f *Framework) CreateNetwork(name string, peers int, minimumNeighbors int,
config := GoShimmerConfig{
Bootstrap: i == 0,
BootstrapInitialIssuanceTimePeriodSec: bootstrapInitialIssuanceTimePeriodSec,
Faucet: i == 0,
}
if _, err = network.CreatePeer(config); err != nil {
return nil, err
......
......@@ -11,6 +11,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/wallet"
hive_ed25519 "github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/identity"
)
......@@ -102,6 +103,14 @@ func (n *Network) CreatePeer(c GoShimmerConfig) (*Peer, error) {
config.EntryNodePublicKey = n.entryNodePublicKey()
config.DisabledPlugins = disabledPluginsPeer
// create wallet
var nodeWallet *wallet.Wallet
if c.Faucet == true {
nodeWallet = wallet.New(faucetSeed)
} else {
nodeWallet = wallet.New()
}
// create Docker container
container := NewDockerContainer(n.dockerClient)
err = container.CreateGoShimmerPeer(config)
......@@ -117,7 +126,7 @@ func (n *Network) CreatePeer(c GoShimmerConfig) (*Peer, error) {
return nil, err
}
peer, err := newPeer(name, identity.New(publicKey), container, n)
peer, err := newPeer(name, identity.New(publicKey), container, nodeWallet, n)
if err != nil {
return nil, err
}
......
package framework
import (
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/wallet"
)
const (
autopeeringMaxTries = 50
......@@ -13,7 +17,7 @@ const (
logsDir = "/tmp/logs/"
disabledPluginsEntryNode = "portcheck,dashboard,analysis-client,profiling,gossip,drng,issuer,sync,metrics,valuetransfers,messagelayer,webapi,webapibroadcastdataendpoint,webapifindtransactionhashesendpoint,webapigetneighborsendpoint,webapigettransactionobjectsbyhashendpoint,webapigettransactiontrytesbyhashendpoint"
disabledPluginsEntryNode = "portcheck,dashboard,analysis-client,profiling,gossip,drng,issuer,sync,metrics,valuetransfers,snapshots,messagelayer,webapi,webapibroadcastdataendpoint,webapifindtransactionhashesendpoint,webapigetneighborsendpoint,webapigettransactionobjectsbyhashendpoint,webapigettransactiontrytesbyhashendpoint"
disabledPluginsPeer = "portcheck,dashboard,analysis-client,profiling"
dockerLogsPrefixLen = 8
......@@ -21,6 +25,13 @@ const (
dkgMaxTries = 50
exitStatusSuccessful = 0
SnapShotFirstAddress = "JaMauTaTSVBNc13edCCvBK9fZxZ1KKW5fXegT1B7N9jY"
)
var (
faucetSeed = []byte{251, 163, 190, 98, 92, 82, 164, 79, 74, 48, 203, 162, 247, 119, 140, 76, 33, 100, 148, 204, 244, 248, 232, 18,
132, 217, 85, 31, 246, 83, 193, 193}
)
// GoShimmerConfig defines the config of a GoShimmer node.
......@@ -38,6 +49,10 @@ type GoShimmerConfig struct {
DRNGDistKey string
DRNGInstance int
DRNGThreshold int
Faucet bool
Wallet *wallet.Wallet
}
// NetworkConfig defines the config of a GoShimmer Docker network.
......
......@@ -6,6 +6,7 @@ import (
"time"
"github.com/iotaledger/goshimmer/client"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/wallet"
"github.com/iotaledger/goshimmer/plugins/webapi/autopeering"
"github.com/iotaledger/hive.go/identity"
)
......@@ -24,13 +25,16 @@ type Peer struct {
// the DockerContainer that this peer is running in
*DockerContainer
// Wallet
*wallet.Wallet
chosen []autopeering.Neighbor
accepted []autopeering.Neighbor
}
// newPeer creates a new instance of Peer with the given information.
// dockerContainer needs to be started in order to determine the container's (and therefore peer's) IP correctly.
func newPeer(name string, identity *identity.Identity, dockerContainer *DockerContainer, network *Network) (*Peer, error) {
func newPeer(name string, identity *identity.Identity, dockerContainer *DockerContainer, wallet *wallet.Wallet, network *Network) (*Peer, error) {
// after container is started we can get its IP
ip, err := dockerContainer.IP(network.name)
if err != nil {
......@@ -43,6 +47,7 @@ func newPeer(name string, identity *identity.Identity, dockerContainer *DockerCo
Identity: identity,
GoShimmerAPI: client.NewGoShimmerAPI(getWebAPIBaseURL(name), http.Client{Timeout: 30 * time.Second}),
DockerContainer: dockerContainer,
Wallet: wallet,
}, nil
}
......
......@@ -4,7 +4,12 @@ import (
"fmt"
"math/rand"
"testing"
"time"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address/signaturescheme"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
"github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload"
"github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework"
"github.com/stretchr/testify/assert"
......@@ -95,6 +100,143 @@ func CheckForMessageIds(t *testing.T, peers []*framework.Peer, ids map[string]Da
}
}
// SendValueMessage sends a value message on a given peer and returns the transaction ID.
func SendValueMessagesOnFaucet(t *testing.T, peers []*framework.Peer) (txId string, addrBalance map[string]int64) {
faucetPeer := peers[0]
sigScheme := signaturescheme.ED25519(*faucetPeer.Seed().KeyPair(0))
// send the same funds to the original address
remainAddr := faucetPeer.Seed().Address(0)
var sentValue int64 = 0
// prepare inputs
unspentOutputs, err := faucetPeer.GetUnspentOutputs([]string{framework.SnapShotFirstAddress})
require.NoErrorf(t, err, "Could not get unspent outputs on %s", faucetPeer.String())
value := unspentOutputs.UnspentOutputs[0].OutputIDs[0].Balances[0].Value
out, err := transaction.OutputIDFromBase58(unspentOutputs.UnspentOutputs[0].OutputIDs[0].ID)
require.NoErrorf(t, err, "Invalid unspent outputs ID on %s", faucetPeer.String())
inputs := transaction.NewInputs([]transaction.OutputID{out}...)
// prepare outputs
outmap := map[address.Address][]*balance.Balance{}
addrBalance = make(map[string]int64)
// send funds to other peers, skip faucet node
for i := 1; i < len(peers); i++ {
addr := peers[i].Seed().Address(0)
// set balances
balances := []*balance.Balance{balance.New(balance.ColorIOTA, 100)}
outmap[addr] = balances
sentValue += 100
// set return map
addrBalance[addr.String()] = 100
}
outputs := transaction.NewOutputs(outmap)
// handle remain address
outputs.Add(remainAddr, []*balance.Balance{balance.New(balance.ColorIOTA, value-sentValue)})
addrBalance[remainAddr.String()] = value - sentValue
// sign transaction
txn := transaction.New(inputs, outputs).Sign(sigScheme)
// send transaction
txId, err = faucetPeer.SendTransaction(txn.Bytes())
require.NoErrorf(t, err, "Could not send transaction on %s", faucetPeer.String())
return
}
// SendDataMessagesOnRandomPeer sends data messages on a random peer and saves the sent message to a map.
func SendValueMessagesOnRandomPeer(t *testing.T, peers []*framework.Peer, addrBalance map[string]int64, numMessages int) {
addrMap := make(map[int]string)
for i, p := range peers {
addrMap[i] = p.Seed().Address(0).String()
}
for i := 0; i < numMessages; i++ {
from := rand.Intn(len(peers))
to := rand.Intn(len(peers))
sentValue := SendValueMessages(t, peers[from], peers[to], addrBalance)
// update balance
addrBalance[addrMap[from]] -= sentValue
addrBalance[addrMap[to]] += sentValue
if sentValue == 0 {
i--
}
time.Sleep(5 * time.Second)
}
return
}
// SendValueMessage sends a value message from and to a given peer and returns the transaction ID.
// for testing convenience, the same addresses are used in each round
func SendValueMessages(t *testing.T, from *framework.Peer, to *framework.Peer, addrBalance map[string]int64) (sent int64) {
sigScheme := signaturescheme.ED25519(*from.Seed().KeyPair(0))
inputAddr := from.Seed().Address(0)
outputAddr := to.Seed().Address(0)
// skip if from peer has no balance
if addrBalance[inputAddr.String()] == 0 {
return 0
}
// prepare inputs
resp, err := from.GetUnspentOutputs([]string{inputAddr.String()})
require.NoErrorf(t, err, "Could not get unspent outputs on %s", from.String())
value := resp.UnspentOutputs[0].OutputIDs[0].Balances[0].Value
out, err := transaction.OutputIDFromBase58(resp.UnspentOutputs[0].OutputIDs[0].ID)
require.NoErrorf(t, err, "Invalid unspent outputs ID on %s", from.String())
inputs := transaction.NewInputs([]transaction.OutputID{out}...)
// prepare outputs
outmap := map[address.Address][]*balance.Balance{}
// set balances
balances := []*balance.Balance{balance.New(balance.ColorIOTA, value)}
outmap[outputAddr] = balances
outputs := transaction.NewOutputs(outmap)
// sign transaction
txn := transaction.New(inputs, outputs).Sign(sigScheme)
// send transaction
_, err = from.SendTransaction(txn.Bytes())
require.NoErrorf(t, err, "Could not send transaction on %s", from.String())
return value
}
// CheckBalances performs checks to make sure that all peers have the same ledger state.
func CheckBalances(t *testing.T, peers []*framework.Peer, addrBalance map[string]int64, checkSynchronized bool) {
for _, peer := range peers {
if checkSynchronized {
// check that the peer sees itself as synchronized
info, err := peer.Info()
require.NoError(t, err)
require.True(t, info.Synced)
}
for addr, b := range addrBalance {
var iotas int64 = 0
resp, err := peer.GetUnspentOutputs([]string{addr})
require.NoError(t, err)
assert.Equal(t, addr, resp.UnspentOutputs[0].Address)
// calculate the total iotas of an address
for _, unspents := range resp.UnspentOutputs[0].OutputIDs {
iotas += unspents.Balances[0].Value
assert.Equal(t, balance.ColorIOTA.String(), unspents.Balances[0].Color)
}
assert.Equal(t, b, iotas)
}
}
}
// ShutdownNetwork shuts down the network and reports errors.
func ShutdownNetwork(t *testing.T, n Shutdowner) {
err := n.Shutdown()
......
package autopeering
import (
"os"
"testing"
"github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework"
)
var f *framework.Framework
// TestMain gets called by the test utility and is executed before any other test in this package.
// It is therefore used to initialize the integration testing framework.
func TestMain(m *testing.M) {
var err error
f, err = framework.Instance()
if err != nil {
panic(err)
}
// call the tests
os.Exit(m.Run())
}
package autopeering
import (
"testing"
"time"
"github.com/iotaledger/goshimmer/tools/integration-tests/tester/tests"
"github.com/stretchr/testify/require"
)
// TestPersistence issues messages on random peers, restarts them and checks for persistence after restart.
func TestPersistence(t *testing.T) {
n, err := f.CreateNetwork("value_TestPersistence", 4, 2)
require.NoError(t, err)
defer tests.ShutdownNetwork(t, n)
// wait for peers to change their state to synchronized
time.Sleep(5 * time.Second)
// master node issue transaction to all peers in the network
_, addrBalance := tests.SendValueMessagesOnFaucet(t, n.Peers())
// wait for messages to be gossiped
time.Sleep(10 * time.Second)
// 2. check whether all issued messages are available on all nodes
tests.CheckBalances(t, n.Peers(), addrBalance, true)
// send value message randomly
tests.SendValueMessagesOnRandomPeer(t, n.Peers(), addrBalance, 10)
// wait for messages to be gossiped
time.Sleep(10 * time.Second)
// check whether all issued messages are available on all nodes
tests.CheckBalances(t, n.Peers(), addrBalance, true)
// 3. stop all nodes
for _, peer := range n.Peers() {
err = peer.Stop()
require.NoError(t, err)
}
// 4. start all nodes
for _, peer := range n.Peers() {
err = peer.Start()
require.NoError(t, err)
}
// wait for peers to start
time.Sleep(10 * time.Second)
// 5. check whether all issued messages are persistently available on all nodes
tests.CheckBalances(t, n.Peers(), addrBalance, true)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment