This commit is contained in:
alex.sharov 2021-07-26 19:13:07 +07:00
parent 7d2a8c7e85
commit 585475978e
4 changed files with 150 additions and 72 deletions

View File

@ -190,7 +190,6 @@ func (f *Fetch) handleInboundMessage(req *sentry.InboundMessage, sentryClient se
}
var hashbuf [32]byte
var unknownHashes Hashes
var unknownCount int
for i := 0; i < hashCount; i++ {
_, pos, err = ParseHash(req.Data, pos, hashbuf[:0])
if err != nil {
@ -204,12 +203,12 @@ func (f *Fetch) handleInboundMessage(req *sentry.InboundMessage, sentryClient se
var encodedRequest []byte
var messageId sentry.MessageId
if req.Id == sentry.MessageId_NEW_POOLED_TRANSACTION_HASHES_66 {
if encodedRequest, err = EncodeGetPooledTransactions66(unknownHashes, unknownCount, uint64(1), nil); err != nil {
if encodedRequest, err = EncodeGetPooledTransactions66(unknownHashes, uint64(1), nil); err != nil {
return err
}
messageId = sentry.MessageId_GET_POOLED_TRANSACTIONS_66
} else {
if encodedRequest, err = EncodeHashes(unknownHashes, unknownCount, nil); err != nil {
if encodedRequest, err = EncodeHashes(unknownHashes, nil); err != nil {
return err
}
messageId = sentry.MessageId_GET_POOLED_TRANSACTIONS_65

View File

@ -81,42 +81,120 @@ func ParseHashesCount(payload []byte, pos int) (int, int, error) {
// It appends encoding to the given given slice (encodeBuf), reusing the space
// there is there is enough capacity.
// The first returned value is the slice where encodinfg
func EncodeHashes(hashes Hashes, count int, encodeBuf []byte) ([]byte, error) {
dataLen := count * 33
var beLen int
if dataLen >= 56 {
beLen = (bits.Len64(uint64(dataLen)) + 7) / 8
}
prefixLen := 1 + beLen
func EncodeHashes(hashes Hashes, encodeBuf []byte) ([]byte, error) {
dataLen := len(hashes) / 32 * 33
prefixLen := rlpListPrefixLen(dataLen)
var encoding []byte
if total := len(encodeBuf) + dataLen + prefixLen; cap(encodeBuf) >= total {
encoding = encodeBuf[:dataLen+prefixLen] // Reuse the space in pkbuf, is it has enough capacity
if total := dataLen + prefixLen; cap(encodeBuf) >= total {
encoding = encodeBuf[:total] // Reuse the space in pkbuf, is it has enough capacity
} else {
encoding = make([]byte, total)
copy(encoding, encodeBuf)
}
if dataLen < 56 {
encoding[0] = 192 + byte(dataLen)
} else {
encoding[0] = 247 + byte(beLen)
binary.BigEndian.PutUint64(encoding[1:], uint64(beLen))
copy(encoding[1:], encoding[9-beLen:9])
}
hashP := 0
rlpListPrefix(dataLen, encoding)
encP := prefixLen
for i := 0; i < count; i++ {
encoding[encP] = 128 + 32
copy(encoding[encP+1:encP+33], hashes[hashP:hashP+32])
for i := 0; i < len(hashes); i += 32 {
rlpEncodeString(hashes[i:i+32], encoding[encP:])
encP += 33
hashP += 32
}
return encoding, nil
}
func rlpListPrefixLen(dataLen int) int {
if dataLen >= 56 {
return 1 + (bits.Len64(uint64(dataLen))+7)/8
}
return 1
}
func rlpListPrefix(dataLen int, to []byte) {
if dataLen >= 56 {
_ = to[9]
beLen := (bits.Len64(uint64(dataLen)) + 7) / 8
binary.BigEndian.PutUint64(to[1:], uint64(dataLen))
to[8-beLen] = 247 + byte(beLen)
copy(to, to[8-beLen:9])
return
}
to[0] = 192 + byte(dataLen)
}
func rlpU64Len(i uint64) int {
if i > 128 {
return 1 + (bits.Len64(i)+7)/8
}
return 1
}
func rlpU64(i uint64, to []byte) {
/*
if requestId == 0 || requestId > 128 {
encoding[pos] = 128 + byte(requestIdLen)
} else {
encoding[pos] = byte(requestId)
}
*/
if i > 128 {
l := (bits.Len64(i) + 7) / 8
to[0] = 128 + byte(l)
binary.BigEndian.PutUint64(to[1:], i)
copy(to[1:], to[1+8-l:1+8])
return
}
if i == 0 {
to[0] = 128
return
}
to[0] = byte(i)
return
//if i == 0 {
// w.str = append(w.str, 0x80)
//} else if i < 128 {
//w.str = append(w.str, byte(i))
//} else {
// s := putint(w.sizebuf[1:], i)
// w.sizebuf[0] = 0x80 + byte(s)
// w.str = append(w.str, w.sizebuf[:s+1]...)
//}
}
func rlpEncodeString(s []byte, to []byte) {
switch {
case len(s) > 56:
beLen := (bits.Len(uint(len(s))) + 7) / 8
binary.BigEndian.PutUint64(to[1:], uint64(len(s)))
_ = to[beLen+len(s)]
to[8-beLen] = byte(beLen) + 183
copy(to, to[8-beLen:9])
copy(to[1+beLen:], s)
case len(s) == 0:
to[0] = 128
case len(s) == 1:
_ = to[1]
if s[0] >= 128 {
to[0] = 129
}
copy(to[1:], s)
default: // 1<s<56
_ = to[len(s)]
to[0] = byte(len(s)) + 128
copy(to[1:], s)
}
}
// we know that it's 32bytes long, and we know that we have enough space
func rlpEncodeHash(h, to []byte) {
_ = to[32] // early bounds check to guarantee safety of writes below
to[0] = 128 + 32
copy(to[1:33], h)
}
// EncodeGetPooledTransactions66 produces encoding of GetPooledTransactions66 packet
func EncodeGetPooledTransactions66(hashes []byte, count int, requestId uint64, encodeBuf []byte) ([]byte, error) {
func EncodeGetPooledTransactions66(hashes []byte, requestId uint64, encodeBuf []byte) ([]byte, error) {
requestIdLen := (bits.Len64(requestId) + 7) / 8
hashesLen := count * 33
hashesLen := len(hashes) / 32 * 33
var hashesBeLen int
if hashesLen >= 56 {
hashesBeLen = (bits.Len64(uint64(hashesLen)) + 7) / 8
@ -125,58 +203,39 @@ func EncodeGetPooledTransactions66(hashes []byte, count int, requestId uint64, e
if requestId == 0 || requestId >= 128 {
dataLen++
}
var dataBeLen int
if dataLen >= 56 {
dataBeLen = (bits.Len64(uint64(dataLen)) + 7) / 8
}
prefixLen := 1 + dataBeLen
prefixLen := rlpListPrefixLen(dataLen)
var encoding []byte
if total := len(encodeBuf) + dataLen + prefixLen; cap(encodeBuf) >= total {
if total := dataLen + prefixLen; cap(encodeBuf) >= total {
encoding = encodeBuf[:dataLen+prefixLen] // Reuse the space in pkbuf, is it has enough capacity
} else {
encoding = make([]byte, total)
copy(encoding, encodeBuf)
}
pos := 0
// Length prefix for the entire structure
if dataLen < 56 {
encoding[pos] = 192 + byte(dataLen)
} else {
encoding[pos] = 247 + byte(dataBeLen)
binary.BigEndian.PutUint64(encoding[pos+1:], uint64(dataBeLen))
copy(encoding[pos+1:], encoding[pos+9-dataBeLen:pos+9])
}
pos += prefixLen
rlpListPrefix(dataLen, encoding)
pos := prefixLen
// encode requestId
if requestId == 0 || requestId > 128 {
encoding[pos] = 128 + byte(requestIdLen)
} else {
encoding[pos] = byte(requestId)
}
pos++
rlpU64(requestId, encoding[pos:])
//if requestId == 0 || requestId > 128 {
// encoding[pos] = 128 + byte(requestIdLen)
//} else {
// encoding[pos] = byte(requestId)
//}
//pos++
if requestId > 128 {
binary.BigEndian.PutUint64(encoding[pos:], requestId)
copy(encoding[pos:], encoding[pos+8-requestIdLen:pos+8])
pos += requestIdLen
//binary.BigEndian.PutUint64(encoding[pos:], requestId)
//copy(encoding[pos:], encoding[pos+8-requestIdLen:pos+8])
//pos += requestIdLen
}
fmt.Printf("aa: %d,%d,%d\n", requestId, rlpU64Len(requestId), requestIdLen)
pos += rlpU64Len(requestId)
// Encode length prefix for hashes
if hashesLen < 56 {
encoding[pos] = 192 + byte(hashesLen)
pos++
} else {
encoding[pos] = 247 + byte(hashesBeLen)
pos++
binary.BigEndian.PutUint64(encoding[pos:], uint64(hashesBeLen))
copy(encoding[pos:], encoding[pos+8-hashesBeLen:pos+8])
pos += hashesBeLen
}
hashP := 0
for i := 0; i < count; i++ {
encoding[pos] = 128 + 32
pos++
copy(encoding[pos:pos+32], hashes[hashP:hashP+32])
pos += 32
hashP += 32
rlpListPrefix(hashesLen, encoding[pos:])
pos += rlpListPrefixLen(hashesLen)
for i := 0; i < len(hashes); i += 32 {
rlpEncodeHash(hashes[i:i+32], encoding[pos:pos+33])
pos += 33
}
return encoding, nil
}

View File

@ -72,6 +72,8 @@ var hashEncodeTests = []struct {
}{
{payloadStr: "e1a0595e27a835cd79729ff1eeacec3120eeb6ed1464a04ec727aaca734ead961328",
hashesStr: "595e27a835cd79729ff1eeacec3120eeb6ed1464a04ec727aaca734ead961328", hashCount: 1, expectedErr: false},
{hashesStr: fmt.Sprintf("%x", toHashes([32]byte{1}, [32]byte{2}, [32]byte{3})),
payloadStr: "f863a00100000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000", hashCount: 3, expectedErr: false},
}
func TestEncodeHash(t *testing.T) {
@ -87,7 +89,7 @@ func TestEncodeHash(t *testing.T) {
if hashes, err = hex.DecodeString(tt.hashesStr); err != nil {
t.Fatal(err)
}
if encodeBuf, err = EncodeHashes(hashes, tt.hashCount, encodeBuf); err != nil {
if encodeBuf, err = EncodeHashes(hashes, encodeBuf); err != nil {
if !tt.expectedErr {
t.Fatal(err)
}
@ -126,7 +128,7 @@ func TestEncodeGPT66(t *testing.T) {
if hashes, err = hex.DecodeString(tt.hashesStr); err != nil {
t.Fatal(err)
}
if encodeBuf, err = EncodeGetPooledTransactions66(hashes, tt.hashCount, tt.requestId, encodeBuf); err != nil {
if encodeBuf, err = EncodeGetPooledTransactions66(hashes, tt.requestId, encodeBuf); err != nil {
if !tt.expectedErr {
t.Fatal(err)
}
@ -139,3 +141,21 @@ func TestEncodeGPT66(t *testing.T) {
})
}
}
func BenchmarkEncHashes(b *testing.B) {
h := make(Hashes, 32*40)
buf := make([]byte, 39*40)
for i := 0; i < b.N; i++ {
buf = buf[:0]
EncodeHashes(h, buf)
}
}
func BenchmarkEncHashes2(b *testing.B) {
h := make(Hashes, 32*40)
buf := make([]byte, 39*40)
for i := 0; i < b.N; i++ {
buf = buf[:0]
EncodeHashes(h, buf)
}
}

View File

@ -85,7 +85,7 @@ func (f *Send) BroadcastLocalPooledTxs(txs Hashes) (sentToPeers int) {
txs = txs[:0]
}
data, err := EncodeHashes(pending, len(pending)/32, nil)
data, err := EncodeHashes(pending, nil)
if err != nil {
f.logger.Warnf("encode hashes: %s", err)
return
@ -145,7 +145,7 @@ func (f *Send) BroadcastRemotePooledTxs(txs Hashes) {
txs = txs[:0]
}
data, err := EncodeHashes(pending, len(pending)/32, nil)
data, err := EncodeHashes(pending, nil)
if err != nil {
f.logger.Warnf("encode hashes: %s", err)
return
@ -207,7 +207,7 @@ func (f *Send) PropagatePooledTxsToPeersList(peers []PeerID, txs []byte) {
txs = txs[:0]
}
data, err := EncodeHashes(pending, len(pending)/32, nil)
data, err := EncodeHashes(pending, nil)
if err != nil {
f.logger.Warnf("encode hashes: %s", err)
return