From 29b27c11468c9a25fefb89c91f87cb39f5e826bc Mon Sep 17 00:00:00 2001 From: lklimek <842586+lklimek@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:58:47 +0100 Subject: [PATCH 1/3] fix: ordered map race condition (#708) * chore(release): update changelog and version to 0.13.2 * chore(release): update changelog and version to 0.13.3 * fix: make OrderedMap thread-safe --- CHANGELOG.md | 21 +++++++++++++++++++++ libs/ds/ordered_map.go | 26 +++++++++++++++++++++++++- libs/ds/ordered_map_test.go | 19 +++++++++++++++++++ version/version.go | 2 +- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2ebdd8ff3..1b63e7136c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## [0.13.3] - 2023-10-16 + +### Bug Fixes + +- Issue with GMP not properly being linked on mac (#698) +- Always propose with current app version (#697) + +## [0.13.2] - 2023-10-09 + +### Bug Fixes + +- Log-file-path setting does not work (#691) + +### Miscellaneous Tasks + +- Update changelog and version to 0.13.2 + ## [0.13.1] - 2023-09-14 ### Bug Fixes @@ -5,6 +22,10 @@ - Send evidence only once (#683) - Panic verifying evidence due to missing pubkey (#684) +### Miscellaneous Tasks + +- Update changelog and version to 0.13.1 + ## [0.13.0] - 2023-09-13 ### Bug Fixes diff --git a/libs/ds/ordered_map.go b/libs/ds/ordered_map.go index 99e471c066..e7be78ebf0 100644 --- a/libs/ds/ordered_map.go +++ b/libs/ds/ordered_map.go @@ -1,11 +1,14 @@ package ds +import "sync" + // OrderedMap is a map with a deterministic iteration order -// this datastructure is not thread-safe +// this datastructure is thread-safe type OrderedMap[T comparable, V any] struct { len int keys map[T]int values []V + mtx sync.RWMutex } // NewOrderedMap returns a new OrderedMap @@ -17,6 +20,9 @@ func NewOrderedMap[T comparable, V any]() *OrderedMap[T, V] { // Put adds a key-value pair to the map func (m *OrderedMap[T, V]) Put(key T, val V) { + m.mtx.Lock() + defer m.mtx.Unlock() + i, ok := m.keys[key] if ok { m.values[i] = val @@ -33,6 +39,9 @@ func (m *OrderedMap[T, V]) Put(key T, val V) { // Get returns the value for a given key func (m *OrderedMap[T, V]) Get(key T) (V, bool) { + m.mtx.RLock() + defer m.mtx.RUnlock() + i, ok := m.keys[key] if !ok { var v V @@ -43,12 +52,18 @@ func (m *OrderedMap[T, V]) Get(key T) (V, bool) { // Has returns true if the map contains the given key func (m *OrderedMap[T, V]) Has(key T) bool { + m.mtx.RLock() + defer m.mtx.RUnlock() + _, ok := m.keys[key] return ok } // Delete removes a key-value pair from the map func (m *OrderedMap[T, V]) Delete(key T) { + m.mtx.Lock() + defer m.mtx.Unlock() + i, ok := m.keys[key] if !ok { return @@ -63,11 +78,17 @@ func (m *OrderedMap[T, V]) Delete(key T) { // Values returns all values in the map func (m *OrderedMap[T, V]) Values() []V { + m.mtx.RLock() + defer m.mtx.RUnlock() + return append([]V{}, m.values[0:m.len]...) } // Keys returns all keys in the map func (m *OrderedMap[T, V]) Keys() []T { + m.mtx.RLock() + defer m.mtx.RUnlock() + keys := make([]T, len(m.keys)) for k, v := range m.keys { keys[v] = k @@ -77,5 +98,8 @@ func (m *OrderedMap[T, V]) Keys() []T { // Len returns a number of the map func (m *OrderedMap[T, V]) Len() int { + m.mtx.RLock() + defer m.mtx.RUnlock() + return m.len } diff --git a/libs/ds/ordered_map_test.go b/libs/ds/ordered_map_test.go index 15a96f0252..3ed15647a5 100644 --- a/libs/ds/ordered_map_test.go +++ b/libs/ds/ordered_map_test.go @@ -1,6 +1,8 @@ package ds import ( + "strconv" + "sync" "testing" "github.com/stretchr/testify/require" @@ -40,3 +42,20 @@ func TestOrderedMap(t *testing.T) { // delete unknown key om.Delete("c") } + +// / Run TestOrderedMap in parallel +func TestOrderedMapMultithread(t *testing.T) { + threads := 100 + + wg := sync.WaitGroup{} + wg.Add(threads) + + for i := 0; i < threads; i++ { + go func(id int) { + t.Run(strconv.FormatInt(int64(id), 10), TestOrderedMap) + wg.Done() + }(i) + } + + wg.Wait() +} diff --git a/version/version.go b/version/version.go index 70dec25555..8e1bb184b4 100644 --- a/version/version.go +++ b/version/version.go @@ -9,7 +9,7 @@ var ( const ( // TMVersionDefault is the used as the fallback version for Tenderdash // when not using git describe. It is formatted with semantic versioning. - TMVersionDefault = "0.13.1" + TMVersionDefault = "0.13.3" // ABCISemVer is the semantic version of the ABCI library ABCISemVer = "0.23.0" From 6548b5674d053fd86c35a20d8078600437708a88 Mon Sep 17 00:00:00 2001 From: lklimek <842586+lklimek@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:17:41 +0100 Subject: [PATCH 2/3] perf: increase web socket channels capacity (#709) * chore(release): update changelog and version to 0.13.2 * chore(release): update changelog and version to 0.13.3 * chore: increase defaultWSWriteChanCapacity 100 -> 500 * chore: subBufferSize 500 --- internal/rpc/core/events.go | 2 +- rpc/jsonrpc/server/ws_handler.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/rpc/core/events.go b/internal/rpc/core/events.go index 023d45a2d7..da8e6088ee 100644 --- a/internal/rpc/core/events.go +++ b/internal/rpc/core/events.go @@ -17,7 +17,7 @@ import ( const ( // Buffer on the Tendermint (server) side to allow some slowness in clients. - subBufferSize = 100 + subBufferSize = 500 // maxQueryLength is the maximum length of a query string that will be // accepted. This is just a safety check to avoid outlandish queries. diff --git a/rpc/jsonrpc/server/ws_handler.go b/rpc/jsonrpc/server/ws_handler.go index bb897680e4..0f9ed2daba 100644 --- a/rpc/jsonrpc/server/ws_handler.go +++ b/rpc/jsonrpc/server/ws_handler.go @@ -17,7 +17,7 @@ import ( // WebSocket handler const ( - defaultWSWriteChanCapacity = 100 + defaultWSWriteChanCapacity = 500 defaultWSWriteWait = 10 * time.Second defaultWSReadWait = 30 * time.Second defaultWSPingPeriod = (defaultWSReadWait * 9) / 10 From cddc1fa6b24465e99f036ddcf9b113dee5153209 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:38:48 +0100 Subject: [PATCH 3/3] chore(release): update changelog and version to 0.13.4 --- CHANGELOG.md | 14 ++++++++++++++ version/version.go | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b63e7136c..0ee2d1966e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [0.13.4] - 2023-12-11 + +### Bug Fixes + +- Ordered map race condition (#708) + +### Performance + +- Increase web socket channels capacity (#709) + ## [0.13.3] - 2023-10-16 ### Bug Fixes @@ -5,6 +15,10 @@ - Issue with GMP not properly being linked on mac (#698) - Always propose with current app version (#697) +### Miscellaneous Tasks + +- Update changelog and version to 0.13.3 + ## [0.13.2] - 2023-10-09 ### Bug Fixes diff --git a/version/version.go b/version/version.go index 8e1bb184b4..58b28384fb 100644 --- a/version/version.go +++ b/version/version.go @@ -9,7 +9,7 @@ var ( const ( // TMVersionDefault is the used as the fallback version for Tenderdash // when not using git describe. It is formatted with semantic versioning. - TMVersionDefault = "0.13.3" + TMVersionDefault = "0.13.4" // ABCISemVer is the semantic version of the ABCI library ABCISemVer = "0.23.0"