From da89a4f5322ca0232ae04459ccbe775952c436d8 Mon Sep 17 00:00:00 2001 From: billfort Date: Mon, 12 Dec 2022 10:21:20 -0700 Subject: [PATCH] Implement txn pool syncing by random address and time window Signed-off-by: billfort --- chain/pool/txpool.go | 26 +- chain/pool/txwithtime.go | 224 ++++++++++ chain/pool/txwithtime_test.go | 408 ++++++++++++++++++ go.mod | 2 + go.sum | 12 + lnode/syncblock.go | 9 + lnode/syncrandaddr.go | 294 +++++++++++++ lnode/synctxnpool.go | 337 +++++++++++++++ pb/nodemessage.pb.go | 776 ++++++++++++++++++++++++---------- pb/nodemessage.proto | 57 +++ 10 files changed, 1929 insertions(+), 216 deletions(-) create mode 100644 chain/pool/txwithtime.go create mode 100644 chain/pool/txwithtime_test.go create mode 100644 lnode/syncrandaddr.go create mode 100644 lnode/synctxnpool.go diff --git a/chain/pool/txpool.go b/chain/pool/txpool.go index 84a2675c0..916d35fd8 100644 --- a/chain/pool/txpool.go +++ b/chain/pool/txpool.go @@ -16,6 +16,7 @@ import ( "github.com/nknorg/nkn/v2/pb" "github.com/nknorg/nkn/v2/transaction" "github.com/nknorg/nkn/v2/util/log" + om "github.com/wk8/go-ordered-map" ) var ( @@ -46,12 +47,20 @@ type TxnPool struct { sync.RWMutex lastDroppedTxn *transaction.Transaction + + // sync txn + lastSyncTime int64 // last sync time in milli-second + twtMap *om.OrderedMap // txn with time ordered map, FIFO txn of last MaxSyncTxnInterval milli-seconds + twtMapMu sync.RWMutex // concurrent mutex for twtMap + twtCount int // counter of twtMap + twtFingerprint []byte // xor of txn hash of twtMap } func NewTxPool() *TxnPool { tp := &TxnPool{ blockValidationState: chain.NewBlockValidationState(), txnCount: 0, + twtMap: om.New(), } go func() { @@ -224,7 +233,8 @@ func (tp *TxnPool) AppendTxnPool(txn *transaction.Transaction) error { return err } - if _, err := list.GetByNonce(txn.UnsignedTx.Nonce); err != nil && list.Full() { + var oldTxn *transaction.Transaction + if oldTxn, err = list.GetByNonce(txn.UnsignedTx.Nonce); err != nil && list.Full() { return errors.New("account txpool full, too many transaction in list") } @@ -243,6 +253,16 @@ func (tp *TxnPool) AppendTxnPool(txn *transaction.Transaction) error { return err } + // 5. sync txn, add to txn with time map + if oldTxn != nil { + oldHash := oldTxn.Hash() + if oldHash.CompareTo(txn.Hash()) != 0 { + tp.replaceTwt(oldTxn, txn) + } + } else { + tp.appendTwt(txn) + } + return nil } @@ -609,6 +629,10 @@ func (tp *TxnPool) removeTransactions(txns []*transaction.Transaction) []*transa func (tp *TxnPool) CleanSubmittedTransactions(txns []*transaction.Transaction) error { txnsRemoved := tp.removeTransactions(txns) + + // sync txn + tp.removeFromTwtMap(txnsRemoved) + tp.blockValidationState.Lock() defer tp.blockValidationState.Unlock() return tp.CleanBlockValidationState(txnsRemoved) diff --git a/chain/pool/txwithtime.go b/chain/pool/txwithtime.go new file mode 100644 index 000000000..dade7a3c1 --- /dev/null +++ b/chain/pool/txwithtime.go @@ -0,0 +1,224 @@ +package pool + +import ( + "fmt" + "time" + + "github.com/nknorg/nkn/v2/common" + "github.com/nknorg/nkn/v2/pb" + "github.com/nknorg/nkn/v2/transaction" +) + +// sync txn +const MaxSyncTxnInterval = 16000 // in milli seconds + +type txnWithTime struct { // abbreviation is twt: txn with time + arriveTime int64 + txn *transaction.Transaction +} + +// xor of byte slices. +// notice!!!, b1 will be modified, b1 is the result. +func xorBytes(b1 []byte, b2 []byte) ([]byte, error) { + if len(b1) != len(b2) { + return nil, fmt.Errorf("Input slices don't have the same length") + } + + for i := 0; i < len(b1); i++ { + b1[i] = b1[i] ^ b2[i] + } + + return b1, nil +} + +// update twtFingerprint +func (tp *TxnPool) updateTwtFingerprint(txnHash common.Uint256) []byte { + + if tp.twtFingerprint == nil { + tp.twtFingerprint = make([]byte, 0, len(txnHash.ToArray())) + tp.twtFingerprint = append(tp.twtFingerprint, txnHash.ToArray()...) + } else { + tp.twtFingerprint, _ = xorBytes(tp.twtFingerprint, txnHash.ToArray()) + } + return tp.twtFingerprint +} + +// when append new txn to pool, we add this txn pointer to txtWithTime map too. +func (tp *TxnPool) appendTwt(txn *transaction.Transaction) *txnWithTime { + + now := time.Now().UnixMilli() + + twt := &txnWithTime{ + arriveTime: now, + txn: txn, + } + + tp.twtMapMu.Lock() + defer tp.twtMapMu.Unlock() + + txnHash := txn.Hash() + _, ok := tp.twtMap.Get(txnHash) + if !ok { + _, present := tp.twtMap.Set(txnHash, twt) + if !present { + tp.updateTwtFingerprint(txnHash) + tp.twtCount++ + } + } + + return twt +} + +// remove a txn from twtMap +func (tp *TxnPool) removeTwt(txnHash common.Uint256) (twt *txnWithTime) { + tp.twtMapMu.Lock() + defer tp.twtMapMu.Unlock() + + v, ok := tp.twtMap.Delete(txnHash) + if ok { + tp.twtCount-- + twt = v.(*txnWithTime) + txnHash := twt.txn.Hash() + tp.updateTwtFingerprint(txnHash) + } + + return +} + +// replace an oldtxn by a new txn in twtMap +func (tp *TxnPool) replaceTwt(oldTxn, newTxn *transaction.Transaction) (twt *txnWithTime) { + if oldTxn == nil || newTxn == nil { + return + } + + tp.removeTwt(oldTxn.Hash()) + tp.appendTwt(newTxn) + + return +} + +// romve expired items from txn with time list +func (tp *TxnPool) RemoveExpiredTwt() (expiredTwt []*txnWithTime) { + + now := time.Now().UnixMilli() + expiredThreshold := now - MaxSyncTxnInterval + + delKeys := make([]interface{}, 0) + + tp.twtMapMu.Lock() + defer tp.twtMapMu.Unlock() + + for pair := tp.twtMap.Oldest(); pair != nil; pair = pair.Next() { + twt := pair.Value.(*txnWithTime) + if twt.arriveTime < expiredThreshold { // expired + delKeys = append(delKeys, pair.Key) + expiredTwt = append(expiredTwt, pair.Value.(*txnWithTime)) + } else { + break + } + } + + for _, key := range delKeys { + tp.twtMap.Delete(key) + tp.twtCount-- + tp.updateTwtFingerprint(key.(common.Uint256)) + } + + return +} + +// remove submitted txns from txn with time map +func (tp *TxnPool) removeFromTwtMap(txnsRemoved []*transaction.Transaction) { + var totalRemoved int = 0 + + tp.twtMapMu.Lock() + defer tp.twtMapMu.Unlock() + + for _, txn := range txnsRemoved { + txnHash := txn.Hash() + _, ok := tp.twtMap.Load(txnHash) + if ok { + tp.twtMap.Delete(txnHash) + tp.updateTwtFingerprint(txnHash) + totalRemoved++ + } + } + tp.twtCount -= totalRemoved + +} + +// get address and nonce from txn with time map +func (tp *TxnPool) GetTwtAddrNonce() map[common.Uint160]uint64 { + + mapAddrNonce := make(map[common.Uint160]uint64) + + tp.twtMapMu.Lock() + defer tp.twtMapMu.Unlock() + + for pair := tp.twtMap.Oldest(); pair != nil; pair = pair.Next() { + + twt := pair.Value.(*txnWithTime) + sender, err := twt.txn.GetProgramHashes() + if err != nil { + return nil + } + nonce, _ := mapAddrNonce[sender[0]] + if twt.txn.UnsignedTx.Nonce+1 > nonce { + mapAddrNonce[sender[0]] = twt.txn.UnsignedTx.Nonce + 1 // we send expecected(next) nonce to neighbor + } + } + + return mapAddrNonce +} + +// get transactions later than specific time from txn with time map +// earliest is in milli-second +func (tp *TxnPool) GetTwtTxnAfter(earliest int64, reqAddrNonce map[common.Uint160]uint64) ([]*pb.Transaction, error) { + respTxns := make([]*pb.Transaction, 0) + + tp.twtMapMu.Lock() + defer tp.twtMapMu.Unlock() + + for pair := tp.twtMap.Newest(); pair != nil; pair = pair.Prev() { + + twt := pair.Value.(*txnWithTime) + if twt.arriveTime < earliest { // skip too old txn + break + } + + sender, err := twt.txn.GetProgramHashes() + if err != nil { + return nil, err + } + + addr := sender[0] + nonce, ok := reqAddrNonce[addr] + + if !ok || twt.txn.UnsignedTx.Nonce >= nonce { // if addr is in request list, we append greater nonce txns to response list + respTxns = append(respTxns, twt.txn.Transaction) + } + } + + return respTxns, nil +} + +// get xorHashOfTxnTime +func (tp *TxnPool) GetTwtFingerprintAndCount() ([]byte, int) { + tp.twtMapMu.RLock() + defer tp.twtMapMu.RUnlock() + + fp := make([]byte, 0, len(tp.twtFingerprint)) + fp = append(fp, tp.twtFingerprint...) + + return fp, tp.twtCount +} + +// set last sync time +func (tp *TxnPool) SetSyncTime() { + tp.lastSyncTime = time.Now().UnixMilli() +} + +// set last sync time +func (tp *TxnPool) GetSyncTime() int64 { + return tp.lastSyncTime +} diff --git a/chain/pool/txwithtime_test.go b/chain/pool/txwithtime_test.go new file mode 100644 index 000000000..849f4e2f7 --- /dev/null +++ b/chain/pool/txwithtime_test.go @@ -0,0 +1,408 @@ +package pool + +import ( + "bytes" + "fmt" + "math/rand" + "testing" + "time" + + "github.com/nknorg/nkn/v2/common" + "github.com/nknorg/nkn/v2/transaction" + "github.com/stretchr/testify/require" +) + +// create a rand txn for testing +func createRandTxn(sender *common.Uint160, nonce uint64) *transaction.Transaction { + + rand.Seed(time.Now().UnixMilli()) + + recipient := new(common.Uint160) + randBytes := make([]byte, 20) + rand.Read(randBytes) + recipient.SetBytes(randBytes) + + val := rand.Intn(10) + if val <= 0 { + val = 1 + } + value, _ := common.StringToFixed64(fmt.Sprintf("%v", val)) + fee, _ := common.StringToFixed64("0.1") + + txn, _ := transaction.NewTransferAssetTransaction(*sender, *recipient, nonce, value, fee) + return (txn) +} + +// go test -v -run=TestXorBytes +func TestXorBytes(t *testing.T) { + b1 := []byte{0xff} + b2 := []byte{0x00} + + b, _ := xorBytes(b1, b2) + require.Equal(t, byte(0xff), b[0]) + + b, _ = xorBytes(b1, b1) + require.Equal(t, byte(0x00), b[0]) + + b, _ = xorBytes(b2, b2) + require.Equal(t, byte(0x00), b[0]) + + b1 = []byte{0xff, 0xff, 0x00} + b2 = []byte{0x00, 0x00, 0xff} + b, _ = xorBytes(b1, b2) + res := bytes.Equal([]byte{0xff, 0xff, 0xff}, b) + require.Equal(t, true, res) + + b, _ = xorBytes(b1, b1) + res = bytes.Equal([]byte{0x00, 0x00, 0x00}, b) + require.Equal(t, true, res) + + // different len + b1 = []byte{0xff, 0xff, 0x00} + b2 = []byte{0x00, 0x00} + b, err := xorBytes(b1, b2) + require.Equal(t, 0, len(b)) + require.NotEqual(t, nil, err) + +} + +// go test -v -run=TestUpdateTwtFingerprint +func TestUpdateTwtFingerprint(t *testing.T) { + tp := NewTxPool() + + b := make([]byte, 32) + b[31] = 0xff + h1, _ := common.Uint256ParseFromBytes(b) + fingerprint := tp.updateTwtFingerprint(h1) + res := bytes.Equal(fingerprint, h1.ToArray()) + require.Equal(t, true, res) + + tp.twtFingerprint = nil + fingerprint = nil + + rand.Seed(time.Now().UnixMilli()) + const numMsg = 1000 + for i := 0; i < numMsg; i++ { + + rand.Read(b) + hash, _ := common.Uint256ParseFromBytes(b) + res = bytes.Equal(b, hash.ToArray()) + require.Equal(t, true, res) + + fp := tp.updateTwtFingerprint(hash) + + if fingerprint == nil { + fingerprint = make([]byte, 0, len(b)) + fingerprint = append(fingerprint, b...) + } else { + fingerprint, _ = xorBytes(fingerprint, b) + } + + res = bytes.Equal(fp, fingerprint) + require.Equal(t, true, res) + } + +} + +// go test -v -run=TestAppendTwt +func TestAppendTwt(t *testing.T) { + tp := NewTxPool() + + sender := new(common.Uint160) + sender.SetBytes([]byte{0x01}) + + // test Append one txn + nonce := uint64(1) + txn := createRandTxn(sender, nonce) + txnHash := txn.Hash() + + tp.appendTwt(txn) + + v, ok := tp.twtMap.Get(txnHash) + require.Equal(t, true, ok) + twt := v.(*txnWithTime) + fingerprint := txnHash.ToArray() + + require.Equal(t, txn, twt.txn) + require.Equal(t, 1, tp.twtCount) + require.Equal(t, fingerprint, tp.twtFingerprint) + + // remove it, reset + tp.removeTwt(txnHash) + fingerprint = nil + + // test append batch txn in ordered. + const numTxn = 1000 + txnAppended := make([]*transaction.Transaction, 0, numTxn) + for i := 0; i < numTxn; i++ { + nonce++ + txn := createRandTxn(sender, nonce) + txnHash := txn.Hash() + tp.appendTwt(txn) + txnAppended = append(txnAppended, txn) + b := txnHash.ToArray() + if fingerprint == nil { + fingerprint = make([]byte, 0, len(b)) + fingerprint = append(fingerprint, b...) + } else { + fingerprint, _ = xorBytes(fingerprint, b) + } + } + require.Equal(t, numTxn, tp.twtCount) + require.Equal(t, fingerprint, tp.twtFingerprint) + + // pop out twt from oldest to newest, they should be same order as we appened them. + for i := 0; i < numTxn; i++ { + pair := tp.twtMap.Oldest() + twt := pair.Value.(*txnWithTime) + require.Equal(t, txnAppended[i], twt.txn) + tp.twtMap.Delete(pair.Key) + } + +} + +// go test -v -run=TestRemoveTwt +func TestRemoveTwt(t *testing.T) { + tp := NewTxPool() + + sender := new(common.Uint160) + sender.SetBytes([]byte{0x01}) + + nonce := uint64(1) + txn := createRandTxn(sender, nonce) + txnHash := txn.Hash() + tp.appendTwt(txn) + require.Equal(t, 1, tp.twtCount) + + twt := tp.removeTwt(txnHash) + + require.Equal(t, txn, twt.txn) + require.Equal(t, 0, tp.twtCount) + + const numMsg = 1000 + txnMap := make(map[common.Uint256]*transaction.Transaction) + for i := 0; i < numMsg; i++ { + nonce++ + txn := createRandTxn(sender, nonce) + txnHash := txn.Hash() + tp.appendTwt(txn) + txnMap[txnHash] = txn + } + require.Equal(t, numMsg, tp.twtCount) + + for txnHash, txn := range txnMap { + twt := tp.removeTwt(txnHash) + require.Equal(t, txn, twt.txn) + } + require.Equal(t, 0, tp.twtCount) + +} + +// go test -v -run=TestReplaceTwt +func TestReplaceTwt(t *testing.T) { + tp := NewTxPool() + + sender := new(common.Uint160) + sender.SetBytes([]byte{0x01}) + + nonce := uint64(1) + txn1 := createRandTxn(sender, nonce) + tp.appendTwt(txn1) + + txnHash1 := txn1.Hash() + v, _ := tp.twtMap.Get(txnHash1) + twt1 := v.(*txnWithTime) + + require.Equal(t, 1, tp.twtCount) + require.Equal(t, txn1, twt1.txn) + require.Equal(t, txnHash1.ToArray(), tp.twtFingerprint) + + // create a new txn with the same sender and nonce + txn2 := createRandTxn(sender, nonce) + + tp.replaceTwt(txn1, txn2) + + txnHash2 := txn2.Hash() + v, _ = tp.twtMap.Get(txnHash2) + twt2 := v.(*txnWithTime) + + require.Equal(t, 1, tp.twtCount) // twtCound should not increased. + require.Equal(t, txn2, twt2.txn) + require.Equal(t, txnHash2.ToArray(), tp.twtFingerprint) + +} + +// go test -v -run=TestRemoveExpiredTwt +func TestRemoveExpiredTwt(t *testing.T) { + tp := NewTxPool() + + sender := new(common.Uint160) + sender.SetBytes([]byte{0x01}) + nonce := uint64(1) + + var txns []*transaction.Transaction + for i := 0; i < 10; i++ { // insert 10 txns in each second + txn := createRandTxn(sender, nonce) + nonce++ + tp.appendTwt(txn) + require.Equal(t, i+1, tp.twtCount) + txns = append(txns, txn) + + time.Sleep(time.Second) + } + + time.Sleep((MaxSyncTxnInterval - 10) * time.Millisecond) + totalExpired := 0 + for i := 0; i < 10; i++ { + expiredTwt := tp.RemoveExpiredTwt() + for j := 0; j < len(expiredTwt); j++ { // expired as same as we appended them. + require.Equal(t, txns[totalExpired], expiredTwt[j].txn) + totalExpired++ + } + if totalExpired >= 10 { + break + } + + time.Sleep(time.Second) + } + + require.Equal(t, 0, tp.twtCount) + +} + +// go test -v -run=TestGetTwtAddrNonce +func TestGetTwtAddrNonce(t *testing.T) { + tp := NewTxPool() + + sender1 := new(common.Uint160) + sender1.SetBytes([]byte{0x01}) + nonce1 := uint64(1) + + for i := 0; i < 10; i++ { + txn := createRandTxn(sender1, nonce1) + nonce1++ + tp.appendTwt(txn) + } + + sender2 := new(common.Uint160) + sender2.SetBytes([]byte{0x02}) + nonce2 := uint64(10) + + for i := 0; i < 5; i++ { + txn := createRandTxn(sender2, nonce2) + nonce2++ + tp.appendTwt(txn) + } + + mapAddrNonce := tp.GetTwtAddrNonce() + require.Equal(t, 2, len(mapAddrNonce)) + require.Equal(t, nonce1, mapAddrNonce[*sender1]) + require.Equal(t, nonce2, mapAddrNonce[*sender2]) + +} + +// go test -v -run=TestGetTwtTxnAfter +func TestGetTwtTxnAfter(t *testing.T) { + tp := NewTxPool() + + sender1 := new(common.Uint160) + sender1.SetBytes([]byte{0x01}) + nonce1 := uint64(1) + + sender2 := new(common.Uint160) + sender2.SetBytes([]byte{0x02}) + nonce2 := uint64(1) + + now1 := time.Now().UnixMilli() + for i := 0; i < 5; i++ { // insert 5 txns in each second + txn := createRandTxn(sender1, nonce1) + nonce1++ + tp.appendTwt(txn) + + txn = createRandTxn(sender2, nonce2) + nonce2++ + tp.appendTwt(txn) + + time.Sleep(time.Second) + } + + now2 := time.Now().UnixMilli() + time.Sleep(time.Second) + + for i := 0; i < 5; i++ { // insert 5 txns + txn := createRandTxn(sender2, nonce2) + nonce2++ + tp.appendTwt(txn) + } + + // set 1 address, and get after now1 + reqAddrNonce := make(map[common.Uint160]uint64) + reqAddrNonce[*sender1] = 4 + + txnList, err := tp.GetTwtTxnAfter(now1, reqAddrNonce) + require.Equal(t, nil, err) + require.Equal(t, 12, len(txnList)) + + // set 2 addresses, and get after now1 + reqAddrNonce[*sender1] = 4 + reqAddrNonce[*sender2] = 6 + + txnList, err = tp.GetTwtTxnAfter(now1, reqAddrNonce) + require.Equal(t, nil, err) + require.Equal(t, 7, len(txnList)) + + // set 2 addresses, get txn after now2 + txnList, err = tp.GetTwtTxnAfter(now2, reqAddrNonce) + require.Equal(t, nil, err) + require.Equal(t, 5, len(txnList)) + +} + +// go test -v -run=TestRemoveFromTwtMap +func TestRemoveFromTwtMap(t *testing.T) { + tp := NewTxPool() + + sender := new(common.Uint160) + sender.SetBytes([]byte{0x01}) + nonce := uint64(1) + + var txns []*transaction.Transaction + for i := 0; i < 10; i++ { // insert 10 txns in each second + txn := createRandTxn(sender, nonce) + nonce++ + tp.appendTwt(txn) + require.Equal(t, i+1, tp.twtCount) + + if i%2 == 1 { + txns = append(txns, txn) + } + } + require.Equal(t, 10, tp.twtCount) + + tp.removeFromTwtMap(txns) + + require.Equal(t, 5, tp.twtCount) +} + +// go test -v -run=TestGetTwtFingerprintAndCount +func TestGetTwtFingerprintAndCount(t *testing.T) { + tp := NewTxPool() + + sender := new(common.Uint160) + sender.SetBytes([]byte{0x01}) + nonce := uint64(1) + + const numTxn = 10 + for i := 0; i < numTxn; i++ { // insert 10 txns in each second + txn := createRandTxn(sender, nonce) + nonce++ + tp.appendTwt(txn) + require.Equal(t, i+1, tp.twtCount) + } + + fp, count := tp.GetTwtFingerprintAndCount() + res := bytes.Equal(fp, tp.twtFingerprint) + + require.Equal(t, numTxn, count) + require.Equal(t, true, res) +} diff --git a/go.mod b/go.mod index 4d2d998d9..757e797c4 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,9 @@ require ( github.com/rdegges/go-ipify v0.0.0-20150526035502-2d94a6a86c40 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 + github.com/wk8/go-ordered-map v1.0.0 // indirect golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 google.golang.org/protobuf v1.26.0 diff --git a/go.sum b/go.sum index f49a297d9..e34ad8616 100644 --- a/go.sum +++ b/go.sum @@ -351,11 +351,18 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= @@ -374,6 +381,8 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vultr/govultr v0.4.2/go.mod h1:TUuUizMOFc7z+PNMssb6iGjKjQfpw5arIaOLfocVudQ= +github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8= +github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -655,6 +664,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/lnode/syncblock.go b/lnode/syncblock.go index 687177a04..ea2c5327c 100644 --- a/lnode/syncblock.go +++ b/lnode/syncblock.go @@ -404,6 +404,15 @@ func (localNode *LocalNode) initSyncing() { localNode.AddMessageHandler(pb.MessageType_GET_BLOCKS, localNode.getBlocksMessageHandler) localNode.AddMessageHandler(pb.MessageType_GET_STATES, localNode.getStatesMessageHandler) localNode.ResetSyncing() + + // sync txn poo + localNode.AddMessageHandler(pb.MessageType_REQ_TXN_POOL_HASH, localNode.requestTxnPoolHashHandler) + localNode.AddMessageHandler(pb.MessageType_REQ_SYNC_TXN_POOL, localNode.requestSyncTxnPoolHandler) + go localNode.StartSyncTxnPool() + // sync txn, random address + localNode.AddMessageHandler(pb.MessageType_REQ_ADDR_NONCE, localNode.requestAddrNonceHandler) + localNode.AddMessageHandler(pb.MessageType_REQ_SYNC_ADDR_TXN, localNode.requestSyncAddrTxnHandler) + go localNode.StartSyncRandAddrTxn() } func removeStoppedNeighbors(neighbors []*node.RemoteNode) []*node.RemoteNode { diff --git a/lnode/syncrandaddr.go b/lnode/syncrandaddr.go new file mode 100644 index 000000000..6dd1739da --- /dev/null +++ b/lnode/syncrandaddr.go @@ -0,0 +1,294 @@ +package lnode + +import ( + "math/rand" + "reflect" + "time" + + "github.com/golang/protobuf/proto" + "github.com/nknorg/nkn/v2/chain" + "github.com/nknorg/nkn/v2/chain/pool" + "github.com/nknorg/nkn/v2/common" + "github.com/nknorg/nkn/v2/config" + "github.com/nknorg/nkn/v2/node" + "github.com/nknorg/nkn/v2/pb" + "github.com/nknorg/nkn/v2/transaction" + "github.com/nknorg/nkn/v2/util" + "github.com/nknorg/nkn/v2/util/log" +) + +// Number of random neighbors to sync rand addr +const NumNbrToSyncRandAddr = 1 + +func (localNode *LocalNode) StartSyncRandAddrTxn() { + for { + dur := util.RandDuration(config.ConsensusDuration/2, 0.4) + time.Sleep(dur) + localNode.SyncRandAddrTxn() + } +} + +// sync rand addr process +func (localNode *LocalNode) SyncRandAddrTxn() { + + neighbors := localNode.GetNeighbors(nil) + neighborCount := len(neighbors) + if neighborCount <= 0 { // don't have neighbor yet + return + } + + if NumNbrToSyncRandAddr < neighborCount { + // choose rand neighbors + r := rand.New(rand.NewSource(time.Now().UnixNano())) + r.Shuffle(len(neighbors), func(i, j int) { neighbors[i], neighbors[j] = neighbors[j], neighbors[i] }) + + neighbors = neighbors[:NumNbrToSyncRandAddr] + } + + for _, neighbor := range neighbors { + + go func(nbr *node.RemoteNode) { + + addrNonceReply, err := localNode.requestAddrNonce(nbr) + if err != nil { + log.Warningf("requestAddrNonce to neighbor %v error: %v\n", nbr.GetAddr(), err) + return + } + + addr160, err := common.Uint160ParseFromBytes(addrNonceReply.Address) + if err != nil { + log.Warning("Sync txn by rand address, parse replied address error : ", err.Error()) + return + } + + if addr160.CompareTo(common.EmptyUint160) == 0 { // get an empty address + return + } + + // here we get next expected nonce = last nonce + 1 + myNonce, err := localNode.TxnPool.GetNonceByTxnPool(addr160) + if err != nil { + myNonce = chain.DefaultLedger.Store.GetNonce(addr160) + } + + if myNonce < addrNonceReply.Nonce { + addrTxnRelpy, err := localNode.requestSyncAddrTxn(nbr, addrNonceReply.Address, myNonce) + if err != nil { + log.Info("localNode.requestSyncAddrTxn err: ", err) + } else { + // update txn pool + for _, pbTxn := range addrTxnRelpy.Transactions { + + txn := &transaction.Transaction{Transaction: pbTxn} + if localNode.ExistHash(txn.Hash()) { + continue + } + localNode.TxnPool.AppendTxnPool(txn) + } + } + + } + + }(neighbor) + } + +} + +// send neighbor a REQ_ADDR_NONCE request message, and wait for reply. +func (localNode *LocalNode) requestAddrNonce(remoteNode *node.RemoteNode) (*pb.AddrNonce, error) { + + msg, err := NewReqAddrNonceMessage() + if err != nil { + return nil, err + } + + buf, err := localNode.SerializeMessage(msg, false) + if err != nil { + return nil, err + } + + replyBytes, err := remoteNode.SendBytesSyncWithTimeout(buf, syncReplyTimeout) + if err != nil { + return nil, err + } + + replyMsg := &pb.AddrNonce{} + err = proto.Unmarshal(replyBytes, replyMsg) + if err != nil { + return nil, err + } + + return replyMsg, nil +} + +// send to a neighbor a REQ_SYNC_ADDR_TXN request message, and wait for reply with timeout +// return the reply messge RPL_SYNC_ADDR_TXN +func (localNode *LocalNode) requestSyncAddrTxn(remoteNode *node.RemoteNode, addr []byte, nonce uint64) (*pb.Transactions, error) { + + msg, err := NewReqSyncAddrTxnMessage(addr, nonce) + if err != nil { + return nil, err + } + + buf, err := localNode.SerializeMessage(msg, false) + if err != nil { + return nil, err + } + + replyBytes, err := remoteNode.SendBytesSyncWithTimeout(buf, syncReplyTimeout) + if err != nil { + return nil, err + } + + replyMsg := &pb.Transactions{} + err = proto.Unmarshal(replyBytes, replyMsg) + if err != nil { + return nil, err + } + + log.Info("Sync txn by rand address, get ", len(replyMsg.Transactions), "txns from neighbor") + + return replyMsg, nil +} + +// build a REQ_ADDR_NONCE request message +func NewReqAddrNonceMessage() (*pb.UnsignedMessage, error) { + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_REQ_ADDR_NONCE, + } + + return msg, nil + +} + +// build RPL_ADDR_NONCE reply message +// reply with rand address my txn pool's with this address' nonce. +func NewRplAddrNonceMessage(tp *pool.TxnPool) (*pb.UnsignedMessage, error) { + addrMap := tp.GetAddressList() + addrCount := len(addrMap) + + var addr common.Uint160 + var nonce uint64 + if addrCount > 0 { + mapKeys := reflect.ValueOf(addrMap).MapKeys() + + // get a rand address + r := rand.New(rand.NewSource(time.Now().UnixNano())) + rn := r.Intn(addrCount) + addr = mapKeys[rn].Interface().(common.Uint160) + + var err error + nonce, err = tp.GetNonceByTxnPool(addr) // here get expected nonce which is current last nonce + 1 + if err != nil { + return nil, err + } + } + + msgBody := &pb.AddrNonce{ + Address: addr.ToArray(), + Nonce: nonce, + } + + buf, err := proto.Marshal(msgBody) + if err != nil { + return nil, err + } + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_RPL_ADDR_NONCE, + Message: buf, + } + + return msg, nil +} + +// build REQ_SYNC_ADDR_TXN request message +// This message includse my txn pool's txn address and maximum nonce. +func NewReqSyncAddrTxnMessage(addr []byte, nonce uint64) (*pb.UnsignedMessage, error) { + + msgBody := &pb.AddrNonce{Address: addr, Nonce: nonce} + + buf, err := proto.Marshal(msgBody) + if err != nil { + return nil, err + } + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_REQ_SYNC_ADDR_TXN, + Message: buf, + } + + return msg, nil + +} + +// build RPL_SYNC_ADDR_TXN message. reply transactions which are needed to sync to the requestor. +func NewRplSyncAddrTxnMessage(reqMsg *pb.AddrNonce, tp *pool.TxnPool) (*pb.UnsignedMessage, error) { + + addr160, err := common.Uint160ParseFromBytes(reqMsg.Address) + if err != nil { + return nil, err + } + + // here list is sorted, ordered by nonce + list := tp.GetAllTransactionsBySender(addr160) + + i := 0 + for i = 0; i < len(list); i++ { + if list[i].UnsignedTx.Nonce >= reqMsg.Nonce { + break + } + } + + var respTxns []*pb.Transaction + for ; i < len(list); i++ { + respTxns = append(respTxns, list[i].Transaction) + } + + msgBody := &pb.Transactions{Transactions: respTxns} + + log.Info("Sync txn by rand address, send ", len(respTxns), " txns to neighbor") + + buf, err := proto.Marshal(msgBody) + if err != nil { + return nil, err + } + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_RPL_SYNC_ADDR_TXN, + Message: buf, + } + + return msg, nil +} + +// handle a REQ_ADDR_NONCE request message. return a RPL_ADDR_NONCE response message buffer. +func (localNode *LocalNode) requestAddrNonceHandler(remoteMessage *node.RemoteMessage) ([]byte, bool, error) { + + replyMsg, err := NewRplAddrNonceMessage(localNode.TxnPool) + if err != nil { + return nil, false, err + } + + replyBuf, err := localNode.SerializeMessage(replyMsg, false) + return replyBuf, false, err +} + +// Handle REQ_SYNC_ADDR_TXN request message, return RPL_SYNC_ADDR_TXN response message buffer. +func (localNode *LocalNode) requestSyncAddrTxnHandler(remoteMessage *node.RemoteMessage) ([]byte, bool, error) { + + reqMsg := &pb.AddrNonce{} + err := proto.Unmarshal(remoteMessage.Message, reqMsg) + if err != nil { + return nil, false, err + } + + replyMsg, err := NewRplSyncAddrTxnMessage(reqMsg, localNode.TxnPool) + if err != nil { + return nil, false, err + } + + replyBuf, err := localNode.SerializeMessage(replyMsg, false) + return replyBuf, false, err +} diff --git a/lnode/synctxnpool.go b/lnode/synctxnpool.go new file mode 100644 index 000000000..fd2ee3fcc --- /dev/null +++ b/lnode/synctxnpool.go @@ -0,0 +1,337 @@ +package lnode + +import ( + "bytes" + "math/rand" + "sort" + "sync" + "time" + + "github.com/golang/protobuf/proto" + "github.com/nknorg/nkn/v2/chain/pool" + "github.com/nknorg/nkn/v2/common" + "github.com/nknorg/nkn/v2/config" + "github.com/nknorg/nkn/v2/node" + "github.com/nknorg/nkn/v2/pb" + "github.com/nknorg/nkn/v2/transaction" + "github.com/nknorg/nkn/v2/util" + "github.com/nknorg/nkn/v2/util/log" +) + +// Number of random neighbors to sync txn pool +const NumNbrToSyncTxnPool = 1 + +func (localNode *LocalNode) StartSyncTxnPool() { + for { + dur := util.RandDuration(config.ConsensusDuration/2, 0.4) + time.Sleep(dur) + localNode.SyncTxnPool() + } +} + +// sync txn pool process +func (localNode *LocalNode) SyncTxnPool() { + + // remove expired twt before sending request + localNode.TxnPool.RemoveExpiredTwt() + + neighbors := localNode.GetNeighbors(nil) + neighborCount := len(neighbors) + + if neighborCount <= 0 { // don't have any neighbor yet + return + } + + if NumNbrToSyncTxnPool < neighborCount { // choose random neighbors + + r := rand.New(rand.NewSource(time.Now().UnixNano())) + r.Shuffle(len(neighbors), func(i, j int) { neighbors[i], neighbors[j] = neighbors[j], neighbors[i] }) + + neighbors = neighbors[:NumNbrToSyncTxnPool] + } + + myHash, _ := localNode.TxnPool.GetTwtFingerprintAndCount() + maxCount := uint32(0) + var maxMu sync.Mutex + var neighborToSync *node.RemoteNode // the neighbor which is sync txn target + var wg sync.WaitGroup + + for _, neighbor := range neighbors { + wg.Add(1) + + go func(nbr *node.RemoteNode) { + defer wg.Done() + + replyMsg, err := localNode.requestTxnPoolHash(nbr) + if err != nil { + log.Warningf("sendReqTxnPoolHash neighbor %v error: %v", nbr.GetAddr(), err) + return + } + + if !bytes.Equal(replyMsg.PoolHash, myHash) { + maxMu.Lock() + if replyMsg.TxnCount > maxCount { // Choose the neighbor which has most txn count in txn pool + neighborToSync = nbr + maxCount = replyMsg.TxnCount + } + maxMu.Unlock() + } + }(neighbor) + + } + + wg.Wait() + + // request for syncing + if neighborToSync != nil { + replyMsg, err := localNode.requestSyncTxnPool(neighborToSync) + if err != nil { + log.Error("req sync txn pool error: ", err) + } else { + // sort it by nonce to append them to txn pool. + sort.Slice(replyMsg.Transactions, func(i, j int) bool { + return replyMsg.Transactions[i].UnsignedTx.Nonce < replyMsg.Transactions[j].UnsignedTx.Nonce + }) + + for _, pbTxn := range replyMsg.Transactions { + txn := &transaction.Transaction{ + Transaction: pbTxn, + } + + if localNode.ExistHash(txn.Hash()) { + continue + } + localNode.TxnPool.AppendTxnPool(txn) + } + + // after update my txn pool, reset sync time. + localNode.TxnPool.SetSyncTime() + } + } +} + +// send neighbor a REQ_TXN_POOL_HASH request message, and wait for reply. +func (localNode *LocalNode) requestTxnPoolHash(remoteNode *node.RemoteNode) (*pb.TxnPoolHashAndCount, error) { + + msg, err := NewReqTxnPoolHashMessage() + if err != nil { + return nil, err + } + + buf, err := localNode.SerializeMessage(msg, false) + if err != nil { + return nil, err + } + + replyBytes, err := remoteNode.SendBytesSyncWithTimeout(buf, syncReplyTimeout) + if err != nil { + return nil, err + } + + replyMsg := &pb.TxnPoolHashAndCount{} + err = proto.Unmarshal(replyBytes, replyMsg) + if err != nil { + return nil, err + } + + return replyMsg, nil +} + +// build a REQ_TXN_POOL_HASH request message +func NewReqTxnPoolHashMessage() (*pb.UnsignedMessage, error) { + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_REQ_TXN_POOL_HASH, + } + + return msg, nil + +} + +// build RPL_TXN_POOL_HASH reply message, reply with my txn pool's hash and txn count. +func NewRplTxnPoolHashMessage(tp *pool.TxnPool) (*pb.UnsignedMessage, error) { + + poolHash, txnCount := tp.GetTwtFingerprintAndCount() + + msgBody := &pb.TxnPoolHashAndCount{ + PoolHash: poolHash, + TxnCount: (uint32)(txnCount), + } + + buf, err := proto.Marshal(msgBody) + if err != nil { + return nil, err + } + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_RPL_TXN_POOL_HASH, + Message: buf, + } + + return msg, nil +} + +// build REQ_SYNC_TXN_POOL request message. This message includse my txn pool's txn address and maximum nonce. +func NewReqSyncTxnPoolMessage(tp *pool.TxnPool) (*pb.UnsignedMessage, error) { + + addrNonceList := make([]*pb.AddrNonce, 0) + mapAddrNonce := tp.GetTwtAddrNonce() + + for addr, nonce := range mapAddrNonce { + addrNonceList = append(addrNonceList, &pb.AddrNonce{ + Address: addr.ToArray(), + Nonce: nonce, + }) + } + + // get the duration since last sync txn time. + duration := time.Now().UnixMilli() - tp.GetSyncTime() + if tp.GetSyncTime() == 0 { // never synced before + duration = 0 + } + msgBody := &pb.RequestSyncTxnPool{Duration: duration, AddrNonce: addrNonceList} + + buf, err := proto.Marshal(msgBody) + if err != nil { + return nil, err + } + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_REQ_SYNC_TXN_POOL, + Message: buf, + } + + return msg, nil +} + +// build RPL_SYNC_TXN_POOL message. reply transactions which are needed to sync to the requestor. +func NewRplSyncTxnPoolMessage(reqMsg *pb.RequestSyncTxnPool, tp *pool.TxnPool) (*pb.UnsignedMessage, error) { + + mapReqAddrNonce := make(map[common.Uint160]uint64) + + // if there is address and nonce in the request message, save them in a map for better searching. + if len(reqMsg.AddrNonce) > 0 { + for _, addrNonce := range reqMsg.AddrNonce { + mapReqAddrNonce[common.BytesToUint160(addrNonce.Address)] = addrNonce.Nonce + } + } + + var respTxns []*pb.Transaction + var err error + + if reqMsg.Duration > 0 { + respTxns, err = syncInDuration(tp, mapReqAddrNonce, reqMsg.Duration) + } else { + respTxns, err = syncFully(tp, mapReqAddrNonce) + } + if err != nil { + return nil, err + } + + msgBody := &pb.Transactions{Transactions: respTxns} + + buf, err := proto.Marshal(msgBody) + if err != nil { + return nil, err + } + + msg := &pb.UnsignedMessage{ + MessageType: pb.MessageType_RPL_SYNC_TXN_POOL, + Message: buf, + } + + return msg, nil +} + +// Only sync txn in the last duration seconds, partially of the txn pool +func syncInDuration(tp *pool.TxnPool, reqAddrNonce map[common.Uint160]uint64, duration int64) ([]*pb.Transaction, error) { + + now := time.Now().UnixMilli() + earliest := now - duration - 1000 // push 1 second ahead + respTxns, err := tp.GetTwtTxnAfter(earliest, reqAddrNonce) + + return respTxns, err +} + +// sync all my txns in the pool to the neighbor when the neighbor just start. +func syncFully(tp *pool.TxnPool, reqAddrNonce map[common.Uint160]uint64) ([]*pb.Transaction, error) { + + respTxns := make([]*pb.Transaction, 0) // response txn list buffer + + mapMyTxnList := tp.GetAllTransactionLists() + for addr, myTxnList := range mapMyTxnList { + nonce, _ := reqAddrNonce[addr] + for _, txn := range myTxnList { + if txn.UnsignedTx.Nonce >= nonce { + respTxns = append(respTxns, txn.Transaction) + } + } + } + + log.Info("Sync txn, send ", len(respTxns), " txns to neighbor") + + return respTxns, nil +} + +// handle a REQ_TXN_POOL_HASH request message, return a RPL_TXN_POOL_HASH response message buffer. +func (localNode *LocalNode) requestTxnPoolHashHandler(remoteMessage *node.RemoteMessage) ([]byte, bool, error) { + // remove expired twt when getting request + localNode.TxnPool.RemoveExpiredTwt() + + replyMsg, err := NewRplTxnPoolHashMessage(localNode.TxnPool) + if err != nil { + return nil, false, err + } + + replyBuf, err := localNode.SerializeMessage(replyMsg, false) + return replyBuf, false, err +} + +// send to a neighbor a REQ_SYNC_TXN_POOL request message, and wait for reply with timeout +// return the reply messge RPL_SYNC_TXN_POOL +func (localNode *LocalNode) requestSyncTxnPool(remoteNode *node.RemoteNode) (*pb.Transactions, error) { + + msg, err := NewReqSyncTxnPoolMessage(localNode.TxnPool) + if err != nil { + return nil, err + } + + buf, err := localNode.SerializeMessage(msg, false) + if err != nil { + return nil, err + } + + replyBytes, err := remoteNode.SendBytesSyncWithTimeout(buf, syncReplyTimeout) + if err != nil { + return nil, err + } + + // get RSP_SYNC_TXN_POOL message, update my txn pool + replyMsg := &pb.Transactions{} + err = proto.Unmarshal(replyBytes, replyMsg) + if err != nil { + return nil, err + } + + log.Info("Sync txn pool, get ", len(replyMsg.Transactions), " txns from neighbor") + + return replyMsg, nil +} + +// Handle REQ_SYNC_TXN_POOL request message, return RPL_SYNC_TXN_POOL response message buffer. +func (localNode *LocalNode) requestSyncTxnPoolHandler(remoteMessage *node.RemoteMessage) ([]byte, bool, error) { + + reqMsg := &pb.RequestSyncTxnPool{} + err := proto.Unmarshal(remoteMessage.Message, reqMsg) + if err != nil { + return nil, false, err + } + + replyMsg, err := NewRplSyncTxnPoolMessage(reqMsg, localNode.TxnPool) + if err != nil { + return nil, false, err + } + + replyBuf, err := localNode.SerializeMessage(replyMsg, false) + return replyBuf, false, err +} diff --git a/pb/nodemessage.pb.go b/pb/nodemessage.pb.go index 0d529a037..27771c4e2 100644 --- a/pb/nodemessage.pb.go +++ b/pb/nodemessage.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.14.0 +// protoc v3.15.6 // source: pb/nodemessage.proto package pb @@ -46,6 +46,16 @@ const ( MessageType_SIGNATURE_CHAIN_OBJECTION MessageType = 20 MessageType_GET_STATES MessageType = 21 MessageType_GET_STATES_REPLY MessageType = 22 + // sync txn pool + MessageType_REQ_TXN_POOL_HASH MessageType = 23 // request txn pool hash + MessageType_RPL_TXN_POOL_HASH MessageType = 24 // reply txn pool hash + MessageType_REQ_SYNC_TXN_POOL MessageType = 25 // request to sync txn pool + MessageType_RPL_SYNC_TXN_POOL MessageType = 26 // reply to sync txn pool + // sync random address transaction + MessageType_REQ_ADDR_NONCE MessageType = 27 // reques for random address and nonce + MessageType_RPL_ADDR_NONCE MessageType = 28 // reply random address and nonce in txn pool + MessageType_REQ_SYNC_ADDR_TXN MessageType = 29 // request for syncing this address transactions + MessageType_RPL_SYNC_ADDR_TXN MessageType = 30 // reply this address' transactions ) // Enum value maps for MessageType. @@ -74,6 +84,14 @@ var ( 20: "SIGNATURE_CHAIN_OBJECTION", 21: "GET_STATES", 22: "GET_STATES_REPLY", + 23: "REQ_TXN_POOL_HASH", + 24: "RPL_TXN_POOL_HASH", + 25: "REQ_SYNC_TXN_POOL", + 26: "RPL_SYNC_TXN_POOL", + 27: "REQ_ADDR_NONCE", + 28: "RPL_ADDR_NONCE", + 29: "REQ_SYNC_ADDR_TXN", + 30: "RPL_SYNC_ADDR_TXN", } MessageType_value = map[string]int32{ "MESSAGE_TYPE_PLACEHOLDER_DO_NOT_USE": 0, @@ -99,6 +117,14 @@ var ( "SIGNATURE_CHAIN_OBJECTION": 20, "GET_STATES": 21, "GET_STATES_REPLY": 22, + "REQ_TXN_POOL_HASH": 23, + "RPL_TXN_POOL_HASH": 24, + "REQ_SYNC_TXN_POOL": 25, + "RPL_SYNC_TXN_POOL": 26, + "REQ_ADDR_NONCE": 27, + "RPL_ADDR_NONCE": 28, + "REQ_SYNC_ADDR_TXN": 29, + "RPL_SYNC_ADDR_TXN": 30, } ) @@ -202,6 +228,16 @@ const ( AllowedUnsignedMessageType_ALLOW_UNSIGNED_SIGNATURE_CHAIN_OBJECTION AllowedUnsignedMessageType = 20 AllowedUnsignedMessageType_ALLOW_UNSIGNED_GET_STATES AllowedUnsignedMessageType = 21 AllowedUnsignedMessageType_ALLOW_UNSIGNED_GET_STATES_REPLY AllowedUnsignedMessageType = 22 + // sync txn pool + AllowedUnsignedMessageType_ALLOW_UNSIGNED_REQ_TXN_POOL_HASH AllowedUnsignedMessageType = 23 // request txn pool hash + AllowedUnsignedMessageType_ALLOW_UNSIGNED_RPL_TXN_POOL_HASH AllowedUnsignedMessageType = 24 // reply txn pool hash + AllowedUnsignedMessageType_ALLOW_UNSIGNED_REQ_SYNC_TXN_POOL AllowedUnsignedMessageType = 25 // request to sync txn pool + AllowedUnsignedMessageType_ALLOW_UNSIGNED_RPL_SYNC_TXN_POOL AllowedUnsignedMessageType = 26 // reply to sync txn pool + // sync random address transaction + AllowedUnsignedMessageType_ALLOW_UNSIGNED_REQ_ADDR_NONCE AllowedUnsignedMessageType = 27 // reques for random address and nonce + AllowedUnsignedMessageType_ALLOW_UNSIGNED_RPL_ADDR_NONCE AllowedUnsignedMessageType = 28 // reply random address and nonce in txn pool + AllowedUnsignedMessageType_ALLOW_UNSIGNED_REQ_SYNC_ADDR_TXN AllowedUnsignedMessageType = 29 // request for syncing this address transactions + AllowedUnsignedMessageType_ALLOW_UNSIGNED_RPL_SYNC_ADDR_TXN AllowedUnsignedMessageType = 30 // reply this address' transactions ) // Enum value maps for AllowedUnsignedMessageType. @@ -230,6 +266,14 @@ var ( 20: "ALLOW_UNSIGNED_SIGNATURE_CHAIN_OBJECTION", 21: "ALLOW_UNSIGNED_GET_STATES", 22: "ALLOW_UNSIGNED_GET_STATES_REPLY", + 23: "ALLOW_UNSIGNED_REQ_TXN_POOL_HASH", + 24: "ALLOW_UNSIGNED_RPL_TXN_POOL_HASH", + 25: "ALLOW_UNSIGNED_REQ_SYNC_TXN_POOL", + 26: "ALLOW_UNSIGNED_RPL_SYNC_TXN_POOL", + 27: "ALLOW_UNSIGNED_REQ_ADDR_NONCE", + 28: "ALLOW_UNSIGNED_RPL_ADDR_NONCE", + 29: "ALLOW_UNSIGNED_REQ_SYNC_ADDR_TXN", + 30: "ALLOW_UNSIGNED_RPL_SYNC_ADDR_TXN", } AllowedUnsignedMessageType_value = map[string]int32{ "ALLOW_UNSIGNED_PLACEHOLDER_DO_NOT_USE": 0, @@ -255,6 +299,14 @@ var ( "ALLOW_UNSIGNED_SIGNATURE_CHAIN_OBJECTION": 20, "ALLOW_UNSIGNED_GET_STATES": 21, "ALLOW_UNSIGNED_GET_STATES_REPLY": 22, + "ALLOW_UNSIGNED_REQ_TXN_POOL_HASH": 23, + "ALLOW_UNSIGNED_RPL_TXN_POOL_HASH": 24, + "ALLOW_UNSIGNED_REQ_SYNC_TXN_POOL": 25, + "ALLOW_UNSIGNED_RPL_SYNC_TXN_POOL": 26, + "ALLOW_UNSIGNED_REQ_ADDR_NONCE": 27, + "ALLOW_UNSIGNED_RPL_ADDR_NONCE": 28, + "ALLOW_UNSIGNED_REQ_SYNC_ADDR_TXN": 29, + "ALLOW_UNSIGNED_RPL_SYNC_ADDR_TXN": 30, } ) @@ -311,6 +363,16 @@ const ( AllowedDirectMessageType_ALLOW_DIRECT_SIGNATURE_CHAIN_OBJECTION AllowedDirectMessageType = 20 AllowedDirectMessageType_ALLOW_DIRECT_GET_STATES AllowedDirectMessageType = 21 AllowedDirectMessageType_ALLOW_DIRECT_GET_STATES_REPLY AllowedDirectMessageType = 22 + // sync txn pool + AllowedDirectMessageType_ALLOW_DIRECT_REQ_TXN_POOL_HASH AllowedDirectMessageType = 23 // request txn pool hash + AllowedDirectMessageType_ALLOW_DIRECT_RPL_TXN_POOL_HASH AllowedDirectMessageType = 24 // reply txn pool hash + AllowedDirectMessageType_ALLOW_DIRECT_REQ_SYNC_TXN_POOL AllowedDirectMessageType = 25 // request to sync txn pool + AllowedDirectMessageType_ALLOW_DIRECT_RPL_SYNC_TXN_POOL AllowedDirectMessageType = 26 // reply to sync txn pool + // sync random address transaction + AllowedDirectMessageType_ALLOW_DIRECT_REQ_ADDR_NONCE AllowedDirectMessageType = 27 // reques for random address and nonce + AllowedDirectMessageType_ALLOW_DIRECT_RPL_ADDR_NONCE AllowedDirectMessageType = 28 // reply random address and nonce in txn pool + AllowedDirectMessageType_ALLOW_DIRECT_REQ_SYNC_ADDR_TXN AllowedDirectMessageType = 29 // request for syncing this address transactions + AllowedDirectMessageType_ALLOW_DIRECT_RPL_SYNC_ADDR_TXN AllowedDirectMessageType = 30 // reply this address' transactions ) // Enum value maps for AllowedDirectMessageType. @@ -337,6 +399,14 @@ var ( 20: "ALLOW_DIRECT_SIGNATURE_CHAIN_OBJECTION", 21: "ALLOW_DIRECT_GET_STATES", 22: "ALLOW_DIRECT_GET_STATES_REPLY", + 23: "ALLOW_DIRECT_REQ_TXN_POOL_HASH", + 24: "ALLOW_DIRECT_RPL_TXN_POOL_HASH", + 25: "ALLOW_DIRECT_REQ_SYNC_TXN_POOL", + 26: "ALLOW_DIRECT_RPL_SYNC_TXN_POOL", + 27: "ALLOW_DIRECT_REQ_ADDR_NONCE", + 28: "ALLOW_DIRECT_RPL_ADDR_NONCE", + 29: "ALLOW_DIRECT_REQ_SYNC_ADDR_TXN", + 30: "ALLOW_DIRECT_RPL_SYNC_ADDR_TXN", } AllowedDirectMessageType_value = map[string]int32{ "ALLOW_DIRECT_PLACEHOLDER_DO_NOT_USE": 0, @@ -360,6 +430,14 @@ var ( "ALLOW_DIRECT_SIGNATURE_CHAIN_OBJECTION": 20, "ALLOW_DIRECT_GET_STATES": 21, "ALLOW_DIRECT_GET_STATES_REPLY": 22, + "ALLOW_DIRECT_REQ_TXN_POOL_HASH": 23, + "ALLOW_DIRECT_RPL_TXN_POOL_HASH": 24, + "ALLOW_DIRECT_REQ_SYNC_TXN_POOL": 25, + "ALLOW_DIRECT_RPL_SYNC_TXN_POOL": 26, + "ALLOW_DIRECT_REQ_ADDR_NONCE": 27, + "ALLOW_DIRECT_RPL_ADDR_NONCE": 28, + "ALLOW_DIRECT_REQ_SYNC_ADDR_TXN": 29, + "ALLOW_DIRECT_RPL_SYNC_ADDR_TXN": 30, } ) @@ -2130,6 +2208,172 @@ func (x *SignatureChainObjectionSigned) GetSignature() []byte { return nil } +// sync txn pool +type TxnPoolHashAndCount struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PoolHash []byte `protobuf:"bytes,1,opt,name=pool_hash,json=poolHash,proto3" json:"pool_hash,omitempty"` + TxnCount uint32 `protobuf:"varint,2,opt,name=txn_count,json=txnCount,proto3" json:"txn_count,omitempty"` +} + +func (x *TxnPoolHashAndCount) Reset() { + *x = TxnPoolHashAndCount{} + if protoimpl.UnsafeEnabled { + mi := &file_pb_nodemessage_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TxnPoolHashAndCount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TxnPoolHashAndCount) ProtoMessage() {} + +func (x *TxnPoolHashAndCount) ProtoReflect() protoreflect.Message { + mi := &file_pb_nodemessage_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TxnPoolHashAndCount.ProtoReflect.Descriptor instead. +func (*TxnPoolHashAndCount) Descriptor() ([]byte, []int) { + return file_pb_nodemessage_proto_rawDescGZIP(), []int{27} +} + +func (x *TxnPoolHashAndCount) GetPoolHash() []byte { + if x != nil { + return x.PoolHash + } + return nil +} + +func (x *TxnPoolHashAndCount) GetTxnCount() uint32 { + if x != nil { + return x.TxnCount + } + return 0 +} + +type AddrNonce struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Nonce uint64 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"` +} + +func (x *AddrNonce) Reset() { + *x = AddrNonce{} + if protoimpl.UnsafeEnabled { + mi := &file_pb_nodemessage_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddrNonce) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddrNonce) ProtoMessage() {} + +func (x *AddrNonce) ProtoReflect() protoreflect.Message { + mi := &file_pb_nodemessage_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddrNonce.ProtoReflect.Descriptor instead. +func (*AddrNonce) Descriptor() ([]byte, []int) { + return file_pb_nodemessage_proto_rawDescGZIP(), []int{28} +} + +func (x *AddrNonce) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *AddrNonce) GetNonce() uint64 { + if x != nil { + return x.Nonce + } + return 0 +} + +type RequestSyncTxnPool struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Duration int64 `protobuf:"varint,1,opt,name=duration,proto3" json:"duration,omitempty"` + AddrNonce []*AddrNonce `protobuf:"bytes,2,rep,name=addrNonce,proto3" json:"addrNonce,omitempty"` +} + +func (x *RequestSyncTxnPool) Reset() { + *x = RequestSyncTxnPool{} + if protoimpl.UnsafeEnabled { + mi := &file_pb_nodemessage_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestSyncTxnPool) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestSyncTxnPool) ProtoMessage() {} + +func (x *RequestSyncTxnPool) ProtoReflect() protoreflect.Message { + mi := &file_pb_nodemessage_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestSyncTxnPool.ProtoReflect.Descriptor instead. +func (*RequestSyncTxnPool) Descriptor() ([]byte, []int) { + return file_pb_nodemessage_proto_rawDescGZIP(), []int{29} +} + +func (x *RequestSyncTxnPool) GetDuration() int64 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *RequestSyncTxnPool) GetAddrNonce() []*AddrNonce { + if x != nil { + return x.AddrNonce + } + return nil +} + var File_pb_nodemessage_proto protoreflect.FileDescriptor var file_pb_nodemessage_proto_rawDesc = []byte{ @@ -2304,206 +2548,268 @@ var file_pb_nodemessage_proto_rawDesc = []byte{ 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x91, 0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, - 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, - 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, - 0x08, 0x0a, 0x04, 0x56, 0x4f, 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x5f, 0x48, - 0x41, 0x56, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, - 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, - 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x03, - 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, - 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, - 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x05, 0x12, 0x1d, 0x0a, 0x19, 0x47, - 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, - 0x54, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, - 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x10, - 0x07, 0x12, 0x1b, 0x0a, 0x17, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, - 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x08, 0x12, 0x0e, - 0x0a, 0x0a, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x53, 0x10, 0x09, 0x12, 0x14, - 0x0a, 0x10, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x53, 0x5f, 0x52, 0x45, 0x50, - 0x4c, 0x59, 0x10, 0x0a, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x10, 0x0b, 0x12, - 0x10, 0x0a, 0x0c, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, - 0x0c, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x43, 0x4b, 0x54, 0x52, 0x41, 0x43, 0x4b, 0x5f, 0x53, - 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, 0x0d, - 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x50, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x4f, 0x0a, 0x13, 0x54, 0x78, 0x6e, 0x50, 0x6f, 0x6f, + 0x6c, 0x48, 0x61, 0x73, 0x68, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x78, + 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, + 0x78, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3b, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, 0x4e, + 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6e, + 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x5d, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, + 0x79, 0x6e, 0x63, 0x54, 0x78, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x2a, 0xc3, 0x06, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, + 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, + 0x56, 0x4f, 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, + 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, + 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, + 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x20, 0x0a, + 0x1c, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, + 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x04, 0x12, + 0x17, 0x0a, 0x13, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x05, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x45, 0x54, 0x5f, + 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, + 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x54, 0x5f, 0x42, + 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x10, 0x07, 0x12, 0x1b, + 0x0a, 0x17, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, + 0x45, 0x52, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x47, + 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x47, + 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, + 0x0a, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x10, 0x0b, 0x12, 0x10, 0x0a, 0x0c, + 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x12, 0x1d, + 0x0a, 0x19, 0x42, 0x41, 0x43, 0x4b, 0x54, 0x52, 0x41, 0x43, 0x4b, 0x5f, 0x53, 0x49, 0x47, 0x4e, + 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, 0x0d, 0x12, 0x21, 0x0a, + 0x1d, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, + 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0e, + 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, - 0x53, 0x10, 0x0e, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, - 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0f, 0x12, 0x26, 0x0a, 0x22, - 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, - 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, - 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, - 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x11, 0x12, 0x2d, 0x0a, - 0x29, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, - 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x12, 0x12, 0x17, 0x0a, 0x13, - 0x50, 0x49, 0x4e, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, - 0x41, 0x49, 0x4e, 0x10, 0x13, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, - 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x10, 0x14, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, - 0x45, 0x53, 0x10, 0x15, 0x12, 0x14, 0x0a, 0x10, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, - 0x45, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x16, 0x2a, 0x43, 0x0a, 0x18, 0x41, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, - 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, - 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x2a, - 0xe3, 0x07, 0x0a, 0x1a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x55, 0x6e, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, - 0x0a, 0x25, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, - 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, - 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x4c, 0x4c, - 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x56, 0x4f, 0x54, 0x45, - 0x10, 0x01, 0x12, 0x28, 0x0a, 0x24, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, - 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x29, 0x0a, 0x25, - 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, - 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, - 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x26, 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, - 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, - 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x04, 0x12, - 0x26, 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, - 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x05, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x4c, 0x4c, 0x4f, 0x57, - 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, - 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, - 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, - 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x10, 0x07, 0x12, 0x2a, 0x0a, 0x26, 0x41, - 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, - 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x5f, - 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x08, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4c, 0x4c, 0x4f, 0x57, - 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x53, 0x10, 0x09, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, - 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, - 0x43, 0x4b, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x41, + 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0f, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x5f, 0x48, + 0x41, 0x56, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, + 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, + 0x10, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, + 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, + 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x11, 0x12, 0x2d, 0x0a, 0x29, 0x52, 0x45, + 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, + 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x12, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x49, 0x4e, + 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, + 0x10, 0x13, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, + 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, + 0x14, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x10, + 0x15, 0x12, 0x14, 0x0a, 0x10, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x5f, + 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x16, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x51, 0x5f, 0x54, + 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x17, 0x12, 0x15, + 0x0a, 0x11, 0x52, 0x50, 0x4c, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x48, + 0x41, 0x53, 0x48, 0x10, 0x18, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x51, 0x5f, 0x53, 0x59, 0x4e, + 0x43, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x19, 0x12, 0x15, 0x0a, 0x11, + 0x52, 0x50, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, + 0x4c, 0x10, 0x1a, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x51, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, + 0x4e, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x1b, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x50, 0x4c, 0x5f, 0x41, + 0x44, 0x44, 0x52, 0x5f, 0x4e, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x1c, 0x12, 0x15, 0x0a, 0x11, 0x52, + 0x45, 0x51, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x58, 0x4e, + 0x10, 0x1d, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x50, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, + 0x44, 0x44, 0x52, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x1e, 0x2a, 0x43, 0x0a, 0x18, 0x41, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x53, + 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, + 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x2a, 0x8d, + 0x0a, 0x0a, 0x1a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, + 0x25, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, + 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, + 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x56, 0x4f, 0x54, 0x45, 0x10, + 0x01, 0x12, 0x28, 0x0a, 0x24, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, + 0x4e, 0x45, 0x44, 0x5f, 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, + 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x29, 0x0a, 0x25, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, - 0x4c, 0x41, 0x59, 0x10, 0x0b, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, - 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, - 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x54, 0x52, 0x41, - 0x43, 0x4b, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, - 0x49, 0x4e, 0x10, 0x0d, 0x12, 0x30, 0x0a, 0x2c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, - 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, - 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0e, 0x12, 0x36, 0x0a, 0x32, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, + 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, + 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x26, 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, - 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0f, 0x12, 0x35, - 0x0a, 0x31, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, - 0x5f, 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, - 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x36, 0x0a, 0x32, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, + 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x04, 0x12, 0x26, + 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, + 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x45, 0x10, 0x05, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, + 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, + 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x50, + 0x4c, 0x59, 0x10, 0x06, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, + 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, + 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x10, 0x07, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x4c, + 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, + 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x5f, 0x52, + 0x45, 0x50, 0x4c, 0x59, 0x10, 0x08, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, + 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, + 0x43, 0x4b, 0x53, 0x10, 0x09, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, + 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, + 0x4b, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x4c, + 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x4c, + 0x41, 0x59, 0x10, 0x0b, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, + 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, + 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x54, 0x52, 0x41, 0x43, + 0x4b, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, + 0x4e, 0x10, 0x0d, 0x12, 0x30, 0x0a, 0x2c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, + 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, + 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x53, 0x10, 0x0e, 0x12, 0x36, 0x0a, 0x32, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, - 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, - 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x11, 0x12, 0x3c, 0x0a, - 0x38, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, + 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, + 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0f, 0x12, 0x35, 0x0a, + 0x31, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, + 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, + 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x36, 0x0a, 0x32, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, + 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, + 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, + 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x11, 0x12, 0x3c, 0x0a, 0x38, + 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, + 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, + 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x12, 0x12, 0x26, 0x0a, 0x22, 0x41, 0x4c, + 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x50, 0x49, 0x4e, + 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, + 0x10, 0x13, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, + 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, + 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x14, + 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, + 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x10, 0x15, 0x12, + 0x23, 0x0a, 0x1f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, + 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x50, + 0x4c, 0x59, 0x10, 0x16, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, + 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, + 0x4f, 0x4f, 0x4c, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x17, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, + 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x50, 0x4c, + 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x18, + 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, + 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, 0x58, 0x4e, 0x5f, + 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x19, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, + 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x50, 0x4c, 0x5f, 0x53, 0x59, 0x4e, + 0x43, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x1a, 0x12, 0x21, 0x0a, 0x1d, + 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, + 0x45, 0x51, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x4e, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x1b, 0x12, + 0x21, 0x0a, 0x1d, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, + 0x44, 0x5f, 0x52, 0x50, 0x4c, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x4e, 0x4f, 0x4e, 0x43, 0x45, + 0x10, 0x1c, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, + 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x44, + 0x44, 0x52, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x1d, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x52, 0x50, 0x4c, 0x5f, 0x53, + 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x1e, 0x2a, 0x96, + 0x09, 0x0a, 0x18, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x41, + 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x4c, 0x41, 0x43, + 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, + 0x53, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, + 0x52, 0x45, 0x43, 0x54, 0x5f, 0x56, 0x4f, 0x54, 0x45, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x41, + 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x49, 0x5f, 0x48, 0x41, + 0x56, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, + 0x4c, 0x10, 0x02, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, + 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, + 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, + 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, + 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, + 0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, + 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x05, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, + 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x50, + 0x4c, 0x59, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, + 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, + 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x10, 0x07, 0x12, 0x28, 0x0a, 0x24, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, + 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, + 0x10, 0x08, 0x12, 0x1b, 0x0a, 0x17, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, + 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x53, 0x10, 0x09, 0x12, + 0x21, 0x0a, 0x1d, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, + 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, + 0x10, 0x0a, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, + 0x43, 0x54, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x54, 0x52, 0x41, 0x43, 0x4b, 0x5f, 0x53, 0x49, 0x47, + 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, 0x0d, 0x12, 0x2e, + 0x0a, 0x2a, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, + 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, + 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0e, 0x12, 0x34, + 0x0a, 0x30, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, + 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, + 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x50, + 0x4c, 0x59, 0x10, 0x0f, 0x12, 0x33, 0x0a, 0x2f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, + 0x52, 0x45, 0x43, 0x54, 0x5f, 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, + 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, + 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x34, 0x0a, 0x30, 0x41, 0x4c, 0x4c, + 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, + 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, + 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x11, 0x12, + 0x3a, 0x0a, 0x36, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x12, 0x12, 0x26, 0x0a, 0x22, 0x41, - 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x50, 0x49, - 0x4e, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, - 0x4e, 0x10, 0x13, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, - 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, - 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, - 0x14, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, - 0x4e, 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x10, 0x15, - 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, - 0x45, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x5f, 0x52, 0x45, - 0x50, 0x4c, 0x59, 0x10, 0x16, 0x2a, 0xfc, 0x06, 0x0a, 0x18, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, - 0x43, 0x54, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, - 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x41, - 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x56, 0x4f, 0x54, 0x45, - 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, - 0x43, 0x54, 0x5f, 0x49, 0x5f, 0x48, 0x41, 0x56, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, - 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x4c, - 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, - 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, - 0x4c, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, - 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, - 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, - 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x05, 0x12, - 0x2a, 0x0a, 0x26, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, - 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x4e, 0x53, 0x55, 0x53, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x41, - 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, - 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x53, 0x10, 0x07, 0x12, - 0x28, 0x0a, 0x24, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, - 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, - 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x08, 0x12, 0x1b, 0x0a, 0x17, 0x41, 0x4c, 0x4c, - 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x53, 0x10, 0x09, 0x12, 0x21, 0x0a, 0x1d, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, - 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, - 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0a, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x4c, 0x4c, - 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x54, 0x52, - 0x41, 0x43, 0x4b, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, - 0x41, 0x49, 0x4e, 0x10, 0x0d, 0x12, 0x2e, 0x0a, 0x2a, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, - 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, - 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x53, 0x10, 0x0e, 0x12, 0x34, 0x0a, 0x30, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, - 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x50, 0x52, - 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x0f, 0x12, 0x33, 0x0a, 0x2f, 0x41, - 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x49, 0x5f, 0x48, 0x41, - 0x56, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, - 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x10, - 0x12, 0x34, 0x0a, 0x30, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, - 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, - 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x11, 0x12, 0x3a, 0x0a, 0x36, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, - 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, - 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, - 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, - 0x10, 0x12, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, - 0x43, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, - 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, 0x13, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x4c, 0x4c, 0x4f, - 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, - 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x10, 0x14, 0x12, 0x1b, 0x0a, 0x17, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, - 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x10, - 0x15, 0x12, 0x21, 0x0a, 0x1d, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, - 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x50, - 0x4c, 0x59, 0x10, 0x16, 0x2a, 0x58, 0x0a, 0x17, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, - 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x26, 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x50, - 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, - 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x4c, 0x4c, 0x4f, 0x57, - 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x10, 0x0b, 0x2a, 0x79, - 0x0a, 0x1f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, - 0x73, 0x74, 0x50, 0x75, 0x73, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x2f, 0x0a, 0x2b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, - 0x43, 0x41, 0x53, 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, - 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, - 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, 0x41, - 0x44, 0x43, 0x41, 0x53, 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x2a, 0x52, 0x0a, 0x1f, 0x41, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x64, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x50, 0x75, 0x6c, - 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x2b, - 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, 0x5f, - 0x50, 0x55, 0x4c, 0x4c, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, - 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x2a, 0x79, 0x0a, - 0x1f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x2f, 0x0a, 0x2b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, 0x43, - 0x41, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, - 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, - 0x00, 0x12, 0x25, 0x0a, 0x21, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, - 0x43, 0x41, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x2a, 0x78, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x46, 0x55, - 0x4c, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, - 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x41, 0x4e, - 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, 0x12, 0x22, - 0x0a, 0x1e, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x48, 0x4f, 0x52, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, - 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x12, 0x12, 0x24, 0x0a, 0x20, 0x41, + 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, + 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, + 0x13, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, + 0x54, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x49, + 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x14, 0x12, 0x1b, 0x0a, + 0x17, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, + 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x53, 0x10, 0x15, 0x12, 0x21, 0x0a, 0x1d, 0x41, 0x4c, + 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x16, 0x12, 0x22, 0x0a, + 0x1e, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, + 0x51, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, + 0x17, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, + 0x54, 0x5f, 0x52, 0x50, 0x4c, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x48, + 0x41, 0x53, 0x48, 0x10, 0x18, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, + 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, + 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x19, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x4c, 0x4c, + 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x50, 0x4c, 0x5f, 0x53, 0x59, + 0x4e, 0x43, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x1a, 0x12, 0x1f, 0x0a, + 0x1b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, + 0x51, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x4e, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x1b, 0x12, 0x1f, + 0x0a, 0x1b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x52, + 0x50, 0x4c, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x4e, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x1c, 0x12, + 0x22, 0x0a, 0x1e, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, + 0x52, 0x45, 0x51, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x58, + 0x4e, 0x10, 0x1d, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x49, 0x52, + 0x45, 0x43, 0x54, 0x5f, 0x52, 0x50, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x44, 0x44, + 0x52, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x1e, 0x2a, 0x58, 0x0a, 0x17, 0x41, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x26, 0x0a, 0x22, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x52, 0x45, 0x4c, 0x41, + 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, + 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x4c, + 0x4c, 0x4f, 0x57, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x10, + 0x0b, 0x2a, 0x79, 0x0a, 0x1f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x42, 0x72, 0x6f, 0x61, + 0x64, 0x63, 0x61, 0x73, 0x74, 0x50, 0x75, 0x73, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x2b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, + 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x5f, 0x50, 0x4c, 0x41, + 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, + 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, + 0x52, 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x5f, 0x54, 0x52, + 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x2a, 0x52, 0x0a, 0x1f, + 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, + 0x50, 0x75, 0x6c, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x2f, 0x0a, 0x2b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, 0x43, 0x41, + 0x53, 0x54, 0x5f, 0x50, 0x55, 0x4c, 0x4c, 0x5f, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, + 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, + 0x2a, 0x79, 0x0a, 0x1f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x42, 0x72, 0x6f, 0x61, 0x64, + 0x63, 0x61, 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x2b, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, 0x4f, + 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x4c, 0x41, 0x43, + 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x55, + 0x53, 0x45, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x52, + 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x54, 0x52, 0x41, + 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0c, 0x2a, 0x78, 0x0a, 0x16, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x54, + 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, + 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x41, + 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x48, 0x4f, 0x52, 0x54, 0x5f, 0x48, + 0x41, 0x53, 0x48, 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2519,7 +2825,7 @@ func file_pb_nodemessage_proto_rawDescGZIP() []byte { } var file_pb_nodemessage_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_pb_nodemessage_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_pb_nodemessage_proto_msgTypes = make([]protoimpl.MessageInfo, 30) var file_pb_nodemessage_proto_goTypes = []interface{}{ (MessageType)(0), // 0: pb.MessageType (AllowedSignedMessageType)(0), // 1: pb.AllowedSignedMessageType @@ -2557,31 +2863,35 @@ var file_pb_nodemessage_proto_goTypes = []interface{}{ (*PinSignatureChain)(nil), // 33: pb.PinSignatureChain (*SignatureChainObjectionUnsigned)(nil), // 34: pb.SignatureChainObjectionUnsigned (*SignatureChainObjectionSigned)(nil), // 35: pb.SignatureChainObjectionSigned - (*Block)(nil), // 36: pb.Block - (*Transaction)(nil), // 37: pb.Transaction - (SyncState)(0), // 38: pb.SyncState - (*Header)(nil), // 39: pb.Header - (*SigChainElem)(nil), // 40: pb.SigChainElem + (*TxnPoolHashAndCount)(nil), // 36: pb.TxnPoolHashAndCount + (*AddrNonce)(nil), // 37: pb.AddrNonce + (*RequestSyncTxnPool)(nil), // 38: pb.RequestSyncTxnPool + (*Block)(nil), // 39: pb.Block + (*Transaction)(nil), // 40: pb.Transaction + (SyncState)(0), // 41: pb.SyncState + (*Header)(nil), // 42: pb.Header + (*SigChainElem)(nil), // 43: pb.SigChainElem } var file_pb_nodemessage_proto_depIdxs = []int32{ 0, // 0: pb.UnsignedMessage.message_type:type_name -> pb.MessageType 8, // 1: pb.RequestBlockProposal.type:type_name -> pb.RequestTransactionType - 36, // 2: pb.RequestBlockProposalReply.block:type_name -> pb.Block + 39, // 2: pb.RequestBlockProposalReply.block:type_name -> pb.Block 8, // 3: pb.RequestProposalTransactions.type:type_name -> pb.RequestTransactionType - 37, // 4: pb.RequestProposalTransactionsReply.transactions:type_name -> pb.Transaction - 38, // 5: pb.GetConsensusStateReply.sync_state:type_name -> pb.SyncState - 39, // 6: pb.GetBlockHeadersReply.block_headers:type_name -> pb.Header - 36, // 7: pb.GetBlocksReply.blocks:type_name -> pb.Block + 40, // 4: pb.RequestProposalTransactionsReply.transactions:type_name -> pb.Transaction + 41, // 5: pb.GetConsensusStateReply.sync_state:type_name -> pb.SyncState + 42, // 6: pb.GetBlockHeadersReply.block_headers:type_name -> pb.Header + 39, // 7: pb.GetBlocksReply.blocks:type_name -> pb.Block 23, // 8: pb.GetStates.reqs:type_name -> pb.StateRequest 24, // 9: pb.GetStatesReply.nodes:type_name -> pb.StateNode - 37, // 10: pb.Transactions.transactions:type_name -> pb.Transaction - 40, // 11: pb.BacktrackSignatureChain.sig_chain_elems:type_name -> pb.SigChainElem - 37, // 12: pb.RequestSignatureChainTransactionReply.transaction:type_name -> pb.Transaction - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 40, // 10: pb.Transactions.transactions:type_name -> pb.Transaction + 43, // 11: pb.BacktrackSignatureChain.sig_chain_elems:type_name -> pb.SigChainElem + 40, // 12: pb.RequestSignatureChainTransactionReply.transaction:type_name -> pb.Transaction + 37, // 13: pb.RequestSyncTxnPool.addrNonce:type_name -> pb.AddrNonce + 14, // [14:14] is the sub-list for method output_type + 14, // [14:14] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_pb_nodemessage_proto_init() } @@ -2918,6 +3228,42 @@ func file_pb_nodemessage_proto_init() { return nil } } + file_pb_nodemessage_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TxnPoolHashAndCount); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pb_nodemessage_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddrNonce); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pb_nodemessage_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestSyncTxnPool); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -2925,7 +3271,7 @@ func file_pb_nodemessage_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pb_nodemessage_proto_rawDesc, NumEnums: 9, - NumMessages: 27, + NumMessages: 30, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/nodemessage.proto b/pb/nodemessage.proto index 89eccbb70..a39bf542a 100644 --- a/pb/nodemessage.proto +++ b/pb/nodemessage.proto @@ -33,6 +33,19 @@ enum MessageType { SIGNATURE_CHAIN_OBJECTION = 20; GET_STATES = 21; GET_STATES_REPLY = 22; + + // sync txn pool + REQ_TXN_POOL_HASH = 23; // request txn pool hash + RPL_TXN_POOL_HASH = 24; // reply txn pool hash + REQ_SYNC_TXN_POOL = 25; // request to sync txn pool + RPL_SYNC_TXN_POOL = 26; // reply to sync txn pool + + // sync random address transaction + REQ_ADDR_NONCE = 27; // reques for random address and nonce + RPL_ADDR_NONCE = 28; // reply random address and nonce in txn pool + REQ_SYNC_ADDR_TXN = 29; // request for syncing this address transactions + RPL_SYNC_ADDR_TXN = 30; // reply this address' transactions + } // Message type that can be signed message @@ -67,6 +80,19 @@ enum AllowedUnsignedMessageType { ALLOW_UNSIGNED_SIGNATURE_CHAIN_OBJECTION = 20; ALLOW_UNSIGNED_GET_STATES = 21; ALLOW_UNSIGNED_GET_STATES_REPLY = 22; + + // sync txn pool + ALLOW_UNSIGNED_REQ_TXN_POOL_HASH = 23; // request txn pool hash + ALLOW_UNSIGNED_RPL_TXN_POOL_HASH = 24; // reply txn pool hash + ALLOW_UNSIGNED_REQ_SYNC_TXN_POOL = 25; // request to sync txn pool + ALLOW_UNSIGNED_RPL_SYNC_TXN_POOL = 26; // reply to sync txn pool + + // sync random address transaction + ALLOW_UNSIGNED_REQ_ADDR_NONCE = 27; // reques for random address and nonce + ALLOW_UNSIGNED_RPL_ADDR_NONCE = 28; // reply random address and nonce in txn pool + ALLOW_UNSIGNED_REQ_SYNC_ADDR_TXN = 29; // request for syncing this address transactions + ALLOW_UNSIGNED_RPL_SYNC_ADDR_TXN = 30; // reply this address' transactions + } // Message type that can be sent as direct message @@ -93,6 +119,19 @@ enum AllowedDirectMessageType { ALLOW_DIRECT_SIGNATURE_CHAIN_OBJECTION = 20; ALLOW_DIRECT_GET_STATES = 21; ALLOW_DIRECT_GET_STATES_REPLY = 22; + + // sync txn pool + ALLOW_DIRECT_REQ_TXN_POOL_HASH = 23; // request txn pool hash + ALLOW_DIRECT_RPL_TXN_POOL_HASH = 24; // reply txn pool hash + ALLOW_DIRECT_REQ_SYNC_TXN_POOL = 25; // request to sync txn pool + ALLOW_DIRECT_RPL_SYNC_TXN_POOL = 26; // reply to sync txn pool + + // sync random address transaction + ALLOW_DIRECT_REQ_ADDR_NONCE = 27; // reques for random address and nonce + ALLOW_DIRECT_RPL_ADDR_NONCE = 28; // reply random address and nonce in txn pool + ALLOW_DIRECT_REQ_SYNC_ADDR_TXN = 29; // request for syncing this address transactions + ALLOW_DIRECT_RPL_SYNC_ADDR_TXN = 30; // reply this address' transactions + } // Message type that can be sent as relay message @@ -266,3 +305,21 @@ message SignatureChainObjectionSigned { bytes message = 1; bytes signature = 2; } + +// sync txn pool +message TxnPoolHashAndCount { + bytes pool_hash = 1; + uint32 txn_count = 2; +} + +message AddrNonce { + bytes address = 1; + uint64 nonce = 2; +} + +message RequestSyncTxnPool { + int64 duration = 1; + repeated AddrNonce addrNonce = 2; +} + +