From ee4369c3bc78a0805ee53b3586781c0b164c3285 Mon Sep 17 00:00:00 2001 From: Jeffrey Picard Date: Fri, 14 Jan 2022 17:40:08 -0500 Subject: [PATCH] ClaimToTXO --- db/prefixes/prefixes.go | 108 ++++++++++++++++++++++++++++++++--- db/prefixes/prefixes_test.go | 76 ++++++++++++++++++++++++ main.go | 4 +- resources/claim_to_txo.csv | 10 ++++ 4 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 resources/claim_to_txo.csv diff --git a/db/prefixes/prefixes.go b/db/prefixes/prefixes.go index a06d4a3..2c5d886 100644 --- a/db/prefixes/prefixes.go +++ b/db/prefixes/prefixes.go @@ -285,20 +285,112 @@ type ClaimToTXOKey struct { } type ClaimToTXOValue struct { - TxNum int32 `json:"tx_num"` - Position int32 `json:"position"` - RootTxNum int32 `json:"root_tx_num"` - RootPosition int32 `json:"root_position"` - Amount int32 `json:"amount"` + TxNum uint32 `json:"tx_num"` + Position uint16 `json:"position"` + RootTxNum uint32 `json:"root_tx_num"` + RootPosition uint16 `json:"root_position"` + Amount uint64 `json:"amount"` ChannelSignatureIsValid bool `json:"channel_signature_is_valid"` Name string `json:"name"` } func (v *ClaimToTXOValue) NormalizedName() string { - //TODO implemented + //TODO implement return v.Name } +func (k *ClaimToTXOKey) PackKey() []byte { + prefixLen := 1 + // b'>20s' + n := prefixLen + 20 + key := make([]byte, n) + copy(key, k.Prefix) + copy(key[prefixLen:], k.ClaimHash[:20]) + + return key +} + +func (v *ClaimToTXOValue) PackValue() []byte { + nameLen := len(v.Name) + n := 4 + 2 + 4 + 2 + 8 + 1 + 2 + nameLen + value := make([]byte, n) + binary.BigEndian.PutUint32(value, v.TxNum) + binary.BigEndian.PutUint16(value[4:], v.Position) + binary.BigEndian.PutUint32(value[6:], v.RootTxNum) + binary.BigEndian.PutUint16(value[10:], v.RootPosition) + binary.BigEndian.PutUint64(value[12:], v.Amount) + var bitSetVar uint8 + if v.ChannelSignatureIsValid { + bitSetVar = 1 + } + value[20] = bitSetVar + binary.BigEndian.PutUint16(value[21:], uint16(nameLen)) + copy(value[23:], []byte(v.Name[:nameLen])) + + return value +} + +func ClaimToTXOKeyPackPartialNFields(nFields int) func(*ClaimToTXOKey) []byte { + return func(u *ClaimToTXOKey) []byte { + return ClaimToTXOKeyPackPartial(u, nFields) + } +} + +func ClaimToTXOKeyPackPartial(k *ClaimToTXOKey, nFields int) []byte { + // Limit nFields between 0 and number of fields, we always at least need + // the prefix, and we never need to iterate past the number of fields. + if nFields > 1 { + nFields = 1 + } + if nFields < 0 { + nFields = 0 + } + + // b'>4sLH' + prefixLen := 1 + var n = prefixLen + for i := 0; i <= nFields; i++ { + switch i { + case 1: + n += 20 + } + } + + key := make([]byte, n) + + for i := 0; i <= nFields; i++ { + switch i { + case 0: + copy(key, k.Prefix) + case 1: + copy(key[prefixLen:], k.ClaimHash[:20]) + } + } + + return key +} + +func ClaimToTXOKeyUnpack(key []byte) *ClaimToTXOKey { + prefixLen := 1 + return &ClaimToTXOKey{ + Prefix: key[:prefixLen], + ClaimHash: key[prefixLen : prefixLen+20], + } +} + +func ClaimToTXOValueUnpack(value []byte) *ClaimToTXOValue { + nameLen := binary.BigEndian.Uint16(value[21:]) + return &ClaimToTXOValue{ + TxNum: binary.BigEndian.Uint32(value), + Position: binary.BigEndian.Uint16(value[4:]), + RootTxNum: binary.BigEndian.Uint32(value[6:]), + RootPosition: binary.BigEndian.Uint16(value[10:]), + Amount: binary.BigEndian.Uint64(value[12:]), + ChannelSignatureIsValid: value[20] == 1, + Name: string(value[23 : 23+nameLen]), + } +} + /* class TXOToClaimKey(typing.NamedTuple): tx_num: int @@ -2390,7 +2482,7 @@ func UnpackGenericKey(key []byte) (byte, interface{}, error) { return SupportToClaim, SupportToClaimKeyUnpack(key), nil case ClaimToTXO: - return 0x0, nil, errors.Base("key unpack function for %v not implemented", firstByte) + return ClaimToTXO, ClaimToTXOKeyUnpack(key), nil case TXOToClaim: return TXOToClaim, TXOToClaimKeyUnpack(key), nil @@ -2461,7 +2553,7 @@ func UnpackGenericValue(key, value []byte) (byte, interface{}, error) { return SupportToClaim, SupportToClaimValueUnpack(value), nil case ClaimToTXO: - return 0x0, nil, errors.Base("value unpack not implemented for key %v", key) + return ClaimToTXO, ClaimToTXOValueUnpack(value), nil case TXOToClaim: return TXOToClaim, TXOToClaimValueUnpack(value), nil diff --git a/db/prefixes/prefixes_test.go b/db/prefixes/prefixes_test.go index 6707848..59ec3f0 100644 --- a/db/prefixes/prefixes_test.go +++ b/db/prefixes/prefixes_test.go @@ -44,6 +44,82 @@ func testInit(filePath string) (*grocksdb.DB, [][]string, func()) { return db, records, toDefer } +func TestClaimToTXO(t *testing.T) { + + filePath := "../../resources/claim_to_txo.csv" + + wOpts := grocksdb.NewDefaultWriteOptions() + db, records, toDefer := testInit(filePath) + defer toDefer() + for _, record := range records { + key, err := hex.DecodeString(record[0]) + if err != nil { + log.Println(err) + } + val, err := hex.DecodeString(record[1]) + if err != nil { + log.Println(err) + } + db.Put(wOpts, key, val) + } + // test prefix + options := dbpkg.NewIterateOptions().WithPrefix([]byte{prefixes.ClaimToTXO}).WithIncludeValue(true) + ch := dbpkg.Iter(db, options) + var i = 0 + for kv := range ch { + // log.Println(kv.Key) + gotKey := kv.Key.(*prefixes.ClaimToTXOKey).PackKey() + + keyPartial1 := prefixes.ClaimToTXOKeyPackPartial(kv.Key.(*prefixes.ClaimToTXOKey), 1) + + // Check pack partial for sanity + if !bytes.HasPrefix(gotKey, keyPartial1) { + t.Errorf("%+v should be prefix of %+v\n", keyPartial1, gotKey) + } + + got := kv.Value.(*prefixes.ClaimToTXOValue).PackValue() + wantKey, err := hex.DecodeString(records[i][0]) + if err != nil { + log.Println(err) + } + want, err := hex.DecodeString(records[i][1]) + if err != nil { + log.Println(err) + } + if !bytes.Equal(gotKey, wantKey) { + t.Errorf("gotKey: %+v, wantKey: %+v\n", got, want) + } + if !bytes.Equal(got, want) { + t.Errorf("got: %+v, want: %+v\n", got, want) + } + i++ + } + + // Test start / stop + start, err := hex.DecodeString(records[0][0]) + if err != nil { + log.Println(err) + } + stop, err := hex.DecodeString(records[9][0]) + if err != nil { + log.Println(err) + } + options2 := dbpkg.NewIterateOptions().WithStart(start).WithStop(stop).WithIncludeValue(true) + ch2 := dbpkg.Iter(db, options2) + i = 0 + for kv := range ch2 { + got := kv.Value.(*prefixes.ClaimToTXOValue).PackValue() + want, err := hex.DecodeString(records[i][1]) + if err != nil { + log.Println(err) + } + if !bytes.Equal(got, want) { + t.Errorf("got: %+v, want: %+v\n", got, want) + } + i++ + } +} + func TestTXOToClaim(t *testing.T) { filePath := "../../resources/txo_to_claim.csv" diff --git a/main.go b/main.go index e5ccedd..90e8d42 100644 --- a/main.go +++ b/main.go @@ -38,7 +38,7 @@ func main() { options := &db.IterOptions{ FillCache: false, - Prefix: []byte{prefixes.TXOToClaim}, + Prefix: []byte{prefixes.ClaimToTXO}, Start: nil, Stop: nil, IncludeStart: true, @@ -49,7 +49,7 @@ func main() { RawValue: true, } - db.ReadWriteRawN(dbVal, options, "./resources/txo_to_claim.csv", 10) + db.ReadWriteRawN(dbVal, options, "./resources/claim_to_txo.csv", 10) return } diff --git a/resources/claim_to_txo.csv b/resources/claim_to_txo.csv new file mode 100644 index 0000000..6f24042 --- /dev/null +++ b/resources/claim_to_txo.csv @@ -0,0 +1,10 @@ +45000000a420c44374f4f399ab4807fa1901eefc87,0297ec2100000297ec21000000000000000f42400100246167656e63652d64c3a974727569742c2d6e6f7576656175782d736b696e732d6c65616b +45000000c27eef5ea69e0d73f118826c7e326bb469,00371d66000000371d660000000000001dcd650001000e4d696e696174757265486f757365 +4500000110e40894573f528c393fbcec7a472ec853,01516b32000001516b3200000000000000989680010021696f2d3137372d4e6f616d2d43686f6d736b792d6f6e2d434f494e54454c50524f +4500000324e40fcb63a0b517a3660645e9bd99244a,030bb6ba0000030bb6ba000000000000000f424001001b436f6e616e2d4578696c65732d526169642d4561726c792d457261 +45000003d1538a0f19f5cd4bc1a62cc294f5c89934,011c7c990000011c7c99000000000000000f424001001130322d636172726167652d68616e646c65 +45000008d47beeff8325e795a8604226145b01702b,02dbb2a2000002dbb2a2000000000000000186a001001039643336363661336161313231376138 +4500000906499e073e94370ceff37cb21c28212444,0369842d00000369842d000000000000000186a001001033333465356465363139306534323466 +45000009c3172e034a255f3c03566dca84bb9f046a,0225c69c000002251b0f0000000000000007a120010028617574686f722d73746f726965732d706f64636173742d657069736f64652d3734332d6b6172656e +45000009ca6e0caaaef16872b4bd4f6f1b8c2363e2,02b16956000002b16956000000000000000f4240010027554e2d504f55522d43454e542d28312d292d28536f72616c2c2d4162c3a963c3a9646169726529 +4500000ad9ded2e15d18987900d09e9b29ef33d03e,02c972b3000002c972b3000000000000000186a0010006313331333333