github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/eth/protocols/snap/progress_test.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package snap
    18  
    19  import (
    20  	"encoding/json"
    21  	"testing"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  )
    25  
    26  // Legacy sync progress definitions
    27  type legacyStorageTask struct {
    28  	Next common.Hash // Next account to sync in this interval
    29  	Last common.Hash // Last account to sync in this interval
    30  }
    31  
    32  type legacyAccountTask struct {
    33  	Next     common.Hash                          // Next account to sync in this interval
    34  	Last     common.Hash                          // Last account to sync in this interval
    35  	SubTasks map[common.Hash][]*legacyStorageTask // Storage intervals needing fetching for large contracts
    36  }
    37  
    38  type legacyProgress struct {
    39  	Tasks []*legacyAccountTask // The suspended account tasks (contract tasks within)
    40  }
    41  
    42  func compareProgress(a legacyProgress, b SyncProgress) bool {
    43  	if len(a.Tasks) != len(b.Tasks) {
    44  		return false
    45  	}
    46  	for i := 0; i < len(a.Tasks); i++ {
    47  		if a.Tasks[i].Next != b.Tasks[i].Next {
    48  			return false
    49  		}
    50  		if a.Tasks[i].Last != b.Tasks[i].Last {
    51  			return false
    52  		}
    53  		// new fields are not checked here
    54  
    55  		if len(a.Tasks[i].SubTasks) != len(b.Tasks[i].SubTasks) {
    56  			return false
    57  		}
    58  		for addrHash, subTasksA := range a.Tasks[i].SubTasks {
    59  			subTasksB, ok := b.Tasks[i].SubTasks[addrHash]
    60  			if !ok || len(subTasksB) != len(subTasksA) {
    61  				return false
    62  			}
    63  			for j := 0; j < len(subTasksA); j++ {
    64  				if subTasksA[j].Next != subTasksB[j].Next {
    65  					return false
    66  				}
    67  				if subTasksA[j].Last != subTasksB[j].Last {
    68  					return false
    69  				}
    70  			}
    71  		}
    72  	}
    73  	return true
    74  }
    75  
    76  func makeLegacyProgress() legacyProgress {
    77  	return legacyProgress{
    78  		Tasks: []*legacyAccountTask{
    79  			{
    80  				Next: common.Hash{},
    81  				Last: common.Hash{0x77},
    82  				SubTasks: map[common.Hash][]*legacyStorageTask{
    83  					common.Hash{0x1}: {
    84  						{
    85  							Next: common.Hash{},
    86  							Last: common.Hash{0xff},
    87  						},
    88  					},
    89  				},
    90  			},
    91  			{
    92  				Next: common.Hash{0x88},
    93  				Last: common.Hash{0xff},
    94  			},
    95  		},
    96  	}
    97  }
    98  
    99  func convertLegacy(legacy legacyProgress) SyncProgress {
   100  	var progress SyncProgress
   101  	for i, task := range legacy.Tasks {
   102  		subTasks := make(map[common.Hash][]*storageTask)
   103  		for owner, list := range task.SubTasks {
   104  			var cpy []*storageTask
   105  			for i := 0; i < len(list); i++ {
   106  				cpy = append(cpy, &storageTask{
   107  					Next: list[i].Next,
   108  					Last: list[i].Last,
   109  				})
   110  			}
   111  			subTasks[owner] = cpy
   112  		}
   113  		accountTask := &accountTask{
   114  			Next:     task.Next,
   115  			Last:     task.Last,
   116  			SubTasks: subTasks,
   117  		}
   118  		if i == 0 {
   119  			accountTask.StorageCompleted = []common.Hash{{0xaa}, {0xbb}} // fulfill new fields
   120  		}
   121  		progress.Tasks = append(progress.Tasks, accountTask)
   122  	}
   123  	return progress
   124  }
   125  
   126  func TestSyncProgressCompatibility(t *testing.T) {
   127  	// Decode serialized bytes of legacy progress, backward compatibility
   128  	legacy := makeLegacyProgress()
   129  	blob, err := json.Marshal(legacy)
   130  	if err != nil {
   131  		t.Fatalf("Failed to marshal progress %v", err)
   132  	}
   133  	var dec SyncProgress
   134  	if err := json.Unmarshal(blob, &dec); err != nil {
   135  		t.Fatalf("Failed to unmarshal progress %v", err)
   136  	}
   137  	if !compareProgress(legacy, dec) {
   138  		t.Fatal("sync progress is not backward compatible")
   139  	}
   140  
   141  	// Decode serialized bytes of new format progress
   142  	progress := convertLegacy(legacy)
   143  	blob, err = json.Marshal(progress)
   144  	if err != nil {
   145  		t.Fatalf("Failed to marshal progress %v", err)
   146  	}
   147  	var legacyDec legacyProgress
   148  	if err := json.Unmarshal(blob, &legacyDec); err != nil {
   149  		t.Fatalf("Failed to unmarshal progress %v", err)
   150  	}
   151  	if !compareProgress(legacyDec, progress) {
   152  		t.Fatal("sync progress is not forward compatible")
   153  	}
   154  }