Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions conformance/poseidon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestConformance_Poseidon_Big_Endian(t *testing.T) {
3, 85, 242, 99, 25, 32, 123, 132, 254, 156, 162,
206, 27, 38, 231, 53, 200, 41, 130, 25, 144}

hash, err := sealevel.PoseidonHash([][]byte{bytes1, bytes2}, true)
hash, err := sealevel.PoseidonHash([][]byte{bytes1, bytes2}, true, false)
assert.NoError(t, err)
assert.Equal(t, expected1, hash)

Expand All @@ -32,7 +32,7 @@ func TestConformance_Poseidon_Big_Endian(t *testing.T) {
169, 243, 2, 63, 119, 18, 148, 167, 138, 203, 112,
231, 63, 144, 175, 226, 124, 173, 64, 30, 129}

hash, err = sealevel.PoseidonHash([][]byte{input3, input3}, true)
hash, err = sealevel.PoseidonHash([][]byte{input3, input3}, true, false)
assert.NoError(t, err)
assert.Equal(t, expected2, hash)

Expand All @@ -42,7 +42,7 @@ func TestConformance_Poseidon_Big_Endian(t *testing.T) {
205, 35, 194, 2, 177, 134, 115, 191, 37, 67,
}

hash, err = sealevel.PoseidonHash([][]byte{input3, input3, input3}, true)
hash, err = sealevel.PoseidonHash([][]byte{input3, input3, input3}, true, false)
assert.NoError(t, err)
assert.Equal(t, expected3, hash)
}
Expand All @@ -58,7 +58,7 @@ func TestConformance_Poseidon_Little_Endian(t *testing.T) {
156, 254, 132, 123, 32, 25, 99, 242, 85, 3, 94,
235, 125, 28, 140, 138, 143, 147, 225, 84, 13}

hash, err := sealevel.PoseidonHash([][]byte{bytes1, bytes2}, false)
hash, err := sealevel.PoseidonHash([][]byte{bytes1, bytes2}, false, false)
assert.NoError(t, err)
assert.Equal(t, expected, hash)
}
8 changes: 7 additions & 1 deletion pkg/features/gates.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ var EnableSbpfV3DeploymentAndExecution = FeatureGate{Name: "EnableSbpfV3Deployme
var DisableSbpfV0Execution = FeatureGate{Name: "DisableSbpfV0Execution", Address: base58.MustDecodeFromString("TestFeature11111111111111111111111111111111")}
var ReenableSbpfV0Execution = FeatureGate{Name: "ReenableSbpfV0Execution", Address: base58.MustDecodeFromString("TestFeature21111111111111111111111111111111")}
var FormalizeLoadedTransactionDataSize = FeatureGate{Name: "FormalizeLoadedTransactionDataSize", Address: base58.MustDecodeFromString("DeS7sR48ZcFTUmt5FFEVDr1v1bh73aAbZiZq3SYr8Eh8")}
var IncreaseCpiAccountInfoLimit = FeatureGate{Name: "IncreaseCpiAccountInfoLimit", Address: base58.MustDecodeFromString("H6iVbVaDZgDphcPbcZwc5LoznMPWQfnJ1AM7L1xzqvt5")}
var StaticInstructionLimit = FeatureGate{Name: "StaticInstructionLimit", Address: base58.MustDecodeFromString("64ixypL1HPu8WtJhNSMb9mSgfFaJvsANuRkTbHyuLfnx")}
var PoseidonEnforcePadding = FeatureGate{Name: "PoseidonEnforcePadding", Address: base58.MustDecodeFromString("poUdAqRXXsNmfqAZ6UqpjbeYgwBygbfQLEvWSqVhSnb")}
var FixAltBn128PairingLengthCheck = FeatureGate{Name: "FixAltBn128PairingLengthCheck", Address: base58.MustDecodeFromString("bnYzodLwmybj7e1HAe98yZrdJTd7we69eMMLgCXqKZm")}
var DeprecateRentExemptionThreshold = FeatureGate{Name: "DeprecateRentExemptionThreshold", Address: base58.MustDecodeFromString("rent6iVy6PDoViPBeJ6k5EJQrkj62h7DPyLbWGHwjrC")}

var AllFeatureGates = []FeatureGate{StopTruncatingStringsInSyscalls, EnablePartitionedEpochReward, EnablePartitionedEpochRewardsSuperfeature,
LastRestartSlotSysvar, Libsecp256k1FailOnBadCount, Libsecp256k1FailOnBadCount2, EnableBpfLoaderSetAuthorityCheckedIx,
Expand All @@ -73,4 +78,5 @@ var AllFeatureGates = []FeatureGate{StopTruncatingStringsInSyscalls, EnableParti
FullInflationVote, FullInflationEnable, FullInflationDevnetAndTestnet, PicoInflation, DisableAccountLoaderSpecialCase, EnableGetEpochStakeSyscall,
ReserveMinimalCUsForBuiltinInstructions, MaskOutRentEpochInVmSerialization, RemoveAccountsExecutableFlagChecks,
AccountsLtHash, RemoveAccountsDeltaHash, EnableLoaderV4, EnableSbpfV1DeploymentAndExecution, EnableSbpfV2DeploymentAndExecution,
EnableSbpfV3DeploymentAndExecution, DisableSbpfV0Execution, ReenableSbpfV0Execution, FormalizeLoadedTransactionDataSize}
EnableSbpfV3DeploymentAndExecution, DisableSbpfV0Execution, ReenableSbpfV0Execution, FormalizeLoadedTransactionDataSize, IncreaseCpiAccountInfoLimit,
StaticInstructionLimit, PoseidonEnforcePadding, FixAltBn128PairingLengthCheck, DeprecateRentExemptionThreshold}
41 changes: 34 additions & 7 deletions pkg/replay/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,8 @@ func loadBlockAccountsAndUpdateSysvars(accountsDb *accountsdb.AccountsDb, block
}

func scanAndEnableFeatures(acctsDb *accountsdb.AccountsDb, slot uint64, startOfEpoch bool) (*features.Features, []*accounts.Account, []*accounts.Account) {
parentNewlyActivatedFeatureAccts := make([]*accounts.Account, 0)
newlyActivatedFeatureAccts := make([]*accounts.Account, 0)
parentAccts := make([]*accounts.Account, 0)
modifiedAccts := make([]*accounts.Account, 0)

f := features.NewFeaturesDefault()

Expand All @@ -651,7 +651,7 @@ func scanAndEnableFeatures(acctsDb *accountsdb.AccountsDb, slot uint64, startOfE
if acct.Owner != a.FeatureAddr {
continue
}
parentNewlyActivatedFeatureAccts = append(parentNewlyActivatedFeatureAccts, acct.Clone())
parentAccts = append(parentAccts, acct.Clone())

featureAcct := features.UnmarshalFeatureAcct(acct.Data)

Expand All @@ -668,21 +668,48 @@ func scanAndEnableFeatures(acctsDb *accountsdb.AccountsDb, slot uint64, startOfE
}

acct.Data = newFeatureAcctBytes
newlyActivatedFeatureAccts = append(newlyActivatedFeatureAccts, acct)
modifiedAccts = append(modifiedAccts, acct)

f.EnableFeature(featureGate, slot)
}
}
}

if len(newlyActivatedFeatureAccts) != 0 {
err := acctsDb.StoreAccounts(newlyActivatedFeatureAccts, slot, nil)
if len(modifiedAccts) != 0 {
err := acctsDb.StoreAccounts(modifiedAccts, slot, nil)
if err != nil {
panic(err)
}
}

return f, newlyActivatedFeatureAccts, parentNewlyActivatedFeatureAccts
for _, featureAcct := range modifiedAccts {
// Handle *SIMD-0194: Deprecate rent exemption threshold* feature activation by updating the Rent sysvar.
if f.IsActive(features.DeprecateRentExemptionThreshold) && featureAcct.Key == features.DeprecateRentExemptionThreshold.Address {
var rentSysvar sealevel.SysvarRent
rentSysvar.LamportsPerUint8Year = uint64(float64(sealevel.SysvarCache.Rent.Sysvar.LamportsPerUint8Year) * sealevel.SysvarCache.Rent.Sysvar.ExemptionThreshold)
rentSysvar.ExemptionThreshold = 1.0
rentSysvar.BurnPercent = sealevel.SysvarCache.Rent.Sysvar.BurnPercent

rentAcct, err := acctsDb.GetAccount(slot, sealevel.SysvarRentAddr)
if err != nil {
panic(err)
}
parentAccts = append(parentAccts, rentAcct.Clone())

newRentSysvarBytes := rentSysvar.MustMarshal()
copy(rentAcct.Data, newRentSysvarBytes)
err = acctsDb.StoreAccounts([]*accounts.Account{rentAcct}, slot, nil)
if err != nil {
panic(err)
}
modifiedAccts = append(modifiedAccts, rentAcct)

sealevel.SysvarCache.Rent.Sysvar = &rentSysvar
sealevel.SysvarCache.Rent.Acct = rentAcct
}
}

return f, modifiedAccts, parentAccts
}

// setupInitialVoteAcctsAndStakeAccts populates the vote and stake caches at startup.
Expand Down
8 changes: 8 additions & 0 deletions pkg/replay/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var (
TxErrProgramAccountNotFound = errors.New("TxErrProgramAccountNotFound")
TxErrInvalidProgramForExecution = errors.New("TxErrInvalidProgramForExecution")
TxErrInvalidBlockhash = errors.New("TxErrInvalidBlockhash")
TxErrSanitizeFailure = errors.New("TxErrSanitizeFailure")
)

func programIndices(tx *solana.Transaction, instrIdx int) []uint64 {
Expand Down Expand Up @@ -317,6 +318,13 @@ func ProcessTransaction(slotCtx *sealevel.SlotCtx, sigverifyWg *sync.WaitGroup,
if arena != nil {
arena.Reset()
}

if slotCtx.Features.IsActive(features.StaticInstructionLimit) {
if len(tx.Message.Instructions) > maxInstrTraceCapacity {
return nil, TxErrSanitizeFailure
}
}

start := time.Now()
sigverifyWg.Add(1)
go verifySignatures(tx, slotCtx.Slot, sigverifyWg)
Expand Down
54 changes: 45 additions & 9 deletions pkg/sealevel/syscalls_cpi.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import (
)

const (
MaxSigners = 16
MaxCpiInstructionDataLen = 10 * 1024
MaxCpiInstructionAccounts = 255
MaxCpiAccountInfos = 128
MaxSigners = 16
MaxCpiInstructionDataLen = 10 * 1024
MaxCpiInstructionAccounts = 255
MaxCpiAccountInfos = 128
MaxCpiAccountInfosSimd0339 = 255
AccountInfoByteSize = 80
)

func checkInstructionSize(execCtx *ExecutionCtx, numAccounts uint64, dataLen uint64) error {
Expand Down Expand Up @@ -91,7 +93,14 @@ func translateInstructionC(vm sbpf.VM, addr uint64) (Instruction, error) {

execCtx := executionCtx(vm)
if execCtx.Features.IsActive(features.LoosenCpiSizeRestriction) {
err = execCtx.ComputeMeter.Consume(ix.DataLen / cu.CUCpiBytesPerUnit)
totalCuTranslationCost := ix.DataLen / cu.CUCpiBytesPerUnit

if execCtx.Features.IsActive(features.IncreaseCpiAccountInfoLimit) {
acctMetaTranslationCost := safemath.SaturatingMulU64(ix.AccountsLen, AccountMetaSize) / cu.CUCpiBytesPerUnit
totalCuTranslationCost = safemath.SaturatingAddU64(totalCuTranslationCost, acctMetaTranslationCost)
}

err = execCtx.ComputeMeter.Consume(totalCuTranslationCost)
if err != nil {
return Instruction{}, err
}
Expand Down Expand Up @@ -168,7 +177,14 @@ func translateInstructionRust(vm sbpf.VM, addr uint64) (Instruction, error) {

execCtx := executionCtx(vm)
if execCtx.Features.IsActive(features.LoosenCpiSizeRestriction) {
err = execCtx.ComputeMeter.Consume(ix.Data.Len / cu.CUCpiBytesPerUnit)
totalCuTranslationCost := ix.Data.Len / cu.CUCpiBytesPerUnit

if execCtx.Features.IsActive(features.IncreaseCpiAccountInfoLimit) {
acctMetaTranslationCost := safemath.SaturatingMulU64(ix.Accounts.Len, AccountMetaSize) / cu.CUCpiBytesPerUnit
totalCuTranslationCost = safemath.SaturatingAddU64(totalCuTranslationCost, acctMetaTranslationCost)
}

err = execCtx.ComputeMeter.Consume(totalCuTranslationCost)
if err != nil {
return Instruction{}, err
}
Expand Down Expand Up @@ -294,7 +310,9 @@ func checkAuthorizedProgram(execCtx *ExecutionCtx, programId solana.PublicKey, i
func checkAccountInfos(execCtx *ExecutionCtx, numAccountInfos uint64) error {
if execCtx.Features.IsActive(features.LoosenCpiSizeRestriction) {
var maxAccountInfos uint64
if execCtx.Features.IsActive(features.IncreaseTxAccountLockLimit) {
if execCtx.Features.IsActive(features.IncreaseCpiAccountInfoLimit) {
maxAccountInfos = MaxCpiAccountInfosSimd0339
} else if execCtx.Features.IsActive(features.IncreaseTxAccountLockLimit) {
maxAccountInfos = MaxCpiAccountInfos
} else {
maxAccountInfos = 64
Expand Down Expand Up @@ -330,11 +348,20 @@ func translateAccountInfosC(vm sbpf.VM, accountInfosAddr, accountInfosLen uint64
accountInfos = append(accountInfos, acctInfo)
}

err = checkAccountInfos(executionCtx(vm), uint64(len(accountInfos)))
execCtx := executionCtx(vm)
err = checkAccountInfos(execCtx, uint64(len(accountInfos)))
if err != nil {
return nil, nil, err
}

if execCtx.Features.IsActive(features.IncreaseCpiAccountInfoLimit) {
acctInfosBytes := safemath.SaturatingMulU64(uint64(len(accountInfos)), AccountInfoByteSize)
err = execCtx.ComputeMeter.Consume(acctInfosBytes / cu.CUCpiBytesPerUnit)
if err != nil {
return nil, nil, err
}
}

accountInfoKeys := make([]solana.PublicKey, 0, len(accountInfos))
for _, acctInfo := range accountInfos {
keyData, err := vm.Translate(acctInfo.KeyAddr, 32, false)
Expand Down Expand Up @@ -367,11 +394,20 @@ func translateAccountInfosRust(vm sbpf.VM, accountInfosAddr, accountInfosLen uin
accountInfos = append(accountInfos, acctInfo)
}

err = checkAccountInfos(executionCtx(vm), uint64(len(accountInfos)))
execCtx := executionCtx(vm)
err = checkAccountInfos(execCtx, uint64(len(accountInfos)))
if err != nil {
return nil, nil, err
}

if execCtx.Features.IsActive(features.IncreaseCpiAccountInfoLimit) {
acctInfosBytes := safemath.SaturatingMulU64(uint64(len(accountInfos)), AccountInfoByteSize)
err = execCtx.ComputeMeter.Consume(acctInfosBytes / cu.CUCpiBytesPerUnit)
if err != nil {
return nil, nil, err
}
}

accountInfoKeys := make([]solana.PublicKey, 0, len(accountInfos))
for _, acctInfo := range accountInfos {
keyData, err := vm.Translate(acctInfo.PubkeyAddr, 32, false)
Expand Down
16 changes: 13 additions & 3 deletions pkg/sealevel/syscalls_curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -863,9 +863,14 @@ func altbn128Multiplication(input []byte, expectedLen uint64) ([]byte, error) {
return resultBytes, nil
}

func altbn128Pairing(input []byte) ([]byte, error) {
elementsLen := uint64(len(input)) / AltBn128PairingElementLen
func altbn128Pairing(input []byte, enforceSimd0334LenCheck bool) ([]byte, error) {
if enforceSimd0334LenCheck {
if len(input)%AltBn128PairingElementLen != 0 {
return nil, fmt.Errorf("AltBn128Error::InvalidInputData")
}
}

elementsLen := uint64(len(input)) / AltBn128PairingElementLen
g1Vals := make([]*bn256.G1, 0)
g2Vals := make([]*bn256.G2, 0)

Expand Down Expand Up @@ -990,7 +995,12 @@ func SyscallAltBn128Impl(vm sbpf.VM, groupOp, inputAddr, inputLen, resultAddr ui

case AltBn128Pairing:
{
result, err := altbn128Pairing(inputSlice)
var enforceSimd0334LenCheck bool
if execCtx.Features.IsActive(features.FixAltBn128PairingLengthCheck) {
enforceSimd0334LenCheck = true
}

result, err := altbn128Pairing(inputSlice, enforceSimd0334LenCheck)
if err != nil {
mlog.Log.Debugf("altbn128 pairing err: %s", err)
return syscallSuccess(1)
Expand Down
4 changes: 2 additions & 2 deletions pkg/sealevel/syscalls_curve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func TestConformance_AltBn128_Pairing1(t *testing.T) {
knownCorrect, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000001")
assert.NoError(t, err)

result, err := altbn128Pairing(inputBytes)
result, err := altbn128Pairing(inputBytes, false)
assert.NoError(t, err)

assert.Equal(t, knownCorrect, result)
Expand Down Expand Up @@ -390,7 +390,7 @@ func TestConformance_AltBn128_Pairing_Multiple(t *testing.T) {
inputBytes, err := hex.DecodeString(inStr)
assert.NoError(t, err)

result, err := altbn128Pairing(inputBytes)
result, err := altbn128Pairing(inputBytes, false)
assert.NoError(t, err)

knownCorrectBytes, err := hex.DecodeString(resultStrs[idx])
Expand Down
12 changes: 9 additions & 3 deletions pkg/sealevel/syscalls_hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

//"github.com/Overclock-Validator/mithril/pkg/mlog"
"github.com/Overclock-Validator/mithril/pkg/cu"
"github.com/Overclock-Validator/mithril/pkg/features"
"github.com/Overclock-Validator/mithril/pkg/sbpf"
"github.com/ethereum/go-ethereum/crypto"
"github.com/iden3/go-iden3-crypto/poseidon"
Expand Down Expand Up @@ -268,14 +269,18 @@ func SwapEndianness(xs []byte) []byte {
return ys
}

func PoseidonHash(input [][]byte, isBigEndian bool) ([]byte, error) {
//mlog.Log.Debugf("PoseidonHash: len(input) = %d, isBigEndian = %t", len(input), isBigEndian)
func PoseidonHash(input [][]byte, isBigEndian bool, enforceSimd0359 bool) ([]byte, error) {
inputBigInts := make([]*big.Int, 0, len(input))

for _, inputSlice := range input {
if len(inputSlice) > 32 {
return nil, fmt.Errorf("input too long")
}

if enforceSimd0359 && len(inputSlice) < 32 {
return nil, fmt.Errorf("input too short")
}

var bigInt *big.Int
if isBigEndian {
bigInt = new(big.Int).SetBytes(inputSlice)
Expand Down Expand Up @@ -366,7 +371,8 @@ func SyscallPoseidonImpl(vm sbpf.VM, parameters, endianness, valsAddr, valsLen,

isBigEndian := endianness == 0

hash, err := PoseidonHash(inputs, isBigEndian)
enforceSimd0359 := execCtx.Features.IsActive(features.PoseidonEnforcePadding)
hash, err := PoseidonHash(inputs, isBigEndian, enforceSimd0359)
if err != nil {
return syscallSuccess(1)
}
Expand Down
22 changes: 22 additions & 0 deletions pkg/sealevel/sysvar_rent.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,28 @@ func (sr *SysvarRent) MustUnmarshalWithDecoder(decoder *bin.Decoder) {
}
}

func (sr *SysvarRent) MustMarshal() []byte {
data := new(bytes.Buffer)
enc := bin.NewBinEncoder(data)

err := enc.WriteUint64(sr.LamportsPerUint8Year, bin.LE)
if err != nil {
panic(fmt.Sprintf("failed to marshal LamportsPerUint8Year in sysvar rent: %s", err))
}

err = enc.WriteFloat64(sr.ExemptionThreshold, bin.LE)
if err != nil {
panic(fmt.Sprintf("failed to marshal ExemptionThreshold in sysvar rent: %s", err))
}

err = enc.WriteByte(sr.BurnPercent)
if err != nil {
panic(fmt.Sprintf("failed to marshal BurnPercent in sysvar rent: %s", err))
}

return data.Bytes()
}

func (sr *SysvarRent) MinimumBalance(dataLen uint64) uint64 {
dataLenWithOverhead := safemath.SaturatingAddU64(dataLen, rentAccountStorageOverhead)
lamportsPerYear := safemath.SaturatingMulU64(dataLenWithOverhead, sr.LamportsPerUint8Year)
Expand Down