transaction_test.go 6.61 KiB
package transaction
import (
"bytes"
"strings"
"testing"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/stretchr/testify/assert"
"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"
)
func TestEmptyDataPayload(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
}
func TestEmptyDataPayloadString(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.True(t, check)
t.Logf("%s", tx.String())
}
func TestShortDataPayload(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
dpBack := tx.GetDataPayload()
assert.Equal(t, true, bytes.Equal(dpBack, dataPayload))
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
// corrupt data payload bytes
// reset essence to force recalculation
tx.essenceBytes = nil
dataPayload[2] = '?'
err = tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
// expect signature is not valid
check = tx.SignaturesValid()
assert.Equal(t, false, check)
}
func TestTooLongDataPayload(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte(strings.Repeat("1", MaxDataPayloadSize+1))
err := tx.SetDataPayload(dataPayload)
assert.Error(t, err)
}
func TestMarshalingEmptyDataPayload(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
v := tx.ObjectStorageValue()
tx1 := Transaction{}
_, err := tx1.UnmarshalObjectStorageValue(v)
assert.NoError(t, err)
assert.Equal(t, true, tx1.SignaturesValid())
assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes()))
}
func TestMarshalingDataPayload(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
v := tx.ObjectStorageValue()
tx1 := Transaction{}
_, err = tx1.UnmarshalObjectStorageValue(v)
assert.NoError(t, err)
assert.Equal(t, true, tx1.SignaturesValid())
assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes()))
}
func TestPutSignatureValid(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
signature := sigScheme.Sign(tx.EssenceBytes())
assert.Equal(t, signature.IsValid(tx.EssenceBytes()), true)
err = tx.PutSignature(signature)
assert.NoError(t, err)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
}
func TestPutSignatureInvalid(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
signatureValid := sigScheme.Sign(tx.EssenceBytes())
assert.Equal(t, true, signatureValid.IsValid(tx.EssenceBytes()))
sigBytes := make([]byte, len(signatureValid.Bytes()))
copy(sigBytes, signatureValid.Bytes())
// inverse last byte --> corrupt the signatureValid
sigBytes[len(sigBytes)-1] = ^sigBytes[len(sigBytes)-1]
sigCorrupted, consumed, err := signaturescheme.BLSSignatureFromBytes(sigBytes)
assert.NoError(t, err)
assert.Equal(t, consumed, len(sigBytes))
assert.Equal(t, false, sigCorrupted.IsValid(tx.EssenceBytes()))
err = tx.PutSignature(sigCorrupted)
// error expected
assert.Error(t, err)
// 0 signatures is not valid
assert.Equal(t, true, !tx.SignaturesValid())
err = tx.PutSignature(signatureValid)
// no error expected
assert.NoError(t, err)
// valid signatures expected
assert.Equal(t, true, tx.SignaturesValid())
}
func TestInputCounts(t *testing.T) {
tx1 := createTransaction(MaxTransactionInputCount + 1, 1)
assert.False(t, tx1.InputsCountValid())
tx2 := createTransaction(MaxTransactionInputCount - 1, 1)
assert.True(t, tx2.InputsCountValid())
}
func createTransaction(inputCount int, outputCount int) *Transaction {
outputIds := make([]OutputID, 0)
for i := 0; i < inputCount; i++ {
outputIds = append(outputIds, NewOutputID(address.Random(), RandomID()))
}
inputs := NewInputs(outputIds...)
bal := balance.New(balance.ColorIOTA, 1)
outputMap := make(map[address.Address][]*balance.Balance)
for i := 0; i < outputCount; i++ {
outputMap[address.Random()] = []*balance.Balance{bal}
}
outputs := NewOutputs(outputMap)
return New(inputs, outputs)
}