diff --git a/zk/txpool/policy.go b/zk/txpool/policy.go index bd969c2a59c..5755928eb37 100644 --- a/zk/txpool/policy.go +++ b/zk/txpool/policy.go @@ -45,6 +45,8 @@ func OperationFromByte(b byte) Operation { return Remove case byte(Update): return Update + case byte(ModeChange): + return ModeChange default: return Add // Default or error handling can be added here } @@ -365,6 +367,9 @@ func bytesToTimestamp(b []byte) time.Time { func LastPolicyTransactions(ctx context.Context, aclDB kv.RwDB, count int) ([]PolicyTransaction, error) { var pts []PolicyTransaction err := aclDB.View(ctx, func(tx kv.Tx) error { + if count == 0 { + return nil + } c, err := tx.Cursor(PolicyTransactions) if err != nil { return err @@ -381,7 +386,7 @@ func LastPolicyTransactions(ctx context.Context, aclDB kv.RwDB, count int) ([]Po } pts = append(pts, pt) - for i := 0; i < count; i++ { + for i := 1; i < count; i++ { _, value, err = c.Prev() if err != nil { return err diff --git a/zk/txpool/policy_test.go b/zk/txpool/policy_test.go index 82456b66700..63cf02914ce 100644 --- a/zk/txpool/policy_test.go +++ b/zk/txpool/policy_test.go @@ -69,6 +69,31 @@ func newTestTxPoolDB(tb testing.TB, dir string) kv.RwDB { return txPoolDB } +func policyTransactionSliceEqual(a, b []PolicyTransaction) bool { + // Check if lengths are different + if len(a) != len(b) { + return false + } + + // Check each element, excluding timeTx + for i := range a { + if a[i].aclType != b[i].aclType { + return false + } + if ACLTypeBinary(a[i].operation) != ACLTypeBinary(b[i].operation) { + return false + } + if a[i].addr != b[i].addr { + return false + } + if a[i].policy != b[i].policy { + return false + } + } + + return true +} + func TestCheckDBsCreation(t *testing.T) { t.Parallel() @@ -189,6 +214,51 @@ func TestRemovePolicy(t *testing.T) { }) } +func TestPolicyMapping(t *testing.T) { + // All policies + var policiesAll []byte + var pListAll []Policy + policiesAll = append(policiesAll, SendTx.ToByte()) + policiesAll = append(policiesAll, Deploy.ToByte()) + pListAll = append(pListAll, SendTx) + pListAll = append(pListAll, Deploy) + + // Only sendTx policy + var policiesSendTx []byte + var pListSendTx []Policy + policiesSendTx = append(policiesSendTx, SendTx.ToByte()) + pListSendTx = append(pListSendTx, SendTx) + + // Only deploy policy + var policiesDeploy []byte + var pListDeploy []Policy + policiesDeploy = append(policiesDeploy, Deploy.ToByte()) + pListDeploy = append(pListDeploy, Deploy) + + // No policy + var policiesNone []byte + var pListNone []Policy + + var tests = []struct { + policies []byte + pList []Policy + want string + }{ + {policiesAll, pListAll, "\tsendTx: true\n\tdeploy: true"}, + {policiesSendTx, pListSendTx, "\tsendTx: true"}, + {policiesDeploy, pListDeploy, "\tdeploy: true"}, + {policiesNone, pListNone, ""}, + } + for _, tt := range tests { + t.Run("PolicyMapping", func(t *testing.T) { + ans := policyMapping(tt.policies, tt.pList) + if ans != tt.want { + t.Errorf("got %v, want %v", ans, tt.want) + } + }) + } +} + func TestAddPolicy(t *testing.T) { t.Parallel() @@ -409,6 +479,74 @@ func TestUpdatePolicies(t *testing.T) { }) } +func TestLastPolicyTransactions(t *testing.T) { + db := newTestACLDB(t, "") + ctx := context.Background() + + SetMode(ctx, db, BlocklistMode) + + // Create a test address and policy + addrInit := common.HexToAddress("0x0000000000000000") + policyInit := SendTx + + addrOne := common.HexToAddress("0x1234567890abcdef") + policyOne := SendTx + + addrTwo := common.HexToAddress("0xabcdef1234567890") + policyTwo := SendTx + + // Add the policy to the ACL + require.NoError(t, AddPolicy(ctx, db, "blocklist", addrInit, policyInit)) + require.NoError(t, AddPolicy(ctx, db, "blocklist", addrOne, policyOne)) + require.NoError(t, AddPolicy(ctx, db, "blocklist", addrTwo, policyTwo)) + + // Create expected policyTransaction output and append to []PolicyTransaction + policyTransactionInit := PolicyTransaction{addr: common.HexToAddress("0x0000000000000000"), aclType: ResolveACLTypeToBinary("blocklist"), policy: Policy(SendTx.ToByte()), operation: Operation(ModeChange.ToByte())} + policyTransactionOne := PolicyTransaction{addr: common.HexToAddress("0x1234567890abcdef"), aclType: ResolveACLTypeToBinary("blocklist"), policy: Policy(SendTx.ToByte()), operation: Operation(Add.ToByte())} + policyTransactionTwo := PolicyTransaction{addr: common.HexToAddress("0xabcdef1234567890"), aclType: ResolveACLTypeToBinary("blocklist"), policy: Policy(SendTx.ToByte()), operation: Operation(Add.ToByte())} + + // LastPolicyTransactions seems to append in reverse order than this test function. So the order of elements is also reversed + // No element in PolicyTransaction slice + var policyTransactionSliceNone []PolicyTransaction + + // Single element in PolicyTransaction slice, always starting with policyTransactionInit + var policyTransactionSliceSingle []PolicyTransaction + policyTransactionSliceSingle = append(policyTransactionSliceSingle, policyTransactionInit) + + // Two elements in PolicyTransaction slice, always starting with policyTransactionInit + var policyTransactionSliceDouble []PolicyTransaction + policyTransactionSliceDouble = append(policyTransactionSliceDouble, policyTransactionInit) + policyTransactionSliceDouble = append(policyTransactionSliceDouble, policyTransactionTwo) + + // Three elements in PolicyTransaction slice, always starting with policyTransactionInit + var policyTransactionSliceTriple []PolicyTransaction + policyTransactionSliceTriple = append(policyTransactionSliceTriple, policyTransactionInit) + policyTransactionSliceTriple = append(policyTransactionSliceTriple, policyTransactionTwo) + policyTransactionSliceTriple = append(policyTransactionSliceTriple, policyTransactionOne) + + // Table driven test + var tests = []struct { + count int + want []PolicyTransaction + }{ + {0, policyTransactionSliceNone}, + {1, policyTransactionSliceSingle}, + {2, policyTransactionSliceDouble}, + {3, policyTransactionSliceTriple}, + } + for _, tt := range tests { + t.Run("LastPolicyTransactions", func(t *testing.T) { + ans, err := LastPolicyTransactions(ctx, db, tt.count) + if err != nil { + t.Errorf("LastPolicyTransactions did not execute successfully: %v", err) + } + if !policyTransactionSliceEqual(ans, tt.want) { + t.Errorf("got %v, want %v", ans, tt.want) + } + }) + } +} + func TestIsActionAllowed(t *testing.T) { db := newTestACLDB(t, "") ctx := context.Background()