func processProof(packed []byte) error {
	if 0 == len(packed) {
		return fault.MissingParameters
	}
	if !mode.Is(mode.Normal) {
		return fault.NotAvailableDuringSynchronise
	}
	var payId pay.PayId
	nonceLength := len(packed) - len(payId)  
	if nonceLength < payment.MinimumNonceLength || nonceLength > payment.MaximumNonceLength {
		return fault.InvalidNonce
	}
	copy(payId[:], packed[:len(payId)])
	nonce := packed[len(payId):]
	rsvr := reservoir.Get()
	status := rsvr.TryProof(payId, nonce)
	if reservoir.TrackingAccepted != status {
		return fault.PayIdAlreadyUsed
	}
	return nil
}
process proof block
package peer
import (
	"encoding/binary"
	"github.com/bitmark-inc/bitmarkd/announce"
	"github.com/bitmark-inc/bitmarkd/asset"
	"github.com/bitmark-inc/bitmarkd/fault"
	"github.com/bitmark-inc/bitmarkd/messagebus"
	"github.com/bitmark-inc/bitmarkd/mode"
	"github.com/bitmark-inc/bitmarkd/pay"
	"github.com/bitmark-inc/bitmarkd/payment"
	"github.com/bitmark-inc/bitmarkd/reservoir"
	"github.com/bitmark-inc/bitmarkd/storage"
	"github.com/bitmark-inc/bitmarkd/transactionrecord"
	"github.com/bitmark-inc/logger"
)
func processSubscription(log *logger.L, command string, arguments [][]byte) {
	dataLength := len(arguments)
	switch command {
	case "block":
		if dataLength < 1 {
			log.Debugf("block with too few data: %d items", dataLength)
			return
		}
		log.Infof("received block: %x", arguments[0])
		if !mode.Is(mode.Normal) {
			err := fault.NotAvailableDuringSynchronise
			log.Debugf("failed assets: error: %s", err)
		} else {
			messagebus.Bus.Blockstore.Send("remote", arguments[0])
		}
	case "assets":
		if dataLength < 1 {
			log.Debugf("assets with too few data: %d items", dataLength)
			return
		}
		log.Infof("received assets: %x", arguments[0])
		err := processAssets(arguments[0])
		if nil != err {
			log.Debugf("failed assets: error: %s", err)
		} else {
			messagebus.Bus.Broadcast.Send("assets", arguments[0])
		}
	case "issues":
		if dataLength < 1 {
			log.Debugf("issues with too few data: %d items", dataLength)
			return
		}
		log.Infof("received issues: %x", arguments[0])
		err := processIssues(arguments[0])
		if nil != err {
			log.Debugf("failed issues: error: %s", err)
		} else {
			messagebus.Bus.Broadcast.Send("issues", arguments[0])
		}
	case "transfer":
		if dataLength < 1 {
			log.Debugf("transfer with too few data: %d items", dataLength)
			return
		}
		log.Infof("received transfer: %x", arguments[0])
		err := processTransfer(arguments[0])
		if nil != err {
			log.Debugf("failed transfer: error: %s", err)
		} else {
			messagebus.Bus.Broadcast.Send("transfer", arguments[0])
		}
	case "proof":
		if dataLength < 1 {
			log.Debugf("proof with too few data: %d items", dataLength)
			return
		}
		log.Infof("received proof: %x", arguments[0])
		err := processProof(arguments[0])
		if nil != err {
			log.Debugf("failed proof: error: %s", err)
		} else {
			messagebus.Bus.Broadcast.Send("proof", arguments[0])
		}
	case "rpc":
		if dataLength < 3 {
			log.Debugf("rpc with too few data: %d items", dataLength)
			return
		}
		if 8 != len(arguments[2]) {
			log.Debug("rpc with invalid timestamp")
			return
		}
		timestamp := binary.BigEndian.Uint64(arguments[2])
		log.Infof("received rpc: fingerprint: %x  rpc: %x  timestamp: %d", arguments[0], arguments[1], timestamp)
		if announce.AddRPC(arguments[0], arguments[1], timestamp) {
			messagebus.Bus.Broadcast.Send("rpc", arguments[0:3]...)
		}
	case "peer":
		if dataLength < 3 {
			log.Debugf("peer with too few data: %d items", dataLength)
			return
		}
		if 8 != len(arguments[2]) {
			log.Debug("peer with invalid timestamp")
			return
		}
		timestamp := binary.BigEndian.Uint64(arguments[2])
		log.Infof("received peer: %x  listener: %x  timestamp: %d", arguments[0], arguments[1], timestamp)
		if announce.AddPeer(arguments[0], arguments[1], timestamp) {
			messagebus.Bus.Broadcast.Send("peer", arguments[0:3]...)
		}
	default:
		log.Debugf("received unhandled command: %q arguments: %x", command, arguments)
	}
}
func processAssets(packed []byte) error {
	if 0 == len(packed) {
		return fault.MissingParameters
	}
	if !mode.Is(mode.Normal) {
		return fault.NotAvailableDuringSynchronise
	}
	ok := false
	for 0 != len(packed) {
		transaction, n, err := transactionrecord.Packed(packed).Unpack(mode.IsTesting())
		if nil != err {
			return err
		}
		switch tx := transaction.(type) {
		case *transactionrecord.AssetData:
			_, packedAsset, err := asset.Cache(tx, storage.Pool.Assets)
			if nil != err {
				return err
			}
			if nil != packedAsset {
				ok = true
			}
		default:
			return fault.TransactionIsNotAnAsset
		}
		packed = packed[n:]
	}
	if !ok {
		return fault.NoNewTransactions
	}
	return nil
}
func processIssues(packed []byte) error {
	if 0 == len(packed) {
		return fault.MissingParameters
	}
	if !mode.Is(mode.Normal) {
		return fault.NotAvailableDuringSynchronise
	}
	packedIssues := transactionrecord.Packed(packed)
	issueCount := 0  
	issues := make([]*transactionrecord.BitmarkIssue, 0, reservoir.MaximumIssues)
	for 0 != len(packedIssues) {
		transaction, n, err := packedIssues.Unpack(mode.IsTesting())
		if nil != err {
			return err
		}
		switch tx := transaction.(type) {
		case *transactionrecord.BitmarkIssue:
			issues = append(issues, tx)
			issueCount += 1
		default:
			return fault.TransactionIsNotAnIssue
		}
		packedIssues = packedIssues[n:]
	}
	if 0 == len(issues) {
		return fault.MissingParameters
	}
	rsvr := reservoir.Get()
	_, duplicate, err := rsvr.StoreIssues(issues)
	if nil != err {
		return err
	}
	if duplicate {
		return fault.TransactionAlreadyExists
	}
	return nil
}
func processTransfer(packed []byte) error {
	if 0 == len(packed) {
		return fault.MissingParameters
	}
	if !mode.Is(mode.Normal) {
		return fault.NotAvailableDuringSynchronise
	}
	transaction, _, err := transactionrecord.Packed(packed).Unpack(mode.IsTesting())
	if nil != err {
		return err
	}
	duplicate := false
	transfer, ok := transaction.(transactionrecord.BitmarkTransfer)
	rsvr := reservoir.Get()
	if ok {
		_, duplicate, err = rsvr.StoreTransfer(transfer)
	} else {
		switch tx := transaction.(type) {
		case *transactionrecord.ShareGrant:
			_, duplicate, err = rsvr.StoreGrant(tx)
		case *transactionrecord.ShareSwap:
			_, duplicate, err = rsvr.StoreSwap(tx)
		default:
			return fault.TransactionIsNotATransfer
		}
	}
	if nil != err {
		return err
	}
	if duplicate {
		return fault.TransactionAlreadyExists
	}
	return nil
}