Skip to content

Commit b3aebb6

Browse files
authored
Merge pull request #4546 from harmony-one/dev
Release Candidate v2024.0.0 - HIP-32 code (no mainnet HF) + Improvements
2 parents 2dee6c6 + 49bba17 commit b3aebb6

File tree

118 files changed

+10086
-1556
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+10086
-1556
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
This [github document](https://help.github.com/articles/creating-a-pull-request/) provides some guidance on how to create a pull request in github.
1212

1313
## PR requirement
14-
To pursue engineering excellence, we have insisted on the highest stardard on the quality of each PR.
14+
To pursue engineering excellence, we have insisted on the highest standard for the quality of each PR.
1515

1616
* For each PR, please run [golint](https://github.com/golang/lint), [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), to fix the basic issues/warnings.
1717
* Make sure you understand [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/).
@@ -21,7 +21,7 @@ To pursue engineering excellence, we have insisted on the highest stardard on th
2121
The best practice is to reorder and squash your local commits before the PR submission to create an atomic and self-contained PR.
2222
This [book chapter](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) provides detailed explanation and guidance on how to rewrite the local git history.
2323

24-
For exampple, a typical workflow is like the following.
24+
For example, a typical workflow is like the following.
2525
```bash
2626
# assuming you are working on a fix of bug1, and use a local branch called "fixes_of_bug1".
2727

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,4 @@ debug_external: clean
179179
bash test/debug-external.sh
180180

181181
build_localnet_validator:
182-
bash test/build-localnet-validator.sh
182+
bash test/build-localnet-validator.sh

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ make debug-kill
150150
151151
To keep things consistent, we have a docker image to run all tests. **These are the same tests ran on the pull request checks**.
152152
153-
Note that all testing docker container binds a couple of ports to the host machine for your convince. The ports are:
153+
Note that all test Docker containers bind several ports to the host machine for your convenience. The ports are:
154154
* `9500` - Shard 0 RPC for a validator
155155
* `9501` - Shard 1 RPC for a validator
156156
* `9599` - Shard 0 RPC for an explorer
@@ -174,7 +174,7 @@ To run this test, do:
174174
make test-rpc
175175
```
176176
This test starts a localnet (within the Docker container), **ensures it reaches a consensus**, and runs a series of tests to ensure correct RPC behavior.
177-
This test also acts as a preliminary integration test (more through tests are done on the testnets).
177+
This test also acts as a preliminary integration test (more thorough tests are done on the testnets).
178178
> The tests ran by this command can be found [here](https://github.com/harmony-one/harmony-test/tree/master/localnet).
179179
180180
If you wish to debug further with the localnet after the tests are done, open a new shell and run:
@@ -194,7 +194,7 @@ To run this test, do:
194194
make test-rosetta
195195
```
196196
This test starts a localnet (within the Docker container), **ensures it reaches a consensus**, and runs the Construction & Data API checks using the [rosetta-cli](https://github.com/coinbase/rosetta-cli).
197-
This test also acts as a preliminary integration test (more through tests are done on the testnets).
197+
This test also acts as a preliminary integration test (more thorough tests are done on the testnets).
198198
> The config for this test can be found [here](https://github.com/harmony-one/harmony-test/blob/master/localnet/configs/localnet_rosetta_test_s0.json) & [here](https://github.com/harmony-one/harmony-test/blob/master/localnet/configs/localnet_rosetta_test_s1.json)
199199
200200
Similar to the RPC tests, if you wish to debug further with the localnet after the tests are done, open a new shell and run:

api/service/legacysync/epoch_syncing.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ func syncLoop(bc core.BlockChain, syncConfig *SyncConfig) (timeout int) {
138138

139139
err := ProcessStateSync(syncConfig, heights, bc)
140140
if err != nil {
141+
if errors.Is(err, core.ErrKnownBlock) {
142+
return 10
143+
}
141144
utils.Logger().Error().Err(err).
142145
Msgf("[EPOCHSYNC] ProcessStateSync failed (isBeacon: %t, ShardID: %d, otherEpoch: %d, currentEpoch: %d)",
143146
isBeacon, bc.ShardID(), otherEpoch, curEpoch)
@@ -199,8 +202,18 @@ func processWithPayload(payload [][]byte, bc core.BlockChain) error {
199202
decoded = append(decoded, block)
200203
}
201204

202-
_, err := bc.InsertChain(decoded, true)
203-
return err
205+
for _, block := range decoded {
206+
_, err := bc.InsertChain([]*types.Block{block}, true)
207+
switch {
208+
case errors.Is(err, core.ErrKnownBlock):
209+
continue
210+
case err != nil:
211+
return err
212+
default:
213+
}
214+
}
215+
216+
return nil
204217
}
205218

206219
// CreateSyncConfig creates SyncConfig for StateSync object.

api/service/legacysync/syncing.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -860,11 +860,12 @@ func (ss *StateSync) getBlockFromLastMileBlocksByParentHash(parentHash common.Ha
860860
}
861861

862862
// UpdateBlockAndStatus ...
863-
func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc core.BlockChain, verifyAllSig bool) error {
863+
func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc core.BlockChain) error {
864864
if block.NumberU64() != bc.CurrentBlock().NumberU64()+1 {
865865
utils.Logger().Debug().Uint64("curBlockNum", bc.CurrentBlock().NumberU64()).Uint64("receivedBlockNum", block.NumberU64()).Msg("[SYNC] Inappropriate block number, ignore!")
866866
return nil
867867
}
868+
verifyAllSig := true
868869

869870
haveCurrentSig := len(block.GetCurrentCommitSig()) != 0
870871
// Verify block signatures
@@ -904,7 +905,17 @@ func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc core.BlockChain
904905
}
905906

906907
_, err := bc.InsertChain([]*types.Block{block}, false /* verifyHeaders */)
907-
if err != nil {
908+
switch {
909+
case errors.Is(err, core.ErrKnownBlock):
910+
utils.Logger().Info().
911+
Uint64("blockHeight", block.NumberU64()).
912+
Uint64("blockEpoch", block.Epoch().Uint64()).
913+
Str("blockHex", block.Hash().Hex()).
914+
Uint32("ShardID", block.ShardID()).
915+
Err(err).
916+
Msg("[SYNC] UpdateBlockAndStatus: Block exists")
917+
return nil
918+
case err != nil:
908919
utils.Logger().Error().
909920
Err(err).
910921
Msgf(
@@ -913,6 +924,7 @@ func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc core.BlockChain
913924
block.ShardID(),
914925
)
915926
return err
927+
default:
916928
}
917929
utils.Logger().Info().
918930
Uint64("blockHeight", block.NumberU64()).
@@ -944,8 +956,8 @@ func (ss *StateSync) generateNewState(bc core.BlockChain) error {
944956
break
945957
}
946958
// Enforce sig check for the last block in a batch
947-
enforceSigCheck := !commonIter.HasNext()
948-
err = ss.UpdateBlockAndStatus(block, bc, enforceSigCheck)
959+
_ = !commonIter.HasNext()
960+
err = ss.UpdateBlockAndStatus(block, bc)
949961
if err != nil {
950962
break
951963
}
@@ -962,7 +974,7 @@ func (ss *StateSync) generateNewState(bc core.BlockChain) error {
962974
if block == nil {
963975
break
964976
}
965-
err = ss.UpdateBlockAndStatus(block, bc, true)
977+
err = ss.UpdateBlockAndStatus(block, bc)
966978
if err != nil {
967979
break
968980
}
@@ -983,7 +995,7 @@ func (ss *StateSync) generateNewState(bc core.BlockChain) error {
983995
if block == nil {
984996
break
985997
}
986-
err = ss.UpdateBlockAndStatus(block, bc, false)
998+
err = ss.UpdateBlockAndStatus(block, bc)
987999
if err != nil {
9881000
break
9891001
}
@@ -1111,6 +1123,9 @@ func (ss *StateSync) SyncLoop(bc core.BlockChain, isBeacon bool, consensus *cons
11111123
}
11121124
err := ss.ProcessStateSync(startHash[:], size, bc)
11131125
if err != nil {
1126+
if errors.Is(err, core.ErrKnownBlock) {
1127+
continue
1128+
}
11141129
utils.Logger().Error().Err(err).
11151130
Msgf("[SYNC] ProcessStateSync failed (isBeacon: %t, ShardID: %d, otherHeight: %d, currentHeight: %d)",
11161131
isBeacon, bc.ShardID(), otherHeight, currentHeight)
@@ -1148,7 +1163,11 @@ func (ss *StateSync) addConsensusLastMile(bc core.BlockChain, consensus *consens
11481163
if block == nil {
11491164
break
11501165
}
1151-
if _, err := bc.InsertChain(types.Blocks{block}, true); err != nil {
1166+
_, err := bc.InsertChain(types.Blocks{block}, true)
1167+
switch {
1168+
case errors.Is(err, core.ErrKnownBlock):
1169+
case errors.Is(err, core.ErrNotLastBlockInEpoch):
1170+
case err != nil:
11521171
return errors.Wrap(err, "failed to InsertChain")
11531172
}
11541173
}

api/service/stagedstreamsync/adapter.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/harmony-one/harmony/core/types"
1010
"github.com/harmony-one/harmony/p2p/stream/common/streammanager"
1111
syncproto "github.com/harmony-one/harmony/p2p/stream/protocols/sync"
12+
"github.com/harmony-one/harmony/p2p/stream/protocols/sync/message"
1213
sttypes "github.com/harmony-one/harmony/p2p/stream/types"
1314
)
1415

@@ -20,6 +21,10 @@ type syncProtocol interface {
2021
GetBlocksByHashes(ctx context.Context, hs []common.Hash, opts ...syncproto.Option) ([]*types.Block, sttypes.StreamID, error)
2122
GetReceipts(ctx context.Context, hs []common.Hash, opts ...syncproto.Option) (receipts []types.Receipts, stid sttypes.StreamID, err error)
2223
GetNodeData(ctx context.Context, hs []common.Hash, opts ...syncproto.Option) (data [][]byte, stid sttypes.StreamID, err error)
24+
GetAccountRange(ctx context.Context, root common.Hash, origin common.Hash, limit common.Hash, bytes uint64, opts ...syncproto.Option) (accounts []*message.AccountData, proof [][]byte, stid sttypes.StreamID, err error)
25+
GetStorageRanges(ctx context.Context, root common.Hash, accounts []common.Hash, origin common.Hash, limit common.Hash, bytes uint64, opts ...syncproto.Option) (slots [][]*message.StorageData, proof [][]byte, stid sttypes.StreamID, err error)
26+
GetByteCodes(ctx context.Context, hs []common.Hash, bytes uint64, opts ...syncproto.Option) (codes [][]byte, stid sttypes.StreamID, err error)
27+
GetTrieNodes(ctx context.Context, root common.Hash, paths []*message.TrieNodePathSet, bytes uint64, opts ...syncproto.Option) (nodes [][]byte, stid sttypes.StreamID, err error)
2328

2429
RemoveStream(stID sttypes.StreamID) // If a stream delivers invalid data, remove the stream
2530
StreamFailed(stID sttypes.StreamID, reason string)

api/service/stagedstreamsync/beacon_helper.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package stagedstreamsync
22

33
import (
4+
"errors"
45
"time"
56

7+
"github.com/harmony-one/harmony/core"
68
"github.com/harmony-one/harmony/core/types"
79
"github.com/harmony-one/harmony/internal/utils"
810
"github.com/rs/zerolog"
@@ -126,7 +128,8 @@ func (bh *beaconHelper) insertLastMileBlocks() (inserted int, bn uint64, err err
126128
}
127129
// TODO: Instruct the beacon helper to verify signatures. This may require some forks
128130
// in pub-sub message (add commit sigs in node.block.sync messages)
129-
if _, err = bh.bc.InsertChain(types.Blocks{b}, true); err != nil {
131+
_, err = bh.bc.InsertChain(types.Blocks{b}, true)
132+
if err != nil && !errors.Is(err, core.ErrKnownBlock) {
130133
bn--
131134
return
132135
}

api/service/stagedstreamsync/block_manager.go

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package stagedstreamsync
22

33
import (
4+
"fmt"
45
"sync"
56

7+
"github.com/ethereum/go-ethereum/common"
68
sttypes "github.com/harmony-one/harmony/p2p/stream/types"
79
"github.com/ledgerwatch/erigon-lib/kv"
810
"github.com/rs/zerolog"
@@ -11,6 +13,7 @@ import (
1113
type BlockDownloadDetails struct {
1214
loopID int
1315
streamID sttypes.StreamID
16+
rootHash common.Hash
1417
}
1518

1619
// blockDownloadManager is the helper structure for get blocks request management
@@ -19,11 +22,11 @@ type blockDownloadManager struct {
1922
tx kv.RwTx
2023

2124
targetBN uint64
22-
requesting map[uint64]struct{} // block numbers that have been assigned to workers but not received
23-
processing map[uint64]struct{} // block numbers received requests but not inserted
24-
retries *prioritizedNumbers // requests where error happens
25-
rq *resultQueue // result queue wait to be inserted into blockchain
26-
bdd map[uint64]BlockDownloadDetails // details about how this block was downloaded
25+
requesting map[uint64]struct{} // block numbers that have been assigned to workers but not received
26+
processing map[uint64]struct{} // block numbers received requests but not inserted
27+
retries *prioritizedNumbers // requests where error happens
28+
rq *resultQueue // result queue wait to be inserted into blockchain
29+
bdd map[uint64]*BlockDownloadDetails // details about how this block was downloaded
2730

2831
logger zerolog.Logger
2932
lock sync.Mutex
@@ -38,26 +41,26 @@ func newBlockDownloadManager(tx kv.RwTx, chain blockChain, targetBN uint64, logg
3841
processing: make(map[uint64]struct{}),
3942
retries: newPrioritizedNumbers(),
4043
rq: newResultQueue(),
41-
bdd: make(map[uint64]BlockDownloadDetails),
44+
bdd: make(map[uint64]*BlockDownloadDetails),
4245
logger: logger,
4346
}
4447
}
4548

4649
// GetNextBatch get the next block numbers batch
47-
func (gbm *blockDownloadManager) GetNextBatch() []uint64 {
50+
func (gbm *blockDownloadManager) GetNextBatch(curHeight uint64) []uint64 {
4851
gbm.lock.Lock()
4952
defer gbm.lock.Unlock()
5053

5154
cap := BlocksPerRequest
5255

53-
bns := gbm.getBatchFromRetries(cap)
56+
bns := gbm.getBatchFromRetries(cap, curHeight)
5457
if len(bns) > 0 {
5558
cap -= len(bns)
5659
gbm.addBatchToRequesting(bns)
5760
}
5861

5962
if gbm.availableForMoreTasks() {
60-
addBNs := gbm.getBatchFromUnprocessed(cap)
63+
addBNs := gbm.getBatchFromUnprocessed(cap, curHeight)
6164
gbm.addBatchToRequesting(addBNs)
6265
bns = append(bns, addBNs...)
6366
}
@@ -88,7 +91,7 @@ func (gbm *blockDownloadManager) HandleRequestResult(bns []uint64, blockBytes []
8891
gbm.retries.push(bn)
8992
} else {
9093
gbm.processing[bn] = struct{}{}
91-
gbm.bdd[bn] = BlockDownloadDetails{
94+
gbm.bdd[bn] = &BlockDownloadDetails{
9295
loopID: loopID,
9396
streamID: streamID,
9497
}
@@ -107,7 +110,7 @@ func (gbm *blockDownloadManager) SetDownloadDetails(bns []uint64, loopID int, st
107110
defer gbm.lock.Unlock()
108111

109112
for _, bn := range bns {
110-
gbm.bdd[bn] = BlockDownloadDetails{
113+
gbm.bdd[bn] = &BlockDownloadDetails{
111114
loopID: loopID,
112115
streamID: streamID,
113116
}
@@ -116,25 +119,43 @@ func (gbm *blockDownloadManager) SetDownloadDetails(bns []uint64, loopID int, st
116119
}
117120

118121
// GetDownloadDetails returns the download details for a block
119-
func (gbm *blockDownloadManager) GetDownloadDetails(blockNumber uint64) (loopID int, streamID sttypes.StreamID) {
122+
func (gbm *blockDownloadManager) GetDownloadDetails(blockNumber uint64) (loopID int, streamID sttypes.StreamID, err error) {
120123
gbm.lock.Lock()
121124
defer gbm.lock.Unlock()
122125

123-
return gbm.bdd[blockNumber].loopID, gbm.bdd[blockNumber].streamID
126+
if dm, exist := gbm.bdd[blockNumber]; exist {
127+
return dm.loopID, dm.streamID, nil
128+
}
129+
return 0, sttypes.StreamID(fmt.Sprint(0)), fmt.Errorf("there is no download details for the block number: %d", blockNumber)
130+
}
131+
132+
// SetRootHash sets the root hash for a specific block
133+
func (gbm *blockDownloadManager) SetRootHash(blockNumber uint64, root common.Hash) {
134+
gbm.lock.Lock()
135+
defer gbm.lock.Unlock()
136+
137+
gbm.bdd[blockNumber].rootHash = root
138+
}
139+
140+
// GetRootHash returns the root hash for a specific block
141+
func (gbm *blockDownloadManager) GetRootHash(blockNumber uint64) common.Hash {
142+
gbm.lock.Lock()
143+
defer gbm.lock.Unlock()
144+
145+
return gbm.bdd[blockNumber].rootHash
124146
}
125147

126148
// getBatchFromRetries get the block number batch to be requested from retries.
127-
func (gbm *blockDownloadManager) getBatchFromRetries(cap int) []uint64 {
149+
func (gbm *blockDownloadManager) getBatchFromRetries(cap int, fromBlockNumber uint64) []uint64 {
128150
var (
129151
requestBNs []uint64
130-
curHeight = gbm.chain.CurrentBlock().NumberU64()
131152
)
132153
for cnt := 0; cnt < cap; cnt++ {
133154
bn := gbm.retries.pop()
134155
if bn == 0 {
135156
break // no more retries
136157
}
137-
if bn <= curHeight {
158+
if bn <= fromBlockNumber {
138159
continue
139160
}
140161
requestBNs = append(requestBNs, bn)
@@ -143,10 +164,9 @@ func (gbm *blockDownloadManager) getBatchFromRetries(cap int) []uint64 {
143164
}
144165

145166
// getBatchFromUnprocessed returns a batch of block numbers to be requested from unprocessed.
146-
func (gbm *blockDownloadManager) getBatchFromUnprocessed(cap int) []uint64 {
167+
func (gbm *blockDownloadManager) getBatchFromUnprocessed(cap int, curHeight uint64) []uint64 {
147168
var (
148169
requestBNs []uint64
149-
curHeight = gbm.chain.CurrentBlock().NumberU64()
150170
)
151171
bn := curHeight + 1
152172
// TODO: this algorithm can be potentially optimized.

0 commit comments

Comments
 (0)