diff --git a/db/db.go b/db/db.go index 4d0a776..3fba812 100644 --- a/db/db.go +++ b/db/db.go @@ -82,6 +82,7 @@ type ResolveError struct { type OptionalResolveResultOrError interface { GetResult() *ResolveResult GetError() *ResolveError + String() string } type optionalResolveResultOrError struct { @@ -97,6 +98,26 @@ func (x *optionalResolveResultOrError) GetError() *ResolveError { return x.err } +func (x *ResolveResult) String() string { + // return fmt.Sprintf("ResolveResult{Name: %s, NormalizedName: %s, ClaimHash: %s, TxNum: %d, Position: %d, TxHash: %s, Height: %d, Amount: %d, ShortUrl: %s, IsControlling: %v, CanonicalUrl: %s, CreationHeight: %d, ActivationHeight: %d, ExpirationHeight: %d, EffectiveAmount: %d, SupportAmount: %d, Reposted: %d, LastTakeoverHeight: %d, ClaimsInChannel: %d, ChannelHash: %s, RepostedClaimHash: %s, SignatureValid: %v}", + // x.Name, x.NormalizedName, hex.EncodeToString(x.ClaimHash), x.TxNum, x.Position, hex.EncodeToString(x.TxHash), x.Height, x.Amount, x.ShortUrl, x.IsControlling, x.CanonicalUrl, x.CreationHeight, x.ActivationHeight, x.ExpirationHeight, x.EffectiveAmount, x.SupportAmount, x.Reposted, x.LastTakeoverHeight, x.ClaimsInChannel, hex.EncodeToString(x.ChannelHash), hex.EncodeToString(x.RepostedClaimHash), x.SignatureValid) + return fmt.Sprintf("%#v", x) +} + +func (x *ResolveError) String() string { + return fmt.Sprintf("ResolveError{Error: %#v}", x.Error) +} + +func (x *optionalResolveResultOrError) String() string { + if x.res != nil { + return x.res.String() + } + if x.err != nil { + return x.err.String() + } + return fmt.Sprintf("%#v", x) +} + type ExpandedResolveResult struct { Stream OptionalResolveResultOrError Channel OptionalResolveResultOrError @@ -104,6 +125,10 @@ type ExpandedResolveResult struct { RepostedChannel OptionalResolveResultOrError } +func (x *ExpandedResolveResult) String() string { + return fmt.Sprintf("ExpandedResolveResult{Stream: %s, Channel: %s, Repost: %s, RepostedChannel: %s}", x.Stream, x.Channel, x.Repost, x.RepostedChannel) +} + type IterOptions struct { FillCache bool Prefix []byte @@ -240,13 +265,26 @@ func GetExpirationHeightFull(lastUpdatedHeight uint32, extended bool) uint32 { return lastUpdatedHeight + NExtendedClaimExpirationTime } +// EnsureHandle is a helper function to ensure that the db has a handle to the given column family. +func EnsureHandle(db *ReadOnlyDBColumnFamily, prefix byte) (*grocksdb.ColumnFamilyHandle, error) { + cfName := string(prefix) + handle := db.Handles[cfName] + if handle == nil { + return nil, fmt.Errorf("%s handle not found", cfName) + } + return handle, nil +} + // // DB Get functions // func GetClaimsInChannelCount(db *ReadOnlyDBColumnFamily, channelHash []byte) (uint32, error) { - prefix := []byte{prefixes.ChannelCount} - handle := db.Handles[string(prefix)] + handle, err := EnsureHandle(db, prefixes.ChannelCount) + if err != nil { + return 0, err + } + key := prefixes.NewChannelCountKey(channelHash) rawKey := key.PackKey() @@ -266,7 +304,11 @@ func GetClaimsInChannelCount(db *ReadOnlyDBColumnFamily, channelHash []byte) (ui func GetShortClaimIdUrl(db *ReadOnlyDBColumnFamily, name string, normalizedName string, claimHash []byte, rootTxNum uint32, rootPosition uint16) (string, error) { prefix := []byte{prefixes.ClaimShortIdPrefix} - handle := db.Handles[string(prefix)] + handle, err := EnsureHandle(db, prefixes.ClaimShortIdPrefix) + if err != nil { + return "", err + } + claimId := hex.EncodeToString(claimHash) claimIdLen := len(claimId) for prefixLen := 0; prefixLen < 10; prefixLen++ { @@ -276,6 +318,7 @@ func GetShortClaimIdUrl(db *ReadOnlyDBColumnFamily, name string, normalizedName } partialClaimId := claimId[:j] partialKey := prefixes.NewClaimShortIDKey(normalizedName, partialClaimId) + log.Printf("partialKey: %#v\n", partialKey) keyPrefix := prefixes.ClaimShortIDKeyPackPartial(partialKey, 2) // Prefix and handle options := NewIterateOptions().WithPrefix(prefix).WithCfHandle(handle) @@ -286,6 +329,10 @@ func GetShortClaimIdUrl(db *ReadOnlyDBColumnFamily, name string, normalizedName ch := IterCF(db.DB, options) row := <-ch + if row == nil { + continue + } + key := row.Key.(*prefixes.ClaimShortIDKey) if key.RootTxNum == rootTxNum && key.RootPosition == rootPosition { return fmt.Sprintf("%s#%s", name, key.PartialClaimId), nil @@ -295,8 +342,11 @@ func GetShortClaimIdUrl(db *ReadOnlyDBColumnFamily, name string, normalizedName } func GetRepost(db *ReadOnlyDBColumnFamily, claimHash []byte) ([]byte, error) { - prefix := []byte{prefixes.Repost} - handle := db.Handles[string(prefix)] + handle, err := EnsureHandle(db, prefixes.Repost) + if err != nil { + return nil, err + } + key := prefixes.NewRepostKey(claimHash) rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) @@ -313,8 +363,11 @@ func GetRepost(db *ReadOnlyDBColumnFamily, claimHash []byte) ([]byte, error) { } func GetRepostedCount(db *ReadOnlyDBColumnFamily, claimHash []byte) (int, error) { - prefix := []byte{prefixes.RepostedClaim} - handle := db.Handles[string(prefix)] + handle, err := EnsureHandle(db, prefixes.RepostedClaim) + if err != nil { + return 0, err + } + key := prefixes.NewRepostedKey(claimHash) keyPrefix := prefixes.RepostedKeyPackPartial(key, 1) // Prefix and handle @@ -335,9 +388,12 @@ func GetRepostedCount(db *ReadOnlyDBColumnFamily, claimHash []byte) (int, error) } func GetChannelForClaim(db *ReadOnlyDBColumnFamily, claimHash []byte, txNum uint32, position uint16) ([]byte, error) { + handle, err := EnsureHandle(db, prefixes.ClaimToChannel) + if err != nil { + return nil, err + } + key := prefixes.NewClaimToChannelKey(claimHash, txNum, position) - cfName := string(prefixes.ClaimToChannel) - handle := db.Handles[cfName] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -353,8 +409,11 @@ func GetChannelForClaim(db *ReadOnlyDBColumnFamily, claimHash []byte, txNum uint } func GetActiveAmount(db *ReadOnlyDBColumnFamily, claimHash []byte, txoType uint8, height uint32) (uint64, error) { - cfName := string(prefixes.ActiveAmount) - handle := db.Handles[cfName] + handle, err := EnsureHandle(db, prefixes.ActiveAmount) + if err != nil { + return 0, err + } + startKey := prefixes.NewActiveAmountKey(claimHash, txoType, 0) endKey := prefixes.NewActiveAmountKey(claimHash, txoType, height) @@ -395,9 +454,12 @@ func GetEffectiveAmount(db *ReadOnlyDBColumnFamily, claimHash []byte, supportOnl } func GetSupportAmount(db *ReadOnlyDBColumnFamily, claimHash []byte) (uint64, error) { + handle, err := EnsureHandle(db, prefixes.SupportAmount) + if err != nil { + return 0, err + } + key := prefixes.NewSupportAmountKey(claimHash) - cfName := string(prefixes.SupportAmount) - handle := db.Handles[cfName] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -419,9 +481,12 @@ func GetTxHash(db *ReadOnlyDBColumnFamily, txNum uint32) ([]byte, error) { return self.prefix_db.tx_hash.get(tx_num, deserialize_value=False) */ // TODO: caching + handle, err := EnsureHandle(db, prefixes.TxHash) + if err != nil { + return nil, err + } + key := prefixes.NewTxHashKey(txNum) - cfName := string(prefixes.TxHash) - handle := db.Handles[cfName] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -442,6 +507,12 @@ func GetActivation(db *ReadOnlyDBColumnFamily, txNum uint32, postition uint16) ( func GetActivationFull(db *ReadOnlyDBColumnFamily, txNum uint32, postition uint16, isSupport bool) (uint32, error) { var typ uint8 + + handle, err := EnsureHandle(db, prefixes.ActivatedClaimAndSupport) + if err != nil { + return 0, err + } + if isSupport { typ = prefixes.ACTIVATED_SUPPORT_TXO_TYPE } else { @@ -449,8 +520,6 @@ func GetActivationFull(db *ReadOnlyDBColumnFamily, txNum uint32, postition uint1 } key := prefixes.NewActivationKey(typ, txNum, postition) - cfName := string(prefixes.ActivatedClaimAndSupport) - handle := db.Handles[cfName] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -465,9 +534,12 @@ func GetActivationFull(db *ReadOnlyDBColumnFamily, txNum uint32, postition uint1 func GetCachedClaimTxo(db *ReadOnlyDBColumnFamily, claim []byte) (*prefixes.ClaimToTXOValue, error) { // TODO: implement cache + handle, err := EnsureHandle(db, prefixes.ClaimToTXO) + if err != nil { + return nil, err + } + key := prefixes.NewClaimToTXOKey(claim) - cfName := string(prefixes.ClaimToTXO) - handle := db.Handles[cfName] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -484,9 +556,12 @@ func GetCachedClaimTxo(db *ReadOnlyDBColumnFamily, claim []byte) (*prefixes.Clai } func GetControllingClaim(db *ReadOnlyDBColumnFamily, name string) (*prefixes.ClaimTakeoverValue, error) { + handle, err := EnsureHandle(db, prefixes.ClaimTakeover) + if err != nil { + return nil, err + } + key := prefixes.NewClaimTakeoverKey(name) - cfName := string(prefixes.ClaimTakeover) - handle := db.Handles[cfName] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -528,9 +603,12 @@ func FsGetClaimByHash(db *ReadOnlyDBColumnFamily, claimHash []byte) (*ResolveRes } func GetDBState(db *ReadOnlyDBColumnFamily) (*prefixes.DBStateValue, error) { - prefix := []byte{prefixes.DBState} + handle, err := EnsureHandle(db, prefixes.DBState) + if err != nil { + return nil, err + } + key := prefixes.NewDBStateKey() - handle := db.Handles[string(prefix)] rawKey := key.PackKey() slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { @@ -546,8 +624,10 @@ func GetDBState(db *ReadOnlyDBColumnFamily) (*prefixes.DBStateValue, error) { } func ClaimShortIdIter(db *ReadOnlyDBColumnFamily, normalizedName string, claimId string) <-chan *prefixes.PrefixRowKV { - prefix := []byte{prefixes.ClaimShortIdPrefix} - handle := db.Handles[string(prefix)] + handle, err := EnsureHandle(db, prefixes.ClaimShortIdPrefix) + if err != nil { + return nil + } key := prefixes.NewClaimShortIDKey(normalizedName, claimId) var rawKeyPrefix []byte = nil if claimId != "" { @@ -563,10 +643,14 @@ func ClaimShortIdIter(db *ReadOnlyDBColumnFamily, normalizedName string, claimId func GetCachedClaimHash(db *ReadOnlyDBColumnFamily, txNum uint32, position uint16) (*prefixes.TXOToClaimValue, error) { // TODO: implement cache + handle, err := EnsureHandle(db, prefixes.TXOToClaim) + if err != nil { + return nil, err + } + key := prefixes.NewTXOToClaimKey(txNum, position) - cfName := string(prefixes.TXOToClaim) - handle := db.Handles[cfName] rawKey := key.PackKey() + slice, err := db.DB.GetCF(db.Opts, handle, rawKey) if err != nil { return nil, err @@ -839,8 +923,11 @@ func ResolveParsedUrl(db *ReadOnlyDBColumnFamily, parsed *PathSegment) (*Resolve } func ResolveClaimInChannel(db *ReadOnlyDBColumnFamily, channelHash []byte, normalizedName string) (*ResolveResult, error) { - prefix := []byte{prefixes.ChannelToClaim} - handle := db.Handles[string(prefix)] + handle, err := EnsureHandle(db, prefixes.ChannelToClaim) + if err != nil { + return nil, err + } + key := prefixes.NewChannelToClaimKey(channelHash, normalizedName) rawKeyPrefix := prefixes.ChannelToClaimKeyPackPartial(key, 2) options := NewIterateOptions().WithCfHandle(handle).WithPrefix(rawKeyPrefix) @@ -959,8 +1046,10 @@ func Resolve(db *ReadOnlyDBColumnFamily, url string) *ExpandedResolveResult { if resolvedChannel != nil { streamClaim, err := ResolveClaimInChannel(db, resolvedChannel.ClaimHash, stream.Normalized()) log.Printf("streamClaim %#v\n", streamClaim) - log.Printf("streamClaim.ClaimHash: %s\n", hex.EncodeToString(streamClaim.ClaimHash)) - log.Printf("streamClaim.ChannelHash: %s\n", hex.EncodeToString(streamClaim.ChannelHash)) + if streamClaim != nil { + log.Printf("streamClaim.ClaimHash: %s\n", hex.EncodeToString(streamClaim.ClaimHash)) + log.Printf("streamClaim.ChannelHash: %s\n", hex.EncodeToString(streamClaim.ChannelHash)) + } // TODO: Confirm error case if err != nil { res.Stream = &optionalResolveResultOrError{ @@ -968,6 +1057,7 @@ func Resolve(db *ReadOnlyDBColumnFamily, url string) *ExpandedResolveResult { } return res } + if streamClaim != nil { resolvedStream, err = FsGetClaimByHash(db, streamClaim.ClaimHash) // TODO: Confirm error case diff --git a/db/db_test.go b/db/db_test.go index ff2a3c5..4917bc5 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -279,19 +279,27 @@ func TestOpenFullDB(t *testing.T) { } expandedResolveResult := dbpkg.Resolve(db, url) log.Printf("expandedResolveResult: %#v\n", expandedResolveResult) + log.Printf("expandedResolveResult: %s\n", expandedResolveResult) } -// FIXME: Needs new data format +// TODO: Finish the constructed data set for the stream part of this resolve. func TestResolve(t *testing.T) { - filePath := "../testdata/P_resolve.csv" + url := "lbry://@Styxhexenhammer666#2/legacy-media-baron-les-moonves-(cbs#9" + filePath := "../testdata/FULL_resolve.csv" db, _, toDefer, err := OpenAndFillTmpDBColumnFamlies(filePath) if err != nil { t.Error(err) return } defer toDefer() - expandedResolveResult := dbpkg.Resolve(db, "asdf") - log.Println(expandedResolveResult) + expandedResolveResult := dbpkg.Resolve(db, url) + log.Printf("%#v\n", expandedResolveResult) + if expandedResolveResult != nil && expandedResolveResult.Channel != nil { + log.Println(expandedResolveResult.Channel.GetError()) + } + if expandedResolveResult != nil && expandedResolveResult.Stream != nil { + log.Println(expandedResolveResult.Stream.GetError()) + } } func TestGetDBState(t *testing.T) { @@ -404,19 +412,20 @@ func TestGetClaimsInChannelCount(t *testing.T) { } func TestPrintClaimShortId(t *testing.T) { - filePath := "../testdata/F_cat.csv" + filePath := "../testdata/F_resolve.csv" CatCSV(filePath) } // TestGetShortClaimIdUrl tests resolving a claim to a short url. func TestGetShortClaimIdUrl(t *testing.T) { - // &{[70] cat 0 2104436 0} - name := "cat" - normalName := "cat" - claimHash := []byte{} - var rootTxNum uint32 = 2104436 + name := "@Styxhexenhammer666" + normalName := util.NormalizeName(name) + claimHash, _ := hex.DecodeString("2556ed1cab9d17f2a9392030a9ad7f5d138f11bd") + // claimHash := []byte{} + var rootTxNum uint32 = 0x61ec7c var position uint16 = 0 - filePath := "../testdata/F_cat.csv" + filePath := "../testdata/F_resolve.csv" + log.Println(filePath) db, _, toDefer, err := OpenAndFillTmpDBColumnFamlies(filePath) if err != nil { t.Error(err) diff --git a/main.go b/main.go index 2e627e9..94cbbed 100644 --- a/main.go +++ b/main.go @@ -113,20 +113,20 @@ func main() { } else if args.CmdType == server.DBCmd3 { // streamHash, _ := hex.DecodeString("9a0ed686ecdad9b6cb965c4d6681c02f0bbc66a6") channelHash, _ := hex.DecodeString("2556ed1cab9d17f2a9392030a9ad7f5d138f11bd") - // name := util.NormalizeName("@Styxhexenhammer666") + name := util.NormalizeName("@Styxhexenhammer666") // txNum := uint32(0x6284e3) // position := uint16(0x0) // For stream claim // txNum := uint32(0x369e2b2) // position := uint16(0x0) // typ := uint8(prefixes.ACTIVATED_CLAIM_TXO_TYPE) - var rawPrefix byte = prefixes.RepostedClaim + var rawPrefix byte = prefixes.ChannelToClaim var startRaw []byte = nil prefix := []byte{rawPrefix} columnFamily := string(prefix) // start := prefixes.NewClaimTakeoverKey(name) // start := prefixes.NewActiveAmountKey(channelHash, prefixes.ACTIVATED_SUPPORT_TXO_TYPE, 0) - start := prefixes.NewRepostedKey(channelHash) + start := prefixes.NewChannelToClaimKey(channelHash, name) startRaw = start.PackKey() // start := &prefixes.ChannelCountKey{ // Prefix: prefix, @@ -154,7 +154,7 @@ func main() { options.CfHandle = handles[1] - db.ReadWriteRawNColumnFamilies(dbVal, options, fmt.Sprintf("./testdata/%s_resolve.csv", columnFamily), 10) + db.ReadWriteRawNColumnFamilies(dbVal, options, fmt.Sprintf("./testdata/%s_resolve.csv", columnFamily), 1) return } diff --git a/testdata/FULL_resolve.csv b/testdata/FULL_resolve.csv new file mode 100644 index 0000000..1cb8d5d --- /dev/null +++ b/testdata/FULL_resolve.csv @@ -0,0 +1,42 @@ +EFGIJPRSVWXZas,, +E,452556ed1cab9d17f2a9392030a9ad7f5d138f11bd,006284e300000061ec7c0000000000000007a1200000134053747978686578656e68616d6d6572363636 +F,4600134073747978686578656e68616d6d657236363601320061ec7c0000,006284e30000 +F,4600134073747978686578656e68616d6d6572363636013503e4d2e60000,03e4d2e60000 +F,4600134073747978686578656e68616d6d657236363601630382eee90000,0382eee90000 +F,4600134073747978686578656e68616d6d65723636360232350061ec7c0000,006284e30000 +F,4600134073747978686578656e68616d6d657236363602356603e4d2e60000,03e4d2e60000 +F,4600134073747978686578656e68616d6d65723636360263330382eee90000,0382eee90000 +F,4600134073747978686578656e68616d6d6572363636033235350061ec7c0000,006284e30000 +F,4600134073747978686578656e68616d6d65723636360335666103e4d2e60000,03e4d2e60000 +F,4600134073747978686578656e68616d6d6572363636036333610382eee90000,0382eee90000 +F,4600134073747978686578656e68616d6d657236363604323535360061ec7c0000,006284e30000 +G,47006284e30000,2556ed1cab9d17f2a9392030a9ad7f5d138f11bd00134073747978686578656e68616d6d6572363636 +I,499a0ed686ecdad9b6cb965c4d6681c02f0bbc66a60369e2b20000,2556ed1cab9d17f2a9392030a9ad7f5d138f11bd +J,4a2556ed1cab9d17f2a9392030a9ad7f5d138f11bd0013612d73747265616d2d696e2d7665726d6f6e740069a2570000,ee29ca5c44313a2827fd35252b72557334635749 +P,5000134073747978686578656e68616d6d6572363636,2556ed1cab9d17f2a9392030a9ad7f5d138f11bd000a6471 +R,5201006284e30000,000a6b652556ed1cab9d17f2a9392030a9ad7f5d138f11bd00134073747978686578656e68616d6d6572363636 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a6b67006286030000,0000007615cbad28 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a706a0063105c0000,000000000bebc200 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a73ea006367550000,0000000005f5e100 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a7d63006469750000,0000000db0b7c894 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a7ebf00648c480000,00000000b2d05e00 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a810e0064ccc00000,000000003b9aca00 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a825b006503cf0000,00000002bf52c92c +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a88930066814a0000,00000000dc887a34 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a88f900669d240000,0000000005f5e100 +S,532556ed1cab9d17f2a9392030a9ad7f5d138f11bd02000a88f900669d260000,000000001dcd6500 +V,56000009ca6e0caaaef16872b4bd4f6f1b8c2363e2,dbdfb6cd5e83baf342eaab8b19662ed0c71aae9a +W,572556ed1cab9d17f2a9392030a9ad7f5d138f11bd00812cb90000,fa3a1c918fafd094083240fd54a3c8577b7f1094 +W,572556ed1cab9d17f2a9392030a9ad7f5d138f11bd00812ce70000,1b845565203eca16cb6135e6fb70d4d2cec4ee9b +W,572556ed1cab9d17f2a9392030a9ad7f5d138f11bd00812ce90000,c2bfc30ebdf2511a2a9a22b463f80d1f751ee38c +W,572556ed1cab9d17f2a9392030a9ad7f5d138f11bd00812d3f0000,f9c6adebfb970aa9ab1cac21f82eb007b2421a20 +W,572556ed1cab9d17f2a9392030a9ad7f5d138f11bd00e7b0800000,a3cfb4a2a4b7efda98d5f680d6dbc30b4ebb328b +W,57255761310145baa958b5587d9b5571423e5a0d3c0208ba650000,2ae0dadba7d5931105ca2e5cb1c12ec61100b9b5 +W,57255761310145baa958b5587d9b5571423e5a0d3c0208dc150000,a9389febb41d9a1c63deef395273b903caf4a18d +W,57255761310145baa958b5587d9b5571423e5a0d3c0208e3eb0000,68ab6c0cdd615540062b6f6d637f8b47ab0e615b +W,57255761310145baa958b5587d9b5571423e5a0d3c0208f7210000,3d8ee0471ae8751e016b62dca9cee5cfebc9b30d +W,57255761310145baa958b5587d9b5571423e5a0d3c02090a7b0000,0a059f3e94ed2c5a9d43986f0f14cf29f02d01ce +X,58006284e3,54e14ff0c404c29b3d39ae4d249435f167d5cd4ce5a428ecb745b3df1c8e3dde +Z,5a2556ed1cab9d17f2a9392030a9ad7f5d138f11bd,00000e56 +a,612556ed1cab9d17f2a9392030a9ad7f5d138f11bd,000007df178c203c +s,73,9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f46300105bec03f782718ccd27260ce980e7d3d0b5c5f7be1517027b68104109128a34d1cc562f32008e00105bef0014f734000700105befffffffffffffffff00105bec \ No newline at end of file diff --git a/testdata/F_resolve.csv b/testdata/F_resolve.csv new file mode 100644 index 0000000..ba135c6 --- /dev/null +++ b/testdata/F_resolve.csv @@ -0,0 +1,11 @@ +F,, +F,4600134073747978686578656e68616d6d657236363601320061ec7c0000,006284e30000 +F,4600134073747978686578656e68616d6d6572363636013503e4d2e60000,03e4d2e60000 +F,4600134073747978686578656e68616d6d657236363601630382eee90000,0382eee90000 +F,4600134073747978686578656e68616d6d65723636360232350061ec7c0000,006284e30000 +F,4600134073747978686578656e68616d6d657236363602356603e4d2e60000,03e4d2e60000 +F,4600134073747978686578656e68616d6d65723636360263330382eee90000,0382eee90000 +F,4600134073747978686578656e68616d6d6572363636033235350061ec7c0000,006284e30000 +F,4600134073747978686578656e68616d6d65723636360335666103e4d2e60000,03e4d2e60000 +F,4600134073747978686578656e68616d6d6572363636036333610382eee90000,0382eee90000 +F,4600134073747978686578656e68616d6d657236363604323535360061ec7c0000,006284e30000 diff --git a/testdata/G_resolve.csv b/testdata/G_resolve.csv new file mode 100644 index 0000000..4740c2f --- /dev/null +++ b/testdata/G_resolve.csv @@ -0,0 +1,2 @@ +G,, +G,47006284e30000,2556ed1cab9d17f2a9392030a9ad7f5d138f11bd00134073747978686578656e68616d6d6572363636 diff --git a/testdata/J_resolve.csv b/testdata/J_resolve.csv new file mode 100644 index 0000000..4288239 --- /dev/null +++ b/testdata/J_resolve.csv @@ -0,0 +1,2 @@ +J,, +J,4a2556ed1cab9d17f2a9392030a9ad7f5d138f11bd0013612d73747265616d2d696e2d7665726d6f6e740069a2570000,ee29ca5c44313a2827fd35252b72557334635749