From 0f53d5b768c7d1762ee933935c43bc9b32681f71 Mon Sep 17 00:00:00 2001
From: Wolfgang Welz <welzwo@gmail.com>
Date: Sat, 6 Jul 2019 14:28:08 +0200
Subject: [PATCH] Add simple validator plugin to validate bundle signatures

---
 plugins/validator/plugin.go | 90 +++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 plugins/validator/plugin.go

diff --git a/plugins/validator/plugin.go b/plugins/validator/plugin.go
new file mode 100644
index 00000000..9b898d79
--- /dev/null
+++ b/plugins/validator/plugin.go
@@ -0,0 +1,90 @@
+package validator
+
+import (
+	"github.com/iotaledger/goshimmer/packages/events"
+	"github.com/iotaledger/goshimmer/packages/model/bundle"
+	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
+	"github.com/iotaledger/goshimmer/packages/node"
+	"github.com/iotaledger/goshimmer/plugins/bundleprocessor"
+	"github.com/iotaledger/iota.go/address"
+	. "github.com/iotaledger/iota.go/consts"
+	"github.com/iotaledger/iota.go/signing"
+	. "github.com/iotaledger/iota.go/trinary"
+)
+
+var PLUGIN = node.NewPlugin("Validator", configure, run)
+
+// Creates bundle signature fragments and the corresponding address to validate against.
+// Each signature fragment after the first must go into its own meta transaction with value = 0.
+func demoSign(seed Trytes, index uint64, sec SecurityLevel, bundleHash Hash) (Hash, []Trytes) {
+
+	addr, _ := address.GenerateAddress(seed, index, sec)
+
+	// compute seed based on address index
+	subseed, _ := signing.Subseed(seed, index)
+	// generate the private key
+	prvKey, _ := signing.Key(subseed, sec)
+
+	normalizedBundleHash := signing.NormalizedBundleHash(bundleHash)
+
+	signatureFragments := make([]Trytes, sec)
+	for i := 0; i < int(sec); i++ {
+		// each security level signs one third of the (normalized) bundle hash
+		signedFragTrits, _ := signing.SignatureFragment(
+			normalizedBundleHash[i*HashTrytesSize/3:(i+1)*HashTrytesSize/3],
+			prvKey[i*KeyFragmentLength:(i+1)*KeyFragmentLength],
+		)
+		signatureFragments[i] = MustTritsToTrytes(signedFragTrits)
+	}
+
+	return addr, signatureFragments
+}
+
+func validateSignatures(bundleHash Hash, txs []*value_transaction.ValueTransaction) (bool, error) {
+	for i, tx := range txs {
+		// ignore all non-input transactions
+		if tx.GetValue() >= 0 {
+			continue
+		}
+
+		address := tx.GetAddress()
+
+		// it is unknown how many fragments there will be
+		fragments := []Trytes{tx.GetSignatureMessageFragment()}
+
+		// each consecutive meta transaction with the same address contains another signature fragment
+		for j := i; j < len(txs)-1; j++ {
+			otherTx := txs[j+1]
+			if otherTx.GetValue() != 0 || otherTx.GetAddress() != address {
+				break
+			}
+
+			fragments = append(fragments, otherTx.GetSignatureMessageFragment())
+		}
+
+		// validate all the fragments against the address using Kerl
+		valid, err := signing.ValidateSignatures(address, fragments, bundleHash, signing.NewKerl)
+		if err != nil {
+			return false, err
+		}
+		if !valid {
+			return false, nil
+		}
+	}
+
+	return true, nil
+}
+
+func configure(plugin *node.Plugin) {
+
+	bundleprocessor.Events.ValueBundleReceived.Attach(events.NewClosure(func(b *bundle.Bundle, txs []*value_transaction.ValueTransaction) {
+		// signature are verified against the bundle hash
+		valid, _ := validateSignatures(b.GetBundleEssenceHash(), txs)
+		if !valid {
+			plugin.LogFailure("Invalid signature")
+		}
+	}))
+}
+
+func run(*node.Plugin) {
+}
-- 
GitLab