-
Notifications
You must be signed in to change notification settings - Fork 20.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eth/protocols/snap: fix snap sync failure on empty storage range #28306
Conversation
747fb18
to
c418b37
Compare
FYI, there was no existing test which triggered the chunked-storage-fetch, so I added one here: 2d426e9#diff-25511a64fb71eea2da50f30896725bd1e6f88edd887ee74f7b70bf2685b24059R791 . Might be useful for you too? |
@holiman I have something to trigger the chunked-storage https://github.com/ethereum/go-ethereum/pull/28306/files#diff-25511a64fb71eea2da50f30896725bd1e6f88edd887ee74f7b70bf2685b24059R1445 |
for i := 0; i < 3; i++ { | ||
var n int | ||
for { | ||
n = mrand.Intn(15) // the last range is set empty deliberately | ||
if _, ok := chosen[byte(n)]; ok { | ||
continue | ||
} | ||
chosen[byte(n)] = struct{}{} | ||
break | ||
} | ||
for j := 0; j < slots/3; j++ { | ||
key := append([]byte{byte(n)}, testutil.RandBytes(31)...) | ||
val, _ := rlp.EncodeToBytes(testutil.RandBytes(32)) | ||
|
||
elem := &kv{key, val} | ||
tr.MustUpdate(elem.k, elem.v) | ||
entries = append(entries, elem) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about something like this?
for i := 0; i < 3; i++ { | |
var n int | |
for { | |
n = mrand.Intn(15) // the last range is set empty deliberately | |
if _, ok := chosen[byte(n)]; ok { | |
continue | |
} | |
chosen[byte(n)] = struct{}{} | |
break | |
} | |
for j := 0; j < slots/3; j++ { | |
key := append([]byte{byte(n)}, testutil.RandBytes(31)...) | |
val, _ := rlp.EncodeToBytes(testutil.RandBytes(32)) | |
elem := &kv{key, val} | |
tr.MustUpdate(elem.k, elem.v) | |
entries = append(entries, elem) | |
} | |
} | |
for i := 0; i < slots; i++ { | |
key := testutil.RandBytes(32) | |
if key[0] >= 0x80 { | |
key[0] -= 0x80 | |
} | |
val, _ := rlp.EncodeToBytes(testutil.RandBytes(32)) | |
elem := &kv{key, val} | |
tr.MustUpdate(elem.k, elem.v) | |
entries = append(entries, elem) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, if I do
if key[0] >= 0x80 {
key[0] = 0x00
}
Then I start to hit the edgecase we want to repro pretty often
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes looks good to me, but the testcase should be improved: it almost never triggers the condition as far as I can tell.
I take that back, it seems ok to me! |
Deployed it on 05, and it can finish snap sync. |
…ereum#28306) This change addresses an issue in snap sync, specifically when the entire sync process can be halted due to an encountered empty storage range. Currently, on the snap sync client side, the response to an empty (partial) storage range is discarded as a non-delivery. However, this response can be a valid response, when the particular range requested does not contain any slots. For instance, consider a large contract where the entire key space is divided into 16 chunks, and there are no available slots in the last chunk [0xf] -> [end]. When the node receives a request for this particular range, the response includes: The proof with origin [0xf] A nil storage slot set If we simply discard this response, the finalization of the last range will be skipped, halting the entire sync process indefinitely. The test case TestSyncWithUnevenStorage can reproduce the scenario described above. In addition, this change also defines the common variables MaxAddress and MaxHash.
…nge (ethereum#28306)" This reverts commit 631db5c.
…nge (ethereum#28306)" This reverts commit 631db5c.
This pull request addresses an issue in snap sync, specifically when the entire sync process can be halted due to an encountered empty storage range.
Currently, on the snap sync client side, the response to an empty storage range is discarded. However, this response is valid when there are no available storage slots within that range.
For instance, consider a large contract where the entire key space is divided into 16 chunks, and there are no available slots in the last chunk [0xf] -> [end]. When the node receives a request for this particular range, the response includes:
If we simply discard this response, the finalization of the last range will be skipped, halting the entire sync process indefinitely. The test case TestSyncWithUnevenStorage can reproduce the scenario described above.
Besides, this pull request also defines the common variables
MaxAddress
andMaxHash
.