valuebundleprocessor.go 2.73 KiB
package bundleprocessor
import (
"github.com/iotaledger/goshimmer/packages/curl"
"github.com/iotaledger/goshimmer/packages/errors"
"github.com/iotaledger/goshimmer/packages/model/bundle"
"github.com/iotaledger/goshimmer/packages/model/value_transaction"
"github.com/iotaledger/goshimmer/packages/workerpool"
"github.com/iotaledger/iota.go/signing"
"github.com/iotaledger/iota.go/trinary"
)
var valueBundleProcessorWorkerPool = workerpool.New(func(task workerpool.Task) {
if err := ProcessSolidValueBundle(task.Param(0).(*bundle.Bundle), task.Param(1).([]*value_transaction.ValueTransaction)); err != nil {
Events.Error.Trigger(err)
}
task.Return(nil)
}, workerpool.WorkerCount(WORKER_COUNT), workerpool.QueueSize(2*WORKER_COUNT))
func ProcessSolidValueBundle(bundle *bundle.Bundle, bundleTransactions []*value_transaction.ValueTransaction) errors.IdentifiableError {
bundle.SetBundleEssenceHash(CalculateBundleHash(bundleTransactions))
Events.BundleSolid.Trigger(bundle, bundleTransactions)
return nil
}
func CalculateBundleHash(transactions []*value_transaction.ValueTransaction) trinary.Trytes {
var lastInputAddress trinary.Trytes
var concatenatedBundleEssences = make(trinary.Trits, len(transactions)*value_transaction.BUNDLE_ESSENCE_SIZE)
for i, bundleTransaction := range transactions {
if bundleTransaction.GetValue() <= 0 {
lastInputAddress = bundleTransaction.GetAddress()
}
copy(concatenatedBundleEssences[value_transaction.BUNDLE_ESSENCE_SIZE*i:value_transaction.BUNDLE_ESSENCE_SIZE*(i+1)], bundleTransaction.GetBundleEssence(lastInputAddress != bundleTransaction.GetAddress()))
}
var bundleHash = make(trinary.Trits, 243)
hasher := curl.NewCurl(243, 81)
hasher.Absorb(concatenatedBundleEssences, 0, len(concatenatedBundleEssences))
hasher.Squeeze(bundleHash, 0, 243)
return trinary.MustTritsToTrytes(bundleHash)
}
func ValidateSignatures(bundleHash trinary.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 := []trinary.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)
if err != nil {
return false, err
}
if !valid {
return false, nil
}
}
return true, nil
}