Skip to content

Commit

Permalink
Merge pull request #16 from lklimek/update-llmq-types
Browse files Browse the repository at this point in the history
feat(btcjson): LLMQ types update, validation and name mapping
  • Loading branch information
QuantumExplorer committed Feb 3, 2023
2 parents a9800ac + 1645f98 commit 221b7c3
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 17 deletions.
70 changes: 63 additions & 7 deletions btcjson/dashevocmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

package btcjson

import "errors"
import (
"errors"
"fmt"
)

func init() {
// No special flags for commands in this file.
Expand Down Expand Up @@ -119,20 +122,73 @@ const (
type LLMQType int

// Enum of LLMQTypes
// https://github.com/dashpay/dips/blob/master/dip-0006.md#current-llmq-types
// See https://github.com/dashpay/dips/blob/master/dip-0006.md#current-llmq-types and
// https://github.com/dashpay/dash/blob/master/src/llmq/params.h
const (
LLMQType_50_60 LLMQType = 1 //every 24 blocks
LLMQType_400_60 LLMQType = 2 //288 blocks
LLMQType_400_85 LLMQType = 3 //576 blocks
LLMQType_100_67 LLMQType = 4 //every 24 blocks
LLMQType_5_60 LLMQType = 100 //24 blocks
LLMQType_50_60 LLMQType = 1 // 50 members, 30 (60%) threshold, one per hour
LLMQType_400_60 LLMQType = 2 // 400 members, 240 (60%) threshold, one every 12 hours
LLMQType_400_85 LLMQType = 3 // 400 members, 340 (85%) threshold, one every 24 hours
LLMQType_100_67 LLMQType = 4 // 100 members, 67 (67%) threshold, one per hour
LLMQType_60_75 LLMQType = 5 // 60 members, 45 (75%) threshold, one every 12 hours
LLMQType_TEST LLMQType = 100 // 3 members, 2 (66%) threshold, one per hour
LLMQType_DEVNET LLMQType = 101 // 12 members, 6 (50%) threshold, one per hour
LLMQType_TEST_V17 LLMQType = 102 // 3 members, 2 (66%) threshold, one per hour
LLMQType_TEST_DIP0024 LLMQType = 103 // 4 members, 2 (66%) threshold, one per hour
LLMQType_TEST_INSTANTSEND LLMQType = 104 // 3 members, 2 (66%) threshold, one per hour
LLMQType_DEVNET_DIP0024 LLMQType = 105 // 8 members, 4 (50%) threshold, one per hour

// LLMQType_5_60 is replaced with LLMQType_TEST to adhere to DIP-0006 naming
LLMQType_5_60 LLMQType = LLMQType_TEST
)

var (
errWrongSizeOfArgs = errors.New("wrong size of arguments")
errQuorumUnmarshalerNotFound = errors.New("quorum unmarshaler not found")

llmqTypes map[string]LLMQType = map[string]LLMQType{
"llmq_50_60": LLMQType_50_60,
"llmq_400_60": LLMQType_400_60,
"llmq_400_85": LLMQType_400_85,
"llmq_100_67": LLMQType_100_67,
"llmq_60_75": LLMQType_60_75,
"llmq_test": LLMQType_TEST,
"llmq_devnet": LLMQType_DEVNET,
"llmq_test_v17": LLMQType_TEST_V17,
"llmq_test_dip0024": LLMQType_TEST_DIP0024,
"llmq_test_instantsend": LLMQType_TEST_INSTANTSEND,
"llmq_devnet_dip0024": LLMQType_DEVNET_DIP0024,
}
)

// GetLLMQType returns LLMQ type for the given name.
// Returns 0 when the name is not supported.
func GetLLMQType(name string) LLMQType {
return llmqTypes[name]
}

// Name returns name of the LLMQType.
// Returns empty string when the type is invalid.
// See https://github.com/dashpay/dash/blob/master/src/llmq/params.h
func (t LLMQType) Name() string {
for name, item := range llmqTypes {
if t == item {
return name
}
}
return ""
}

// Validate checks if provided LLMQ type is valid, eg. if it's one of LLMQ types
// defined in accordance with DIP-0006.
// See https://github.com/dashpay/dips/blob/master/dip-0006/llmq-types.md
func (t LLMQType) Validate() error {
if (t >= LLMQType_50_60 && t <= LLMQType_60_75) || (t >= LLMQType_TEST && t <= LLMQType_DEVNET_DIP0024) {
return nil
}

return fmt.Errorf("unsupported quorum type %d", t)
}

// QuorumCmd defines the quorum JSON-RPC command.
type QuorumCmd struct {
SubCmd QuorumCmdSubCmd `jsonrpcusage:"\"list|info|dkgstatus|sign|getrecsig|hasrecsig|isconflicting|memberof|selectquorum\""`
Expand Down
44 changes: 44 additions & 0 deletions btcjson/dashevocmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"testing"

"github.com/dashevo/dashd-go/btcjson"
Expand Down Expand Up @@ -177,3 +178,46 @@ func TestDashEvoCmds(t *testing.T) {
}
}
}

func TestLLMQTypeValidate(t *testing.T) {
testCases := []struct {
llmqType btcjson.LLMQType
expectErr bool
}{{-1, true}, {0, true}, {1, false}, {2, false}, {5, false}, {6, true}, {99, true}, {100, false}, {105, false}, {106, true}}

for _, tc := range testCases {
t.Run(strconv.Itoa(int(tc.llmqType)), func(t *testing.T) {
err := tc.llmqType.Validate()
if (err != nil) != tc.expectErr {
t.Errorf("LLMQ Type %d, expected error %v, got %s", tc.llmqType, tc.expectErr, err)
}
})
}

}

func TestLLMQTypeString(t *testing.T) {
testCases := []struct {
llmqType btcjson.LLMQType
name string
}{
{0, ""},
{btcjson.LLMQType_400_60, "llmq_400_60"},
{btcjson.LLMQType_TEST, "llmq_test"},
{btcjson.LLMQType_5_60, "llmq_test"}, // exception
{999999, ""},
}
for _, tc := range testCases {
t.Run(strconv.Itoa(int(tc.llmqType)), func(t *testing.T) {
gotName := tc.llmqType.Name()
if gotName != tc.name {
t.Errorf("invalid llmq type name, got: %s, expected: %s", tc.llmqType.Name(), tc.name)
}

gotType := btcjson.GetLLMQType(tc.name)
if (gotName != "" && tc.llmqType != gotType) || (gotName == "" && gotType != 0) {
t.Errorf("invalid llmq type, got: %d, expected: %d", gotType, tc.llmqType)
}
})
}
}
12 changes: 2 additions & 10 deletions rpcclient/evo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,6 @@ func TestQuorumMemberOf(t *testing.T) {
compareWithCliCommand(t, &result, &cli, "quorum", "memberof", proTxHash)
}

var llmqTypes = map[string]btcjson.LLMQType{
"llmq_50_60": btcjson.LLMQType_50_60,
"llmq_400_60": btcjson.LLMQType_400_60,
"llmq_400_85": btcjson.LLMQType_400_85,
"llmq_100_67": btcjson.LLMQType_100_67,
"llmq_5_60": btcjson.LLMQType_5_60,
}

func TestQuorumSign(t *testing.T) {
requestID := "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234"
messageHash := "51c11d287dfa85aef3eebb5420834c8e443e01d15c0b0a8e397d67e2e51aa239"
Expand Down Expand Up @@ -258,8 +250,8 @@ func TestQuorumSign(t *testing.T) {
t.Fatal("not a member of any quorums")
}
quorumHash := mo[0].QuorumHash
quorumType, ok := llmqTypes[mo[0].Type]
if !ok {
quorumType := btcjson.GetLLMQType(mo[0].Type)
if quorumType == 0 {
t.Fatal("unknown quorum type", mo[0].Type)
}

Expand Down

0 comments on commit 221b7c3

Please sign in to comment.