diff --git a/go.mod b/go.mod index ca1664f..3a82ac8 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/blinklabs-io/cdnsd go 1.20 require ( - github.com/blinklabs-io/cardano-models v0.2.0 - github.com/blinklabs-io/gouroboros v0.69.5 + github.com/blinklabs-io/cardano-models v0.3.0 + github.com/blinklabs-io/gouroboros v0.70.0 github.com/blinklabs-io/snek v0.17.1 github.com/dgraph-io/badger/v4 v4.2.0 github.com/kelseyhightower/envconfig v1.4.0 @@ -18,6 +18,10 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/fxamacker/cbor/v2 v2.5.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.17.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect @@ -26,6 +30,7 @@ require ( github.com/google/flatbuffers v1.12.1 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/klauspost/compress v1.12.3 // indirect + github.com/leodido/go-urn v1.2.4 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/x448/float16 v0.8.4 // indirect go.opencensus.io v0.22.5 // indirect @@ -34,6 +39,7 @@ require ( golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.17.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index e82e532..dedddad 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/blinklabs-io/cardano-models v0.2.0 h1:fQ2vkvMLFgQodtFpYE73i+6+eNN5vaIB3GBIys8FsyI= -github.com/blinklabs-io/cardano-models v0.2.0/go.mod h1:iH8IqSca4WzFQIAT3Ssd3TviILfoCgaJQ8mc3JrIvwE= -github.com/blinklabs-io/gouroboros v0.69.5 h1:oFTObwPchrzZAunNA/+Y6g5NwMZQhA1Zj+iZGzX4TsU= -github.com/blinklabs-io/gouroboros v0.69.5/go.mod h1:ecxtryJb+vIeVizQl4nYJr0tVdyIgOTze7R9xeGqFu4= +github.com/blinklabs-io/cardano-models v0.3.0 h1:Xc7H1l4i96Vaf5bBKXrOl1ctL0vyT/bJ9+OrZUqD6E4= +github.com/blinklabs-io/cardano-models v0.3.0/go.mod h1:mahC1oL4zVM5TCqZzqZ9I2GWAcEfzhJ3tYBpjwBWVI4= +github.com/blinklabs-io/gouroboros v0.70.0 h1:/Jlo1G2c7rQDjijSXNti4v+J34QSkQwS57Vso6STqBo= +github.com/blinklabs-io/gouroboros v0.70.0/go.mod h1:ecxtryJb+vIeVizQl4nYJr0tVdyIgOTze7R9xeGqFu4= github.com/blinklabs-io/snek v0.17.1 h1:3u5eBTWF9tHQSNnHtHs7AQVSdX99xtqiPS5Hk7EU1qE= github.com/blinklabs-io/snek v0.17.1/go.mod h1:6XJ2eDcU4n5V6TgpLDod+YD7pM43JOXcCiNOrDhdtKY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -23,6 +23,15 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= +github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -53,6 +62,8 @@ github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/Vq github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -60,7 +71,12 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= @@ -114,6 +130,8 @@ golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -143,5 +161,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/config/config.go b/internal/config/config.go index e30873b..f81a4b2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,24 +14,6 @@ import ( "gopkg.in/yaml.v2" ) -// Per-network script address for Handshake -var networkScriptAddresses = map[string]string{ - "preprod": "addr_test1wpf6lxntd3dztphew0m5dagrs7ptjcg9g6vgjyazt7mw44gdnwq0h", -} - -// Per-network intercept points for starting the chain-sync -// We start the sync somewhere near where we expect the first data to appear to save time -// during the initial sync -var networkInterceptPoints = map[string]struct { - Hash string - Slot uint64 -}{ - "preprod": { - Hash: "a35a0d216e00c64c257e41089138f4d22be721281d73f2ab8ef61ca8863d04a0", - Slot: 34255089, - }, -} - type Config struct { Logging LoggingConfig `yaml:"logging"` Metrics MetricsConfig `yaml:"metrics"` @@ -39,6 +21,7 @@ type Config struct { Debug DebugConfig `yaml:"debug"` Indexer IndexerConfig `yaml:"indexer"` State StateConfig `yaml:"state"` + Profile string `yaml:"profile" envconfig:"PROFILE"` } type LoggingConfig struct { @@ -72,6 +55,9 @@ type IndexerConfig struct { ScriptAddress string `yaml:"scriptAddress" envconfig:"INDEXER_SCRIPT_ADDRESS"` InterceptHash string `yaml:"interceptHash" envconfig:"INDEXER_INTERCEPT_HASH"` InterceptSlot uint64 `yaml:"interceptSlot" envconfig:"INDEXER_INTERCEPT_SLOT"` + Tld string `yaml:"tld" envconfig:"INDEXER_TLD"` + PolicyId string `yaml:"policyId" envconfig:"INDEXER_POLICY_ID"` + Verify bool `yaml:"verify" envconfig:"INDEXER_VERIFY"` } type StateConfig struct { @@ -105,10 +91,12 @@ var globalConfig = &Config{ }, Indexer: IndexerConfig{ Network: "preprod", + Verify: true, }, State: StateConfig{ Directory: "./.state", }, + Profile: "cardano-preprod-testing", } func Load(configFile string) (*Config, error) { @@ -130,19 +118,41 @@ func Load(configFile string) (*Config, error) { if err != nil { return nil, fmt.Errorf("error processing environment: %s", err) } - // Provide default script address for named network + // Check profile + profile, ok := Profiles[globalConfig.Profile] + if !ok { + return nil, fmt.Errorf("unknown profile: %s", globalConfig.Profile) + } + // Provide default network + if globalConfig.Indexer.Network != "" { + if profile.Network != "" { + globalConfig.Indexer.Network = profile.Network + } else { + return nil, fmt.Errorf("no built-in network name for specified profile, please provide one") + } + } + // Provide default script address from profile if globalConfig.Indexer.ScriptAddress == "" { - if scriptAddress, ok := networkScriptAddresses[globalConfig.Indexer.Network]; ok { - globalConfig.Indexer.ScriptAddress = scriptAddress + if profile.ScriptAddress != "" { + globalConfig.Indexer.ScriptAddress = profile.ScriptAddress } else { - return nil, fmt.Errorf("no built-in script address for specified network, please provide one") + return nil, fmt.Errorf("no built-in script address for specified profile, please provide one") } } - // Provide default intercept point for named network + // Provide default intercept point from profile if globalConfig.Indexer.InterceptSlot == 0 || globalConfig.Indexer.InterceptHash == "" { - if interceptPoint, ok := networkInterceptPoints[globalConfig.Indexer.Network]; ok { - globalConfig.Indexer.InterceptHash = interceptPoint.Hash - globalConfig.Indexer.InterceptSlot = interceptPoint.Slot + if profile.InterceptHash != "" && profile.InterceptSlot > 0 { + globalConfig.Indexer.InterceptHash = profile.InterceptHash + globalConfig.Indexer.InterceptSlot = profile.InterceptSlot + } + } + // Provide default TLD and Policy ID from profile + if globalConfig.Indexer.Tld == "" || globalConfig.Indexer.PolicyId == "" { + if profile.Tld != "" && profile.PolicyId != "" { + globalConfig.Indexer.Tld = profile.Tld + globalConfig.Indexer.PolicyId = profile.PolicyId + } else { + return nil, fmt.Errorf("no built-in TLD and/or policy ID for specified profile, please provide one") } } return globalConfig, nil diff --git a/internal/config/profile.go b/internal/config/profile.go new file mode 100644 index 0000000..5a84ff7 --- /dev/null +++ b/internal/config/profile.go @@ -0,0 +1,29 @@ +// Copyright 2023 Blink Labs Software +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +package config + +type Profile struct { + Network string // Cardano network name + Tld string // Top-level domain + PolicyId string // Verification asset policy ID + ScriptAddress string // Address to follow + InterceptSlot uint64 // Chain-sync initial intercept slot + InterceptHash string // Chain-sync initial intercept hash +} + +var Profiles = map[string]Profile{ + // This (default) profile corresponds to the values specified in: + // https://github.com/blinklabs-io/cardano-dns/blob/main/README.md + "cardano-preprod-testing": Profile{ + Network: "preprod", + Tld: "cardano", + PolicyId: "6af60c2a7a06551ef09b3810a41d086b26ca26f926d22e462103194d", + ScriptAddress: "addr_test1vr75xezmpxastymx985l3gamuxrwqdwcfrcnjlygs55aynsqu3edq", + InterceptSlot: 50844079, + InterceptHash: "81325118471fddb00a20327572b371aee7cce13b846a18500d011b9cefd2a34c", + }, +} diff --git a/internal/indexer/indexer.go b/internal/indexer/indexer.go index 5e55484..ad77cf9 100644 --- a/internal/indexer/indexer.go +++ b/internal/indexer/indexer.go @@ -153,6 +153,7 @@ func (i *Indexer) Start() error { } func (i *Indexer) handleEvent(evt event.Event) error { + cfg := config.GetConfig() logger := logging.GetLogger() eventTx := evt.Payload.(input_chainsync.TransactionEvent) eventCtx := evt.Context.(input_chainsync.TransactionContext) @@ -169,17 +170,82 @@ func (i *Indexer) handleEvent(evt event.Event) error { // Stop processing TX output if we can't parse the datum continue } - domainName := string(dnsDomain.Origin) - // Convert to canonical form for consistency - domainName = dns.CanonicalName(domainName) + origin := string(dnsDomain.Origin) + // Convert origin to canonical form for consistency + // This mostly means adding a trailing period if it doesn't have one + domainName := dns.CanonicalName(origin) + // We want an empty value for the TLD root for convenience + if domainName == `.` { + domainName = `` + } + // Append TLD + domainName = dns.CanonicalName( + domainName + cfg.Indexer.Tld, + ) + if cfg.Indexer.Verify { + // Look for asset matching domain origin and TLD policy ID + if txOutput.Assets() == nil { + logger.Warnf( + "ignoring datum for domain %q with no matching asset", + domainName, + ) + continue + } + foundAsset := false + for _, policyId := range txOutput.Assets().Policies() { + for _, assetName := range txOutput.Assets().Assets(policyId) { + if policyId.String() == cfg.Indexer.PolicyId { + if string(assetName) == string(origin) { + foundAsset = true + } else { + logger.Warnf( + "ignoring datum for domain %q with no matching asset", + domainName, + ) + } + } else { + logger.Warnf( + "ignoring datum for domain %q with no matching asset", + domainName, + ) + } + } + } + if !foundAsset { + continue + } + // Make sure all records are for specified origin domain + badRecordName := false + for _, record := range dnsDomain.Records { + recordName := dns.CanonicalName( + string(record.Lhs), + ) + if !strings.HasSuffix(recordName, domainName) { + logger.Warnf( + "ignoring datum with record %q outside of origin domain (%s)", + recordName, + domainName, + ) + badRecordName = true + break + } + } + if badRecordName { + continue + } + } nameServers := map[string]string{} for _, record := range dnsDomain.Records { + recordName := strings.Trim( + string(record.Lhs), + `.`, + ) // NOTE: we're losing information here, but we need to revamp the storage // format before we can use it. We're also making the assumption that all // records are for nameservers switch strings.ToUpper(string(record.Type)) { case "A", "AAAA": - nameServers[string(record.Lhs)] = string(record.Rhs) + nameServers[recordName] = string(record.Rhs) default: continue }