الوقت ومتغيرات النظام

دوال للتعامل مع الوقت والوصول إلى متغيرات النظام. لكل دالة قراءة sysvar دالة كتابة مقابلة؛ والبنيات هي مرايا Go مباشرة لمصدر سولانا.

التعامل مع الساعة

WarpToSlot

func (s *LiteSVM) WarpToSlot(slot uint64) error

تقديم الساعة الداخلية إلى slot محدد.

before, err := svm.Clock()
if err != nil {
t.Fatal(err)
}
t.Logf("current slot: %d", before.Slot)
if err := svm.WarpToSlot(10_000_000); err != nil {
t.Fatal(err)
}
after, err := svm.Clock()
if err != nil {
t.Fatal(err)
}
t.Logf("new slot: %d", after.Slot)

Clock

type Clock struct {
Slot uint64
EpochStartTimestamp int64
Epoch uint64
LeaderScheduleEpoch uint64
UnixTimestamp int64
}
func (s *LiteSVM) Clock() (Clock, error)

قراءة الـ sysvar الخاص بـ Clock.

c, err := svm.Clock()
if err != nil {
t.Fatal(err)
}
t.Logf("slot=%d epoch=%d unix=%d", c.Slot, c.Epoch, c.UnixTimestamp)

SetClock

func (s *LiteSVM) SetClock(c Clock) error

الكتابة فوق الـ sysvar الخاص بـ Clock. اقرأه، عدّل الحقول، ثم اكتبه مجدداً عندما تحتاج إلى التحكم في Epoch أو UnixTimestamp (اللذين لا يقوم WarpToSlot بتحديثهما).

c, err := svm.Clock()
if err != nil {
t.Fatal(err)
}
c.Slot = 1_000
c.Epoch = 10
c.UnixTimestamp = 1_735_689_600
if err := svm.SetClock(c); err != nil {
t.Fatal(err)
}

يقوم WarpToSlot بتحديث Slot فقط. استخدم SetClock عندما يقرأ برنامجك Epoch أو UnixTimestamp من الـ sysvar الخاص بـ Clock.

rent

rent / SetRent

type Rent struct {
LamportsPerByteYear uint64
ExemptionThreshold float64
BurnPercent uint8
}
func (s *LiteSVM) Rent() (Rent, error)
func (s *LiteSVM) SetRent(r Rent) error
r, err := svm.Rent()
if err != nil {
t.Fatal(err)
}
t.Logf("lamports/byte-year: %d", r.LamportsPerByteYear)
t.Logf("exemption threshold: %.2f", r.ExemptionThreshold)
t.Logf("burn percent: %d", r.BurnPercent)

MinimumBalanceForRentExemption

func (s *LiteSVM) MinimumBalanceForRentExemption(dataLen int) (uint64, error)
for _, size := range []int{0, 100, 1024} {
min, err := svm.MinimumBalanceForRentExemption(size)
if err != nil {
t.Fatal(err)
}
t.Logf("%4d bytes -> %d lamports", size, min)
}

جدول الـ epoch

type EpochSchedule struct {
SlotsPerEpoch uint64
LeaderScheduleSlotOffset uint64
Warmup bool
FirstNormalEpoch uint64
FirstNormalSlot uint64
}
func (s *LiteSVM) EpochSchedule() (EpochSchedule, error)
func (s *LiteSVM) SetEpochSchedule(e EpochSchedule) error
es, err := svm.EpochSchedule()
if err != nil {
t.Fatal(err)
}
t.Logf("slots per epoch: %d", es.SlotsPerEpoch)
t.Logf("first normal epoch: %d", es.FirstNormalEpoch)
t.Logf("first normal slot: %d", es.FirstNormalSlot)

مكافآت الـ epoch

type EpochRewards struct {
DistributionStartingBlockHeight uint64
NumPartitions uint64
ParentBlockhash solana.Hash
TotalPointsLo uint64 // low 64 bits of the u128 total_points
TotalPointsHi uint64 // high 64 bits
TotalRewards uint64
DistributedRewards uint64
Active bool
}
func (s *LiteSVM) EpochRewards() (EpochRewards, error)
func (s *LiteSVM) SetEpochRewards(e EpochRewards) error

total_points هو نوع u128 على جانب سولانا؛ يعرض litesvm-go النصفين بشكل صريح حتى لا يحتاج مستخدمو Go إلى مكتبة u128. بالنسبة للقيم التي تتناسب مع 64 بت، يكون TotalPointsHi هو 0 وتكون TotalPointsLo هي القيمة.

معلومات الـ slot

LastRestartSlot / SetLastRestartSlot

func (s *LiteSVM) LastRestartSlot() (uint64, error)
func (s *LiteSVM) SetLastRestartSlot(slot uint64) error
last, err := svm.LastRestartSlot()
if err != nil {
t.Fatal(err)
}
if err := svm.SetLastRestartSlot(last + 1); err != nil {
t.Fatal(err)
}

SlotHashes / SetSlotHashes

type SlotHash struct {
Slot uint64
Hash solana.Hash
}
func (s *LiteSVM) SlotHashes() ([]SlotHash, error)
func (s *LiteSVM) SetSlotHashes(items []SlotHash) error

SlotHistory

SlotHistory عبارة عن bitvec بحجم ~128 كيلوبايت؛ يعرضها litesvm-go كمقبض بدلاً من شريحة.

sh, err := litesvm.NewSlotHistory()
if err != nil {
t.Fatal(err)
}
defer sh.Close()
sh.Add(42)
switch sh.Check(42) {
case litesvm.SlotHistoryFound:
// ...
case litesvm.SlotHistoryNotFound:
// ...
case litesvm.SlotHistoryTooOld:
// ...
case litesvm.SlotHistoryFuture:
// ...
}
if err := svm.SetSlotHistory(sh); err != nil {
t.Fatal(err)
}
الدالةالوصف
litesvm.NewSlotHistory() (*SlotHistory, error)مقبض فارغ
sh.Add(slot uint64)تسجيل slot
sh.Check(slot uint64) SlotHistoryCheckFuture / TooOld / Found / NotFound
sh.Oldest() uint64أقدم slot مُتتبَّع
sh.Newest() uint64أحدث slot مُتتبَّع
sh.NextSlot() uint64الـ slot التالي للتسجيل
sh.SetNextSlot(slot uint64) errorتجاوز علامة الـ slot التالي
sh.Close()تحرير المقبض
svm.SlotHistory() (*SlotHistory, error)القراءة في مقبض جديد
svm.SetSlotHistory(*SlotHistory) errorالتثبيت على SVM

سجل الحصص

type StakeHistoryItem struct {
Epoch uint64
Effective uint64
Activating uint64
Deactivating uint64
}
func (s *LiteSVM) StakeHistory() ([]StakeHistoryItem, error)
func (s *LiteSVM) SetStakeHistory(items []StakeHistoryItem) error

اختبار المنطق المعتمد على الوقت

استخدم WarpToSlot للتقدم البسيط القائم على الـ slot، وSetClock للتحكم الكامل:

func TestTimeLockedVault(t *testing.T) {
svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
const unlockSlot = uint64(10_000)
// Setup: create the time-locked account ...
// Test 1: Try to withdraw before unlock (should fail)
before, err := svm.Clock()
if err != nil {
t.Fatal(err)
}
t.Logf("current slot: %d", before.Slot)
// ... attempt withdrawal, expect failure ...
// Warp time forward past unlock slot
if err := svm.WarpToSlot(unlockSlot + 1); err != nil {
t.Fatal(err)
}
// Test 2: Try to withdraw after unlock (should succeed)
after, err := svm.Clock()
if err != nil {
t.Fatal(err)
}
t.Logf("new slot: %d", after.Slot)
// ... attempt withdrawal, expect success ...
}

Is this page helpful?