update deps; restructure
This commit is contained in:
parent
a6ae236e89
commit
797829a627
283 changed files with 22255 additions and 7999 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,4 +1,3 @@
|
||||||
/local.db
|
|
||||||
/local.db-journal
|
|
||||||
/cover.out
|
/cover.out
|
||||||
/e2e/main.go
|
/.env
|
||||||
|
/local.db
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ linters:
|
||||||
- bidichk
|
- bidichk
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- containedctx
|
- containedctx
|
||||||
|
- copyloopvar
|
||||||
- decorder
|
- decorder
|
||||||
- dogsled
|
- dogsled
|
||||||
- dupl
|
- dupl
|
||||||
|
|
@ -86,7 +87,6 @@ linters:
|
||||||
- errname
|
- errname
|
||||||
- errorlint
|
- errorlint
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- exportloopref
|
|
||||||
- forcetypeassert
|
- forcetypeassert
|
||||||
- gocognit
|
- gocognit
|
||||||
- gocritic
|
- gocritic
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ builds:
|
||||||
- -extldflags "-static"
|
- -extldflags "-static"
|
||||||
flags:
|
flags:
|
||||||
- -tags=timetzdata,goolm
|
- -tags=timetzdata,goolm
|
||||||
main: ./cmd/
|
main: ./cmd/postmoogle
|
||||||
goos:
|
goos:
|
||||||
- linux
|
- linux
|
||||||
- windows
|
- windows
|
||||||
|
|
|
||||||
47
go.mod
47
go.mod
|
|
@ -1,8 +1,8 @@
|
||||||
module github.com/etkecc/postmoogle
|
module github.com/etkecc/postmoogle
|
||||||
|
|
||||||
go 1.22
|
go 1.22.0
|
||||||
|
|
||||||
toolchain go1.23.0
|
toolchain go1.23.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/archdx/zerolog-sentry v1.8.4
|
github.com/archdx/zerolog-sentry v1.8.4
|
||||||
|
|
@ -12,15 +12,15 @@ require (
|
||||||
github.com/etkecc/go-env v1.2.1
|
github.com/etkecc/go-env v1.2.1
|
||||||
github.com/etkecc/go-fswatcher v1.0.1
|
github.com/etkecc/go-fswatcher v1.0.1
|
||||||
github.com/etkecc/go-healthchecks/v2 v2.2.1
|
github.com/etkecc/go-healthchecks/v2 v2.2.1
|
||||||
github.com/etkecc/go-linkpearl v0.0.0-20240820090551-8c5298047259
|
github.com/etkecc/go-linkpearl v0.0.0-20240916112808-1ff87355b2b3
|
||||||
github.com/etkecc/go-mxidwc v1.0.1
|
github.com/etkecc/go-mxidwc v1.0.1
|
||||||
github.com/etkecc/go-psd v0.0.0-20240820090455-a55658424f56
|
github.com/etkecc/go-psd v0.0.0-20241014083754-1bc4ec777ba8
|
||||||
github.com/etkecc/go-secgen v1.2.1
|
github.com/etkecc/go-secgen v1.3.0
|
||||||
github.com/etkecc/go-validator/v2 v2.2.2
|
github.com/etkecc/go-validator/v2 v2.2.4
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/gabriel-vasile/mimetype v1.4.5
|
github.com/gabriel-vasile/mimetype v1.4.6
|
||||||
github.com/getsentry/sentry-go v0.28.1
|
github.com/getsentry/sentry-go v0.29.1
|
||||||
github.com/jhillyerd/enmime v1.2.0
|
github.com/jhillyerd/enmime v1.3.0
|
||||||
github.com/kvannotten/mailstrip v0.0.0-20200711213611-0002f5c0467e
|
github.com/kvannotten/mailstrip v0.0.0-20200711213611-0002f5c0467e
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/mcnijman/go-emailaddress v1.1.1
|
github.com/mcnijman/go-emailaddress v1.1.1
|
||||||
|
|
@ -28,20 +28,21 @@ require (
|
||||||
github.com/raja/argon2pw v1.0.2-0.20210910183755-a391af63bd39
|
github.com/raja/argon2pw v1.0.2-0.20210910183755-a391af63bd39
|
||||||
github.com/rs/zerolog v1.33.0
|
github.com/rs/zerolog v1.33.0
|
||||||
github.com/swaggo/swag v1.16.3
|
github.com/swaggo/swag v1.16.3
|
||||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
|
||||||
maunium.net/go/mautrix v0.20.0
|
maunium.net/go/mautrix v0.21.0
|
||||||
modernc.org/sqlite v1.32.0
|
modernc.org/sqlite v1.33.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
blitiri.com.ar/go/spf v1.5.1 // indirect
|
blitiri.com.ar/go/spf v1.5.1 // indirect
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
github.com/buger/jsonparser v1.1.1 // indirect
|
github.com/buger/jsonparser v1.1.1 // indirect
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/etkecc/go-trysmtp v1.1.4 // indirect
|
github.com/etkecc/go-trysmtp v1.1.5 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||||
github.com/go-openapi/spec v0.20.4 // indirect
|
github.com/go-openapi/spec v0.20.4 // indirect
|
||||||
|
|
@ -63,20 +64,20 @@ require (
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
github.com/tidwall/gjson v1.17.3 // indirect
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tidwall/sjson v1.2.5 // indirect
|
github.com/tidwall/sjson v1.2.5 // indirect
|
||||||
github.com/yuin/goldmark v1.7.4 // indirect
|
github.com/yuin/goldmark v1.7.6 // indirect
|
||||||
go.mau.fi/util v0.7.0 // indirect
|
go.mau.fi/util v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.26.0 // indirect
|
golang.org/x/crypto v0.28.0 // indirect
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.30.0 // indirect
|
||||||
golang.org/x/sys v0.24.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.19.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.26.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a // indirect
|
modernc.org/gc/v3 v3.0.0-20241004144649-1aea3fae8852 // indirect
|
||||||
modernc.org/libc v1.59.9 // indirect
|
modernc.org/libc v1.61.0 // indirect
|
||||||
modernc.org/mathutil v1.6.0 // indirect
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
modernc.org/memory v1.8.0 // indirect
|
modernc.org/memory v1.8.0 // indirect
|
||||||
modernc.org/strutil v1.2.0 // indirect
|
modernc.org/strutil v1.2.0 // indirect
|
||||||
|
|
|
||||||
102
go.sum
102
go.sum
|
|
@ -1,5 +1,7 @@
|
||||||
blitiri.com.ar/go/spf v1.5.1 h1:CWUEasc44OrANJD8CzceRnRn1Jv0LttY68cYym2/pbE=
|
blitiri.com.ar/go/spf v1.5.1 h1:CWUEasc44OrANJD8CzceRnRn1Jv0LttY68cYym2/pbE=
|
||||||
blitiri.com.ar/go/spf v1.5.1/go.mod h1:E71N92TfL4+Yyd5lpKuE9CAF2pd4JrUq1xQfkTxoNdk=
|
blitiri.com.ar/go/spf v1.5.1/go.mod h1:E71N92TfL4+Yyd5lpKuE9CAF2pd4JrUq1xQfkTxoNdk=
|
||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||||
|
|
@ -34,24 +36,24 @@ github.com/etkecc/go-fswatcher v1.0.1 h1:n9hqtjzTS3ETb9hcZe1EqYA1lkkhlzZlztu3hXw
|
||||||
github.com/etkecc/go-fswatcher v1.0.1/go.mod h1:O5TODJ9z6Qb7X+snqHbB+F0Pah6G497Wdg0SFE/UYpE=
|
github.com/etkecc/go-fswatcher v1.0.1/go.mod h1:O5TODJ9z6Qb7X+snqHbB+F0Pah6G497Wdg0SFE/UYpE=
|
||||||
github.com/etkecc/go-healthchecks/v2 v2.2.1 h1:veGW/EoFuF4mB9ylHhCB4C98MY2kjl3++wZ7g6KRSXg=
|
github.com/etkecc/go-healthchecks/v2 v2.2.1 h1:veGW/EoFuF4mB9ylHhCB4C98MY2kjl3++wZ7g6KRSXg=
|
||||||
github.com/etkecc/go-healthchecks/v2 v2.2.1/go.mod h1:IowWGN4F6By6z0eh63+639OscylgtdvT9ITjfN6hnZA=
|
github.com/etkecc/go-healthchecks/v2 v2.2.1/go.mod h1:IowWGN4F6By6z0eh63+639OscylgtdvT9ITjfN6hnZA=
|
||||||
github.com/etkecc/go-linkpearl v0.0.0-20240820090551-8c5298047259 h1:dPTbAGkvxpMeCW3umXW08x+V9cWZTrxJVB8Ci5/Xxww=
|
github.com/etkecc/go-linkpearl v0.0.0-20240916112808-1ff87355b2b3 h1:Mkf7lWP0lf5Hv8g4x+p1IJ64kfQYIX85z8dKDjsKeuw=
|
||||||
github.com/etkecc/go-linkpearl v0.0.0-20240820090551-8c5298047259/go.mod h1:1t/feey8th1xSrJaa3CqYzrmc4yUUv/YPv7djgI7aQY=
|
github.com/etkecc/go-linkpearl v0.0.0-20240916112808-1ff87355b2b3/go.mod h1:lmPUKcFUSGuJ2kwqL9Yc5gWsBKVGQr+smuDCX+BqMWY=
|
||||||
github.com/etkecc/go-mxidwc v1.0.1 h1:t4Kq3FxSlQjt1i7RpzE5q3cOWjJ0vrTzzGZRSpgh8mg=
|
github.com/etkecc/go-mxidwc v1.0.1 h1:t4Kq3FxSlQjt1i7RpzE5q3cOWjJ0vrTzzGZRSpgh8mg=
|
||||||
github.com/etkecc/go-mxidwc v1.0.1/go.mod h1:WFlntcH4mdual/gNi6X7a6rSJERNuLjdrwM3K/tucQA=
|
github.com/etkecc/go-mxidwc v1.0.1/go.mod h1:WFlntcH4mdual/gNi6X7a6rSJERNuLjdrwM3K/tucQA=
|
||||||
github.com/etkecc/go-psd v0.0.0-20240820090455-a55658424f56 h1:WgHl5bTrf+3RqSrSXJiE4S2tkW+UKnMbWR4K+nWEh48=
|
github.com/etkecc/go-psd v0.0.0-20241014083754-1bc4ec777ba8 h1:ariQTBlHHe71O507IZ97QSHFrk0Eo2vlMm1skJ97Y7Q=
|
||||||
github.com/etkecc/go-psd v0.0.0-20240820090455-a55658424f56/go.mod h1:D+viZZ4CaSlJLz2E99eoLkO8Xvb6Q5/1jEgQ3tbVY0U=
|
github.com/etkecc/go-psd v0.0.0-20241014083754-1bc4ec777ba8/go.mod h1:x4ORuml+JdRsska0sXHbpSQAqvQyqDLjXydP5Ax5wBg=
|
||||||
github.com/etkecc/go-secgen v1.2.1 h1:z0z9TFsjH+FEhvB7AJASTdp3v/fsgFaHP+rrB/cMKWg=
|
github.com/etkecc/go-secgen v1.3.0 h1:DfytmSQL7W0nL7E0kmgDCrorU7V3e2bT5XBgrIisbbs=
|
||||||
github.com/etkecc/go-secgen v1.2.1/go.mod h1:luevmnqMsxEb0oBUGaxht8lVjgPWHj2qESSTkf+ID5k=
|
github.com/etkecc/go-secgen v1.3.0/go.mod h1:6dkfdOtmtVxkj1hIJM6U6yA7frSNpr1H5brz5t18Y3I=
|
||||||
github.com/etkecc/go-trysmtp v1.1.4 h1:qI1DezcjV9bFnPpnDGFguldyb6fD5GdlllsFPwCySt4=
|
github.com/etkecc/go-trysmtp v1.1.5 h1:MQ4l4bE9nWUqRKoJOalGHGLkb/hRmzbcBMlClufEOng=
|
||||||
github.com/etkecc/go-trysmtp v1.1.4/go.mod h1:J4zQu+kgM37xQY148wUz0Dm6y+YhtzMghAv/AaXt0sQ=
|
github.com/etkecc/go-trysmtp v1.1.5/go.mod h1:J4zQu+kgM37xQY148wUz0Dm6y+YhtzMghAv/AaXt0sQ=
|
||||||
github.com/etkecc/go-validator/v2 v2.2.2 h1:W3f7ktYJRpKh+qF3OlMWo1EmTAGDDCIdKFQQy1VqQWA=
|
github.com/etkecc/go-validator/v2 v2.2.4 h1:E4sE4FpYPVP6VRvnndni+8qUXbeSuHxkniFsi6uCRFQ=
|
||||||
github.com/etkecc/go-validator/v2 v2.2.2/go.mod h1:ZbgSUczvrg15hps+eTw8GmCGjiepgiaHyv7TM9W+Oes=
|
github.com/etkecc/go-validator/v2 v2.2.4/go.mod h1:5VX2VICgMALoFBiGc02p/6RjQ8ifRxZ0KOuLAH5fTe0=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||||
github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k=
|
github.com/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA=
|
||||||
github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg=
|
github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
|
@ -79,8 +81,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||||
github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslHk=
|
github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw=
|
||||||
github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I=
|
github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
|
@ -106,8 +108,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/mcnijman/go-emailaddress v1.1.1 h1:AGhgVDG3tCDaL0/Vc6erlPQjDuDN3dAT7rRdgFtetr0=
|
github.com/mcnijman/go-emailaddress v1.1.1 h1:AGhgVDG3tCDaL0/Vc6erlPQjDuDN3dAT7rRdgFtetr0=
|
||||||
github.com/mcnijman/go-emailaddress v1.1.1/go.mod h1:5whZrhS8Xp5LxO8zOD35BC+b76kROtsh+dPomeRt/II=
|
github.com/mcnijman/go-emailaddress v1.1.1/go.mod h1:5whZrhS8Xp5LxO8zOD35BC+b76kROtsh+dPomeRt/II=
|
||||||
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a h1:eU8j/ClY2Ty3qdHnn0TyW3ivFoPC/0F1gQZz8yTxbbE=
|
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a h1:eU8j/ClY2Ty3qdHnn0TyW3ivFoPC/0F1gQZz8yTxbbE=
|
||||||
|
|
@ -148,8 +150,8 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
|
||||||
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
|
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||||
github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
|
@ -157,20 +159,20 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||||
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
github.com/yuin/goldmark v1.7.6 h1:cZgJxVh5mL5cu8KOnwxvFJy5TFB0BHUskZZyq7TYbDg=
|
||||||
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.6/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
go.mau.fi/util v0.7.0 h1:l31z+ivrSQw+cv/9eFebEqtQW2zhxivGypn+JT0h/ws=
|
go.mau.fi/util v0.8.0 h1:MiSny8jgQq4XtCLAT64gDJhZVhqiDeMVIEBDFVw+M0g=
|
||||||
go.mau.fi/util v0.7.0/go.mod h1:bWYreIoTULL/UiRbZdfddPh7uWDFW5yX4YCv5FB0eE0=
|
go.mau.fi/util v0.8.0/go.mod h1:1Ixb8HWoVbl3rT6nAX6nV4iMkzn7KU/KXwE0Rn5RmsQ=
|
||||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
@ -178,18 +180,18 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
|
@ -201,20 +203,20 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
maunium.net/go/mautrix v0.20.0 h1:bzQnVQR+LvQxV1YlAr7BSWCS8AWa0Ov0lyPhbbChM0o=
|
maunium.net/go/mautrix v0.21.0 h1:Z6nVu+clkJgj6ANwFYQQ1BtYeVXZPZ9lRgwuFN57gOY=
|
||||||
maunium.net/go/mautrix v0.20.0/go.mod h1:V725r8w7oddsS7CxnmTAp634A4nwJCFY7J3jiTMUz2c=
|
maunium.net/go/mautrix v0.21.0/go.mod h1:qm9oDhcHxF/Xby5RUuONIGpXw1SXXqLZj/GgvMxJxu0=
|
||||||
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
||||||
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||||
modernc.org/ccgo/v4 v4.20.7 h1:skrinQsjxWfvj6nbC3ztZPJy+NuwmB3hV9zX/pthNYQ=
|
modernc.org/ccgo/v4 v4.21.0 h1:kKPI3dF7RIag8YcToh5ZwDcVMIv6VGa0ED5cvh0LMW4=
|
||||||
modernc.org/ccgo/v4 v4.20.7/go.mod h1:UOkI3JSG2zT4E2ioHlncSOZsXbuDCZLvPi3uMlZT5GY=
|
modernc.org/ccgo/v4 v4.21.0/go.mod h1:h6kt6H/A2+ew/3MW/p6KEoQmrq/i3pr0J/SiwiaF/g0=
|
||||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||||
modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M=
|
modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M=
|
||||||
modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||||
modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a h1:CfbpOLEo2IwNzJdMvE8aiRbPMxoTpgAJeyePh0SmO8M=
|
modernc.org/gc/v3 v3.0.0-20241004144649-1aea3fae8852 h1:IYXPPTTjjoSHvUClZIYexDiO7g+4x+XveKT4gCIAwiY=
|
||||||
modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
modernc.org/gc/v3 v3.0.0-20241004144649-1aea3fae8852/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||||
modernc.org/libc v1.59.9 h1:k+nNDDakwipimgmJ1D9H466LhFeSkaPPycAs1OZiDmY=
|
modernc.org/libc v1.61.0 h1:eGFcvWpqlnoGwzZeZe3PWJkkKbM/3SUGyk1DVZQ0TpE=
|
||||||
modernc.org/libc v1.59.9/go.mod h1:EY/egGEU7Ju66eU6SBqCNYaFUDuc4npICkMWnU5EE3A=
|
modernc.org/libc v1.61.0/go.mod h1:DvxVX89wtGTu+r72MLGhygpfi3aUGgZRdAYGCAVVud0=
|
||||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||||
|
|
@ -223,8 +225,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||||
modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s=
|
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
|
||||||
modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA=
|
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
||||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
|
|
|
||||||
15
justfile
15
justfile
|
|
@ -4,7 +4,7 @@ default:
|
||||||
|
|
||||||
# update go deps
|
# update go deps
|
||||||
update *flags:
|
update *flags:
|
||||||
go get {{ flags }} ./cmd
|
go get {{ flags }} ./cmd/postmoogle
|
||||||
go mod tidy
|
go mod tidy
|
||||||
go mod vendor
|
go mod vendor
|
||||||
|
|
||||||
|
|
@ -22,11 +22,11 @@ mocks:
|
||||||
|
|
||||||
# generate swagger docks
|
# generate swagger docks
|
||||||
swagger:
|
swagger:
|
||||||
@swag init --dir ./cmd,./
|
@swag init --parseDependency --dir ./cmd/postmoogle,./
|
||||||
|
|
||||||
# automatically fix swagger issues
|
# automatically fix swagger issues
|
||||||
swaggerfix: && swagger
|
swaggerfix: && swagger
|
||||||
@swag fmt --dir ./cmd,./
|
@swag fmt --dir ./cmd/postmoogle,./
|
||||||
|
|
||||||
# run unit tests
|
# run unit tests
|
||||||
test packages="./...":
|
test packages="./...":
|
||||||
|
|
@ -35,9 +35,12 @@ test packages="./...":
|
||||||
-@rm -f cover.out
|
-@rm -f cover.out
|
||||||
|
|
||||||
# run app
|
# run app
|
||||||
run:
|
run *flags:
|
||||||
@go run ./cmd
|
@go run ./cmd/postmoogle {{ flags }}
|
||||||
|
|
||||||
|
install:
|
||||||
|
@CGO_ENABLED=0 go install -ldflags '-extldflags "-static"' -tags timetzdata,goolm -v ./cmd/postmoogle
|
||||||
|
|
||||||
# build app
|
# build app
|
||||||
build:
|
build:
|
||||||
CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -tags timetzdata,goolm -v -o postmoogle ./cmd
|
@CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -tags timetzdata,goolm -v ./cmd/postmoogle
|
||||||
|
|
|
||||||
27
vendor/filippo.io/edwards25519/LICENSE
generated
vendored
Normal file
27
vendor/filippo.io/edwards25519/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
14
vendor/filippo.io/edwards25519/README.md
generated
vendored
Normal file
14
vendor/filippo.io/edwards25519/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# filippo.io/edwards25519
|
||||||
|
|
||||||
|
```
|
||||||
|
import "filippo.io/edwards25519"
|
||||||
|
```
|
||||||
|
|
||||||
|
This library implements the edwards25519 elliptic curve, exposing the necessary APIs to build a wide array of higher-level primitives.
|
||||||
|
Read the docs at [pkg.go.dev/filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519).
|
||||||
|
|
||||||
|
The code is originally derived from Adam Langley's internal implementation in the Go standard library, and includes George Tankersley's [performance improvements](https://golang.org/cl/71950). It was then further developed by Henry de Valence for use in ristretto255, and was finally [merged back into the Go standard library](https://golang.org/cl/276272) as of Go 1.17. It now tracks the upstream codebase and extends it with additional functionality.
|
||||||
|
|
||||||
|
Most users don't need this package, and should instead use `crypto/ed25519` for signatures, `golang.org/x/crypto/curve25519` for Diffie-Hellman, or `github.com/gtank/ristretto255` for prime order group logic. However, for anyone currently using a fork of `crypto/internal/edwards25519`/`crypto/ed25519/internal/edwards25519` or `github.com/agl/edwards25519`, this package should be a safer, faster, and more powerful alternative.
|
||||||
|
|
||||||
|
Since this package is meant to curb proliferation of edwards25519 implementations in the Go ecosystem, it welcomes requests for new APIs or reviewable performance improvements.
|
||||||
20
vendor/filippo.io/edwards25519/doc.go
generated
vendored
Normal file
20
vendor/filippo.io/edwards25519/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package edwards25519 implements group logic for the twisted Edwards curve
|
||||||
|
//
|
||||||
|
// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2
|
||||||
|
//
|
||||||
|
// This is better known as the Edwards curve equivalent to Curve25519, and is
|
||||||
|
// the curve used by the Ed25519 signature scheme.
|
||||||
|
//
|
||||||
|
// Most users don't need this package, and should instead use crypto/ed25519 for
|
||||||
|
// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or
|
||||||
|
// github.com/gtank/ristretto255 for prime order group logic.
|
||||||
|
//
|
||||||
|
// However, developers who do need to interact with low-level edwards25519
|
||||||
|
// operations can use this package, which is an extended version of
|
||||||
|
// crypto/internal/edwards25519 from the standard library repackaged as
|
||||||
|
// an importable module.
|
||||||
|
package edwards25519
|
||||||
427
vendor/filippo.io/edwards25519/edwards25519.go
generated
vendored
Normal file
427
vendor/filippo.io/edwards25519/edwards25519.go
generated
vendored
Normal file
|
|
@ -0,0 +1,427 @@
|
||||||
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package edwards25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"filippo.io/edwards25519/field"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Point types.
|
||||||
|
|
||||||
|
type projP1xP1 struct {
|
||||||
|
X, Y, Z, T field.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
type projP2 struct {
|
||||||
|
X, Y, Z field.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point represents a point on the edwards25519 curve.
|
||||||
|
//
|
||||||
|
// This type works similarly to math/big.Int, and all arguments and receivers
|
||||||
|
// are allowed to alias.
|
||||||
|
//
|
||||||
|
// The zero value is NOT valid, and it may be used only as a receiver.
|
||||||
|
type Point struct {
|
||||||
|
// Make the type not comparable (i.e. used with == or as a map key), as
|
||||||
|
// equivalent points can be represented by different Go values.
|
||||||
|
_ incomparable
|
||||||
|
|
||||||
|
// The point is internally represented in extended coordinates (X, Y, Z, T)
|
||||||
|
// where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522.
|
||||||
|
x, y, z, t field.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
type incomparable [0]func()
|
||||||
|
|
||||||
|
func checkInitialized(points ...*Point) {
|
||||||
|
for _, p := range points {
|
||||||
|
if p.x == (field.Element{}) && p.y == (field.Element{}) {
|
||||||
|
panic("edwards25519: use of uninitialized Point")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type projCached struct {
|
||||||
|
YplusX, YminusX, Z, T2d field.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
type affineCached struct {
|
||||||
|
YplusX, YminusX, T2d field.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructors.
|
||||||
|
|
||||||
|
func (v *projP2) Zero() *projP2 {
|
||||||
|
v.X.Zero()
|
||||||
|
v.Y.One()
|
||||||
|
v.Z.One()
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// identity is the point at infinity.
|
||||||
|
var identity, _ = new(Point).SetBytes([]byte{
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
|
||||||
|
|
||||||
|
// NewIdentityPoint returns a new Point set to the identity.
|
||||||
|
func NewIdentityPoint() *Point {
|
||||||
|
return new(Point).Set(identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generator is the canonical curve basepoint. See TestGenerator for the
|
||||||
|
// correspondence of this encoding with the values in RFC 8032.
|
||||||
|
var generator, _ = new(Point).SetBytes([]byte{
|
||||||
|
0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})
|
||||||
|
|
||||||
|
// NewGeneratorPoint returns a new Point set to the canonical generator.
|
||||||
|
func NewGeneratorPoint() *Point {
|
||||||
|
return new(Point).Set(generator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *projCached) Zero() *projCached {
|
||||||
|
v.YplusX.One()
|
||||||
|
v.YminusX.One()
|
||||||
|
v.Z.One()
|
||||||
|
v.T2d.Zero()
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *affineCached) Zero() *affineCached {
|
||||||
|
v.YplusX.One()
|
||||||
|
v.YminusX.One()
|
||||||
|
v.T2d.Zero()
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignments.
|
||||||
|
|
||||||
|
// Set sets v = u, and returns v.
|
||||||
|
func (v *Point) Set(u *Point) *Point {
|
||||||
|
*v = *u
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encoding.
|
||||||
|
|
||||||
|
// Bytes returns the canonical 32-byte encoding of v, according to RFC 8032,
|
||||||
|
// Section 5.1.2.
|
||||||
|
func (v *Point) Bytes() []byte {
|
||||||
|
// This function is outlined to make the allocations inline in the caller
|
||||||
|
// rather than happen on the heap.
|
||||||
|
var buf [32]byte
|
||||||
|
return v.bytes(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Point) bytes(buf *[32]byte) []byte {
|
||||||
|
checkInitialized(v)
|
||||||
|
|
||||||
|
var zInv, x, y field.Element
|
||||||
|
zInv.Invert(&v.z) // zInv = 1 / Z
|
||||||
|
x.Multiply(&v.x, &zInv) // x = X / Z
|
||||||
|
y.Multiply(&v.y, &zInv) // y = Y / Z
|
||||||
|
|
||||||
|
out := copyFieldElement(buf, &y)
|
||||||
|
out[31] |= byte(x.IsNegative() << 7)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
var feOne = new(field.Element).One()
|
||||||
|
|
||||||
|
// SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not
|
||||||
|
// represent a valid point on the curve, SetBytes returns nil and an error and
|
||||||
|
// the receiver is unchanged. Otherwise, SetBytes returns v.
|
||||||
|
//
|
||||||
|
// Note that SetBytes accepts all non-canonical encodings of valid points.
|
||||||
|
// That is, it follows decoding rules that match most implementations in
|
||||||
|
// the ecosystem rather than RFC 8032.
|
||||||
|
func (v *Point) SetBytes(x []byte) (*Point, error) {
|
||||||
|
// Specifically, the non-canonical encodings that are accepted are
|
||||||
|
// 1) the ones where the field element is not reduced (see the
|
||||||
|
// (*field.Element).SetBytes docs) and
|
||||||
|
// 2) the ones where the x-coordinate is zero and the sign bit is set.
|
||||||
|
//
|
||||||
|
// Read more at https://hdevalence.ca/blog/2020-10-04-its-25519am,
|
||||||
|
// specifically the "Canonical A, R" section.
|
||||||
|
|
||||||
|
y, err := new(field.Element).SetBytes(x)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("edwards25519: invalid point encoding length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// -x² + y² = 1 + dx²y²
|
||||||
|
// x² + dx²y² = x²(dy² + 1) = y² - 1
|
||||||
|
// x² = (y² - 1) / (dy² + 1)
|
||||||
|
|
||||||
|
// u = y² - 1
|
||||||
|
y2 := new(field.Element).Square(y)
|
||||||
|
u := new(field.Element).Subtract(y2, feOne)
|
||||||
|
|
||||||
|
// v = dy² + 1
|
||||||
|
vv := new(field.Element).Multiply(y2, d)
|
||||||
|
vv = vv.Add(vv, feOne)
|
||||||
|
|
||||||
|
// x = +√(u/v)
|
||||||
|
xx, wasSquare := new(field.Element).SqrtRatio(u, vv)
|
||||||
|
if wasSquare == 0 {
|
||||||
|
return nil, errors.New("edwards25519: invalid point encoding")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select the negative square root if the sign bit is set.
|
||||||
|
xxNeg := new(field.Element).Negate(xx)
|
||||||
|
xx = xx.Select(xxNeg, xx, int(x[31]>>7))
|
||||||
|
|
||||||
|
v.x.Set(xx)
|
||||||
|
v.y.Set(y)
|
||||||
|
v.z.One()
|
||||||
|
v.t.Multiply(xx, y) // xy = T / Z
|
||||||
|
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFieldElement(buf *[32]byte, v *field.Element) []byte {
|
||||||
|
copy(buf[:], v.Bytes())
|
||||||
|
return buf[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversions.
|
||||||
|
|
||||||
|
func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 {
|
||||||
|
v.X.Multiply(&p.X, &p.T)
|
||||||
|
v.Y.Multiply(&p.Y, &p.Z)
|
||||||
|
v.Z.Multiply(&p.Z, &p.T)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *projP2) FromP3(p *Point) *projP2 {
|
||||||
|
v.X.Set(&p.x)
|
||||||
|
v.Y.Set(&p.y)
|
||||||
|
v.Z.Set(&p.z)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Point) fromP1xP1(p *projP1xP1) *Point {
|
||||||
|
v.x.Multiply(&p.X, &p.T)
|
||||||
|
v.y.Multiply(&p.Y, &p.Z)
|
||||||
|
v.z.Multiply(&p.Z, &p.T)
|
||||||
|
v.t.Multiply(&p.X, &p.Y)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Point) fromP2(p *projP2) *Point {
|
||||||
|
v.x.Multiply(&p.X, &p.Z)
|
||||||
|
v.y.Multiply(&p.Y, &p.Z)
|
||||||
|
v.z.Square(&p.Z)
|
||||||
|
v.t.Multiply(&p.X, &p.Y)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// d is a constant in the curve equation.
|
||||||
|
var d, _ = new(field.Element).SetBytes([]byte{
|
||||||
|
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
|
||||||
|
0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
|
||||||
|
0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
|
||||||
|
0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52})
|
||||||
|
var d2 = new(field.Element).Add(d, d)
|
||||||
|
|
||||||
|
func (v *projCached) FromP3(p *Point) *projCached {
|
||||||
|
v.YplusX.Add(&p.y, &p.x)
|
||||||
|
v.YminusX.Subtract(&p.y, &p.x)
|
||||||
|
v.Z.Set(&p.z)
|
||||||
|
v.T2d.Multiply(&p.t, d2)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *affineCached) FromP3(p *Point) *affineCached {
|
||||||
|
v.YplusX.Add(&p.y, &p.x)
|
||||||
|
v.YminusX.Subtract(&p.y, &p.x)
|
||||||
|
v.T2d.Multiply(&p.t, d2)
|
||||||
|
|
||||||
|
var invZ field.Element
|
||||||
|
invZ.Invert(&p.z)
|
||||||
|
v.YplusX.Multiply(&v.YplusX, &invZ)
|
||||||
|
v.YminusX.Multiply(&v.YminusX, &invZ)
|
||||||
|
v.T2d.Multiply(&v.T2d, &invZ)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// (Re)addition and subtraction.
|
||||||
|
|
||||||
|
// Add sets v = p + q, and returns v.
|
||||||
|
func (v *Point) Add(p, q *Point) *Point {
|
||||||
|
checkInitialized(p, q)
|
||||||
|
qCached := new(projCached).FromP3(q)
|
||||||
|
result := new(projP1xP1).Add(p, qCached)
|
||||||
|
return v.fromP1xP1(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtract sets v = p - q, and returns v.
|
||||||
|
func (v *Point) Subtract(p, q *Point) *Point {
|
||||||
|
checkInitialized(p, q)
|
||||||
|
qCached := new(projCached).FromP3(q)
|
||||||
|
result := new(projP1xP1).Sub(p, qCached)
|
||||||
|
return v.fromP1xP1(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 {
|
||||||
|
var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
|
||||||
|
|
||||||
|
YplusX.Add(&p.y, &p.x)
|
||||||
|
YminusX.Subtract(&p.y, &p.x)
|
||||||
|
|
||||||
|
PP.Multiply(&YplusX, &q.YplusX)
|
||||||
|
MM.Multiply(&YminusX, &q.YminusX)
|
||||||
|
TT2d.Multiply(&p.t, &q.T2d)
|
||||||
|
ZZ2.Multiply(&p.z, &q.Z)
|
||||||
|
|
||||||
|
ZZ2.Add(&ZZ2, &ZZ2)
|
||||||
|
|
||||||
|
v.X.Subtract(&PP, &MM)
|
||||||
|
v.Y.Add(&PP, &MM)
|
||||||
|
v.Z.Add(&ZZ2, &TT2d)
|
||||||
|
v.T.Subtract(&ZZ2, &TT2d)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 {
|
||||||
|
var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
|
||||||
|
|
||||||
|
YplusX.Add(&p.y, &p.x)
|
||||||
|
YminusX.Subtract(&p.y, &p.x)
|
||||||
|
|
||||||
|
PP.Multiply(&YplusX, &q.YminusX) // flipped sign
|
||||||
|
MM.Multiply(&YminusX, &q.YplusX) // flipped sign
|
||||||
|
TT2d.Multiply(&p.t, &q.T2d)
|
||||||
|
ZZ2.Multiply(&p.z, &q.Z)
|
||||||
|
|
||||||
|
ZZ2.Add(&ZZ2, &ZZ2)
|
||||||
|
|
||||||
|
v.X.Subtract(&PP, &MM)
|
||||||
|
v.Y.Add(&PP, &MM)
|
||||||
|
v.Z.Subtract(&ZZ2, &TT2d) // flipped sign
|
||||||
|
v.T.Add(&ZZ2, &TT2d) // flipped sign
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 {
|
||||||
|
var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
|
||||||
|
|
||||||
|
YplusX.Add(&p.y, &p.x)
|
||||||
|
YminusX.Subtract(&p.y, &p.x)
|
||||||
|
|
||||||
|
PP.Multiply(&YplusX, &q.YplusX)
|
||||||
|
MM.Multiply(&YminusX, &q.YminusX)
|
||||||
|
TT2d.Multiply(&p.t, &q.T2d)
|
||||||
|
|
||||||
|
Z2.Add(&p.z, &p.z)
|
||||||
|
|
||||||
|
v.X.Subtract(&PP, &MM)
|
||||||
|
v.Y.Add(&PP, &MM)
|
||||||
|
v.Z.Add(&Z2, &TT2d)
|
||||||
|
v.T.Subtract(&Z2, &TT2d)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 {
|
||||||
|
var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
|
||||||
|
|
||||||
|
YplusX.Add(&p.y, &p.x)
|
||||||
|
YminusX.Subtract(&p.y, &p.x)
|
||||||
|
|
||||||
|
PP.Multiply(&YplusX, &q.YminusX) // flipped sign
|
||||||
|
MM.Multiply(&YminusX, &q.YplusX) // flipped sign
|
||||||
|
TT2d.Multiply(&p.t, &q.T2d)
|
||||||
|
|
||||||
|
Z2.Add(&p.z, &p.z)
|
||||||
|
|
||||||
|
v.X.Subtract(&PP, &MM)
|
||||||
|
v.Y.Add(&PP, &MM)
|
||||||
|
v.Z.Subtract(&Z2, &TT2d) // flipped sign
|
||||||
|
v.T.Add(&Z2, &TT2d) // flipped sign
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doubling.
|
||||||
|
|
||||||
|
func (v *projP1xP1) Double(p *projP2) *projP1xP1 {
|
||||||
|
var XX, YY, ZZ2, XplusYsq field.Element
|
||||||
|
|
||||||
|
XX.Square(&p.X)
|
||||||
|
YY.Square(&p.Y)
|
||||||
|
ZZ2.Square(&p.Z)
|
||||||
|
ZZ2.Add(&ZZ2, &ZZ2)
|
||||||
|
XplusYsq.Add(&p.X, &p.Y)
|
||||||
|
XplusYsq.Square(&XplusYsq)
|
||||||
|
|
||||||
|
v.Y.Add(&YY, &XX)
|
||||||
|
v.Z.Subtract(&YY, &XX)
|
||||||
|
|
||||||
|
v.X.Subtract(&XplusYsq, &v.Y)
|
||||||
|
v.T.Subtract(&ZZ2, &v.Z)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negation.
|
||||||
|
|
||||||
|
// Negate sets v = -p, and returns v.
|
||||||
|
func (v *Point) Negate(p *Point) *Point {
|
||||||
|
checkInitialized(p)
|
||||||
|
v.x.Negate(&p.x)
|
||||||
|
v.y.Set(&p.y)
|
||||||
|
v.z.Set(&p.z)
|
||||||
|
v.t.Negate(&p.t)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns 1 if v is equivalent to u, and 0 otherwise.
|
||||||
|
func (v *Point) Equal(u *Point) int {
|
||||||
|
checkInitialized(v, u)
|
||||||
|
|
||||||
|
var t1, t2, t3, t4 field.Element
|
||||||
|
t1.Multiply(&v.x, &u.z)
|
||||||
|
t2.Multiply(&u.x, &v.z)
|
||||||
|
t3.Multiply(&v.y, &u.z)
|
||||||
|
t4.Multiply(&u.y, &v.z)
|
||||||
|
|
||||||
|
return t1.Equal(&t2) & t3.Equal(&t4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constant-time operations
|
||||||
|
|
||||||
|
// Select sets v to a if cond == 1 and to b if cond == 0.
|
||||||
|
func (v *projCached) Select(a, b *projCached, cond int) *projCached {
|
||||||
|
v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
|
||||||
|
v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
|
||||||
|
v.Z.Select(&a.Z, &b.Z, cond)
|
||||||
|
v.T2d.Select(&a.T2d, &b.T2d, cond)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select sets v to a if cond == 1 and to b if cond == 0.
|
||||||
|
func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached {
|
||||||
|
v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
|
||||||
|
v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
|
||||||
|
v.T2d.Select(&a.T2d, &b.T2d, cond)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
|
||||||
|
func (v *projCached) CondNeg(cond int) *projCached {
|
||||||
|
v.YplusX.Swap(&v.YminusX, cond)
|
||||||
|
v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
|
||||||
|
func (v *affineCached) CondNeg(cond int) *affineCached {
|
||||||
|
v.YplusX.Swap(&v.YminusX, cond)
|
||||||
|
v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
|
||||||
|
return v
|
||||||
|
}
|
||||||
349
vendor/filippo.io/edwards25519/extra.go
generated
vendored
Normal file
349
vendor/filippo.io/edwards25519/extra.go
generated
vendored
Normal file
|
|
@ -0,0 +1,349 @@
|
||||||
|
// Copyright (c) 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package edwards25519
|
||||||
|
|
||||||
|
// This file contains additional functionality that is not included in the
|
||||||
|
// upstream crypto/internal/edwards25519 package.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"filippo.io/edwards25519/field"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExtendedCoordinates returns v in extended coordinates (X:Y:Z:T) where
|
||||||
|
// x = X/Z, y = Y/Z, and xy = T/Z as in https://eprint.iacr.org/2008/522.
|
||||||
|
func (v *Point) ExtendedCoordinates() (X, Y, Z, T *field.Element) {
|
||||||
|
// This function is outlined to make the allocations inline in the caller
|
||||||
|
// rather than happen on the heap. Don't change the style without making
|
||||||
|
// sure it doesn't increase the inliner cost.
|
||||||
|
var e [4]field.Element
|
||||||
|
X, Y, Z, T = v.extendedCoordinates(&e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Point) extendedCoordinates(e *[4]field.Element) (X, Y, Z, T *field.Element) {
|
||||||
|
checkInitialized(v)
|
||||||
|
X = e[0].Set(&v.x)
|
||||||
|
Y = e[1].Set(&v.y)
|
||||||
|
Z = e[2].Set(&v.z)
|
||||||
|
T = e[3].Set(&v.t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExtendedCoordinates sets v = (X:Y:Z:T) in extended coordinates where
|
||||||
|
// x = X/Z, y = Y/Z, and xy = T/Z as in https://eprint.iacr.org/2008/522.
|
||||||
|
//
|
||||||
|
// If the coordinates are invalid or don't represent a valid point on the curve,
|
||||||
|
// SetExtendedCoordinates returns nil and an error and the receiver is
|
||||||
|
// unchanged. Otherwise, SetExtendedCoordinates returns v.
|
||||||
|
func (v *Point) SetExtendedCoordinates(X, Y, Z, T *field.Element) (*Point, error) {
|
||||||
|
if !isOnCurve(X, Y, Z, T) {
|
||||||
|
return nil, errors.New("edwards25519: invalid point coordinates")
|
||||||
|
}
|
||||||
|
v.x.Set(X)
|
||||||
|
v.y.Set(Y)
|
||||||
|
v.z.Set(Z)
|
||||||
|
v.t.Set(T)
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isOnCurve(X, Y, Z, T *field.Element) bool {
|
||||||
|
var lhs, rhs field.Element
|
||||||
|
XX := new(field.Element).Square(X)
|
||||||
|
YY := new(field.Element).Square(Y)
|
||||||
|
ZZ := new(field.Element).Square(Z)
|
||||||
|
TT := new(field.Element).Square(T)
|
||||||
|
// -x² + y² = 1 + dx²y²
|
||||||
|
// -(X/Z)² + (Y/Z)² = 1 + d(T/Z)²
|
||||||
|
// -X² + Y² = Z² + dT²
|
||||||
|
lhs.Subtract(YY, XX)
|
||||||
|
rhs.Multiply(d, TT).Add(&rhs, ZZ)
|
||||||
|
if lhs.Equal(&rhs) != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// xy = T/Z
|
||||||
|
// XY/Z² = T/Z
|
||||||
|
// XY = TZ
|
||||||
|
lhs.Multiply(X, Y)
|
||||||
|
rhs.Multiply(T, Z)
|
||||||
|
return lhs.Equal(&rhs) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesMontgomery converts v to a point on the birationally-equivalent
|
||||||
|
// Curve25519 Montgomery curve, and returns its canonical 32 bytes encoding
|
||||||
|
// according to RFC 7748.
|
||||||
|
//
|
||||||
|
// Note that BytesMontgomery only encodes the u-coordinate, so v and -v encode
|
||||||
|
// to the same value. If v is the identity point, BytesMontgomery returns 32
|
||||||
|
// zero bytes, analogously to the X25519 function.
|
||||||
|
//
|
||||||
|
// The lack of an inverse operation (such as SetMontgomeryBytes) is deliberate:
|
||||||
|
// while every valid edwards25519 point has a unique u-coordinate Montgomery
|
||||||
|
// encoding, X25519 accepts inputs on the quadratic twist, which don't correspond
|
||||||
|
// to any edwards25519 point, and every other X25519 input corresponds to two
|
||||||
|
// edwards25519 points.
|
||||||
|
func (v *Point) BytesMontgomery() []byte {
|
||||||
|
// This function is outlined to make the allocations inline in the caller
|
||||||
|
// rather than happen on the heap.
|
||||||
|
var buf [32]byte
|
||||||
|
return v.bytesMontgomery(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Point) bytesMontgomery(buf *[32]byte) []byte {
|
||||||
|
checkInitialized(v)
|
||||||
|
|
||||||
|
// RFC 7748, Section 4.1 provides the bilinear map to calculate the
|
||||||
|
// Montgomery u-coordinate
|
||||||
|
//
|
||||||
|
// u = (1 + y) / (1 - y)
|
||||||
|
//
|
||||||
|
// where y = Y / Z.
|
||||||
|
|
||||||
|
var y, recip, u field.Element
|
||||||
|
|
||||||
|
y.Multiply(&v.y, y.Invert(&v.z)) // y = Y / Z
|
||||||
|
recip.Invert(recip.Subtract(feOne, &y)) // r = 1/(1 - y)
|
||||||
|
u.Multiply(u.Add(feOne, &y), &recip) // u = (1 + y)*r
|
||||||
|
|
||||||
|
return copyFieldElement(buf, &u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultByCofactor sets v = 8 * p, and returns v.
|
||||||
|
func (v *Point) MultByCofactor(p *Point) *Point {
|
||||||
|
checkInitialized(p)
|
||||||
|
result := projP1xP1{}
|
||||||
|
pp := (&projP2{}).FromP3(p)
|
||||||
|
result.Double(pp)
|
||||||
|
pp.FromP1xP1(&result)
|
||||||
|
result.Double(pp)
|
||||||
|
pp.FromP1xP1(&result)
|
||||||
|
result.Double(pp)
|
||||||
|
return v.fromP1xP1(&result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given k > 0, set s = s**(2*i).
|
||||||
|
func (s *Scalar) pow2k(k int) {
|
||||||
|
for i := 0; i < k; i++ {
|
||||||
|
s.Multiply(s, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert sets s to the inverse of a nonzero scalar v, and returns s.
|
||||||
|
//
|
||||||
|
// If t is zero, Invert returns zero.
|
||||||
|
func (s *Scalar) Invert(t *Scalar) *Scalar {
|
||||||
|
// Uses a hardcoded sliding window of width 4.
|
||||||
|
var table [8]Scalar
|
||||||
|
var tt Scalar
|
||||||
|
tt.Multiply(t, t)
|
||||||
|
table[0] = *t
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
table[i+1].Multiply(&table[i], &tt)
|
||||||
|
}
|
||||||
|
// Now table = [t**1, t**3, t**5, t**7, t**9, t**11, t**13, t**15]
|
||||||
|
// so t**k = t[k/2] for odd k
|
||||||
|
|
||||||
|
// To compute the sliding window digits, use the following Sage script:
|
||||||
|
|
||||||
|
// sage: import itertools
|
||||||
|
// sage: def sliding_window(w,k):
|
||||||
|
// ....: digits = []
|
||||||
|
// ....: while k > 0:
|
||||||
|
// ....: if k % 2 == 1:
|
||||||
|
// ....: kmod = k % (2**w)
|
||||||
|
// ....: digits.append(kmod)
|
||||||
|
// ....: k = k - kmod
|
||||||
|
// ....: else:
|
||||||
|
// ....: digits.append(0)
|
||||||
|
// ....: k = k // 2
|
||||||
|
// ....: return digits
|
||||||
|
|
||||||
|
// Now we can compute s roughly as follows:
|
||||||
|
|
||||||
|
// sage: s = 1
|
||||||
|
// sage: for coeff in reversed(sliding_window(4,l-2)):
|
||||||
|
// ....: s = s*s
|
||||||
|
// ....: if coeff > 0 :
|
||||||
|
// ....: s = s*t**coeff
|
||||||
|
|
||||||
|
// This works on one bit at a time, with many runs of zeros.
|
||||||
|
// The digits can be collapsed into [(count, coeff)] as follows:
|
||||||
|
|
||||||
|
// sage: [(len(list(group)),d) for d,group in itertools.groupby(sliding_window(4,l-2))]
|
||||||
|
|
||||||
|
// Entries of the form (k, 0) turn into pow2k(k)
|
||||||
|
// Entries of the form (1, coeff) turn into a squaring and then a table lookup.
|
||||||
|
// We can fold the squaring into the previous pow2k(k) as pow2k(k+1).
|
||||||
|
|
||||||
|
*s = table[1/2]
|
||||||
|
s.pow2k(127 + 1)
|
||||||
|
s.Multiply(s, &table[1/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[9/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[11/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[13/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[15/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[7/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[15/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[5/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[1/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[15/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[15/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[7/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[3/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[11/2])
|
||||||
|
s.pow2k(5 + 1)
|
||||||
|
s.Multiply(s, &table[11/2])
|
||||||
|
s.pow2k(9 + 1)
|
||||||
|
s.Multiply(s, &table[9/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[3/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[3/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[3/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[9/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[7/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[3/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[13/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[7/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[9/2])
|
||||||
|
s.pow2k(3 + 1)
|
||||||
|
s.Multiply(s, &table[15/2])
|
||||||
|
s.pow2k(4 + 1)
|
||||||
|
s.Multiply(s, &table[11/2])
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiScalarMult sets v = sum(scalars[i] * points[i]), and returns v.
|
||||||
|
//
|
||||||
|
// Execution time depends only on the lengths of the two slices, which must match.
|
||||||
|
func (v *Point) MultiScalarMult(scalars []*Scalar, points []*Point) *Point {
|
||||||
|
if len(scalars) != len(points) {
|
||||||
|
panic("edwards25519: called MultiScalarMult with different size inputs")
|
||||||
|
}
|
||||||
|
checkInitialized(points...)
|
||||||
|
|
||||||
|
// Proceed as in the single-base case, but share doublings
|
||||||
|
// between each point in the multiscalar equation.
|
||||||
|
|
||||||
|
// Build lookup tables for each point
|
||||||
|
tables := make([]projLookupTable, len(points))
|
||||||
|
for i := range tables {
|
||||||
|
tables[i].FromP3(points[i])
|
||||||
|
}
|
||||||
|
// Compute signed radix-16 digits for each scalar
|
||||||
|
digits := make([][64]int8, len(scalars))
|
||||||
|
for i := range digits {
|
||||||
|
digits[i] = scalars[i].signedRadix16()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap first loop iteration to save computing 16*identity
|
||||||
|
multiple := &projCached{}
|
||||||
|
tmp1 := &projP1xP1{}
|
||||||
|
tmp2 := &projP2{}
|
||||||
|
// Lookup-and-add the appropriate multiple of each input point
|
||||||
|
for j := range tables {
|
||||||
|
tables[j].SelectInto(multiple, digits[j][63])
|
||||||
|
tmp1.Add(v, multiple) // tmp1 = v + x_(j,63)*Q in P1xP1 coords
|
||||||
|
v.fromP1xP1(tmp1) // update v
|
||||||
|
}
|
||||||
|
tmp2.FromP3(v) // set up tmp2 = v in P2 coords for next iteration
|
||||||
|
for i := 62; i >= 0; i-- {
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords
|
||||||
|
v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords
|
||||||
|
// Lookup-and-add the appropriate multiple of each input point
|
||||||
|
for j := range tables {
|
||||||
|
tables[j].SelectInto(multiple, digits[j][i])
|
||||||
|
tmp1.Add(v, multiple) // tmp1 = v + x_(j,i)*Q in P1xP1 coords
|
||||||
|
v.fromP1xP1(tmp1) // update v
|
||||||
|
}
|
||||||
|
tmp2.FromP3(v) // set up tmp2 = v in P2 coords for next iteration
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// VarTimeMultiScalarMult sets v = sum(scalars[i] * points[i]), and returns v.
|
||||||
|
//
|
||||||
|
// Execution time depends on the inputs.
|
||||||
|
func (v *Point) VarTimeMultiScalarMult(scalars []*Scalar, points []*Point) *Point {
|
||||||
|
if len(scalars) != len(points) {
|
||||||
|
panic("edwards25519: called VarTimeMultiScalarMult with different size inputs")
|
||||||
|
}
|
||||||
|
checkInitialized(points...)
|
||||||
|
|
||||||
|
// Generalize double-base NAF computation to arbitrary sizes.
|
||||||
|
// Here all the points are dynamic, so we only use the smaller
|
||||||
|
// tables.
|
||||||
|
|
||||||
|
// Build lookup tables for each point
|
||||||
|
tables := make([]nafLookupTable5, len(points))
|
||||||
|
for i := range tables {
|
||||||
|
tables[i].FromP3(points[i])
|
||||||
|
}
|
||||||
|
// Compute a NAF for each scalar
|
||||||
|
nafs := make([][256]int8, len(scalars))
|
||||||
|
for i := range nafs {
|
||||||
|
nafs[i] = scalars[i].nonAdjacentForm(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
multiple := &projCached{}
|
||||||
|
tmp1 := &projP1xP1{}
|
||||||
|
tmp2 := &projP2{}
|
||||||
|
tmp2.Zero()
|
||||||
|
|
||||||
|
// Move from high to low bits, doubling the accumulator
|
||||||
|
// at each iteration and checking whether there is a nonzero
|
||||||
|
// coefficient to look up a multiple of.
|
||||||
|
//
|
||||||
|
// Skip trying to find the first nonzero coefficent, because
|
||||||
|
// searching might be more work than a few extra doublings.
|
||||||
|
for i := 255; i >= 0; i-- {
|
||||||
|
tmp1.Double(tmp2)
|
||||||
|
|
||||||
|
for j := range nafs {
|
||||||
|
if nafs[j][i] > 0 {
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
tables[j].SelectInto(multiple, nafs[j][i])
|
||||||
|
tmp1.Add(v, multiple)
|
||||||
|
} else if nafs[j][i] < 0 {
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
tables[j].SelectInto(multiple, -nafs[j][i])
|
||||||
|
tmp1.Sub(v, multiple)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp2.FromP1xP1(tmp1)
|
||||||
|
}
|
||||||
|
|
||||||
|
v.fromP2(tmp2)
|
||||||
|
return v
|
||||||
|
}
|
||||||
420
vendor/filippo.io/edwards25519/field/fe.go
generated
vendored
Normal file
420
vendor/filippo.io/edwards25519/field/fe.go
generated
vendored
Normal file
|
|
@ -0,0 +1,420 @@
|
||||||
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package field implements fast arithmetic modulo 2^255-19.
|
||||||
|
package field
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Element represents an element of the field GF(2^255-19). Note that this
|
||||||
|
// is not a cryptographically secure group, and should only be used to interact
|
||||||
|
// with edwards25519.Point coordinates.
|
||||||
|
//
|
||||||
|
// This type works similarly to math/big.Int, and all arguments and receivers
|
||||||
|
// are allowed to alias.
|
||||||
|
//
|
||||||
|
// The zero value is a valid zero element.
|
||||||
|
type Element struct {
|
||||||
|
// An element t represents the integer
|
||||||
|
// t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204
|
||||||
|
//
|
||||||
|
// Between operations, all limbs are expected to be lower than 2^52.
|
||||||
|
l0 uint64
|
||||||
|
l1 uint64
|
||||||
|
l2 uint64
|
||||||
|
l3 uint64
|
||||||
|
l4 uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
const maskLow51Bits uint64 = (1 << 51) - 1
|
||||||
|
|
||||||
|
var feZero = &Element{0, 0, 0, 0, 0}
|
||||||
|
|
||||||
|
// Zero sets v = 0, and returns v.
|
||||||
|
func (v *Element) Zero() *Element {
|
||||||
|
*v = *feZero
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
var feOne = &Element{1, 0, 0, 0, 0}
|
||||||
|
|
||||||
|
// One sets v = 1, and returns v.
|
||||||
|
func (v *Element) One() *Element {
|
||||||
|
*v = *feOne
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// reduce reduces v modulo 2^255 - 19 and returns it.
|
||||||
|
func (v *Element) reduce() *Element {
|
||||||
|
v.carryPropagate()
|
||||||
|
|
||||||
|
// After the light reduction we now have a field element representation
|
||||||
|
// v < 2^255 + 2^13 * 19, but need v < 2^255 - 19.
|
||||||
|
|
||||||
|
// If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1,
|
||||||
|
// generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise.
|
||||||
|
c := (v.l0 + 19) >> 51
|
||||||
|
c = (v.l1 + c) >> 51
|
||||||
|
c = (v.l2 + c) >> 51
|
||||||
|
c = (v.l3 + c) >> 51
|
||||||
|
c = (v.l4 + c) >> 51
|
||||||
|
|
||||||
|
// If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's
|
||||||
|
// effectively applying the reduction identity to the carry.
|
||||||
|
v.l0 += 19 * c
|
||||||
|
|
||||||
|
v.l1 += v.l0 >> 51
|
||||||
|
v.l0 = v.l0 & maskLow51Bits
|
||||||
|
v.l2 += v.l1 >> 51
|
||||||
|
v.l1 = v.l1 & maskLow51Bits
|
||||||
|
v.l3 += v.l2 >> 51
|
||||||
|
v.l2 = v.l2 & maskLow51Bits
|
||||||
|
v.l4 += v.l3 >> 51
|
||||||
|
v.l3 = v.l3 & maskLow51Bits
|
||||||
|
// no additional carry
|
||||||
|
v.l4 = v.l4 & maskLow51Bits
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets v = a + b, and returns v.
|
||||||
|
func (v *Element) Add(a, b *Element) *Element {
|
||||||
|
v.l0 = a.l0 + b.l0
|
||||||
|
v.l1 = a.l1 + b.l1
|
||||||
|
v.l2 = a.l2 + b.l2
|
||||||
|
v.l3 = a.l3 + b.l3
|
||||||
|
v.l4 = a.l4 + b.l4
|
||||||
|
// Using the generic implementation here is actually faster than the
|
||||||
|
// assembly. Probably because the body of this function is so simple that
|
||||||
|
// the compiler can figure out better optimizations by inlining the carry
|
||||||
|
// propagation.
|
||||||
|
return v.carryPropagateGeneric()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtract sets v = a - b, and returns v.
|
||||||
|
func (v *Element) Subtract(a, b *Element) *Element {
|
||||||
|
// We first add 2 * p, to guarantee the subtraction won't underflow, and
|
||||||
|
// then subtract b (which can be up to 2^255 + 2^13 * 19).
|
||||||
|
v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0
|
||||||
|
v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1
|
||||||
|
v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2
|
||||||
|
v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3
|
||||||
|
v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4
|
||||||
|
return v.carryPropagate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negate sets v = -a, and returns v.
|
||||||
|
func (v *Element) Negate(a *Element) *Element {
|
||||||
|
return v.Subtract(feZero, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert sets v = 1/z mod p, and returns v.
|
||||||
|
//
|
||||||
|
// If z == 0, Invert returns v = 0.
|
||||||
|
func (v *Element) Invert(z *Element) *Element {
|
||||||
|
// Inversion is implemented as exponentiation with exponent p − 2. It uses the
|
||||||
|
// same sequence of 255 squarings and 11 multiplications as [Curve25519].
|
||||||
|
var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element
|
||||||
|
|
||||||
|
z2.Square(z) // 2
|
||||||
|
t.Square(&z2) // 4
|
||||||
|
t.Square(&t) // 8
|
||||||
|
z9.Multiply(&t, z) // 9
|
||||||
|
z11.Multiply(&z9, &z2) // 11
|
||||||
|
t.Square(&z11) // 22
|
||||||
|
z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0
|
||||||
|
|
||||||
|
t.Square(&z2_5_0) // 2^6 - 2^1
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
t.Square(&t) // 2^10 - 2^5
|
||||||
|
}
|
||||||
|
z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0
|
||||||
|
|
||||||
|
t.Square(&z2_10_0) // 2^11 - 2^1
|
||||||
|
for i := 0; i < 9; i++ {
|
||||||
|
t.Square(&t) // 2^20 - 2^10
|
||||||
|
}
|
||||||
|
z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0
|
||||||
|
|
||||||
|
t.Square(&z2_20_0) // 2^21 - 2^1
|
||||||
|
for i := 0; i < 19; i++ {
|
||||||
|
t.Square(&t) // 2^40 - 2^20
|
||||||
|
}
|
||||||
|
t.Multiply(&t, &z2_20_0) // 2^40 - 2^0
|
||||||
|
|
||||||
|
t.Square(&t) // 2^41 - 2^1
|
||||||
|
for i := 0; i < 9; i++ {
|
||||||
|
t.Square(&t) // 2^50 - 2^10
|
||||||
|
}
|
||||||
|
z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0
|
||||||
|
|
||||||
|
t.Square(&z2_50_0) // 2^51 - 2^1
|
||||||
|
for i := 0; i < 49; i++ {
|
||||||
|
t.Square(&t) // 2^100 - 2^50
|
||||||
|
}
|
||||||
|
z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0
|
||||||
|
|
||||||
|
t.Square(&z2_100_0) // 2^101 - 2^1
|
||||||
|
for i := 0; i < 99; i++ {
|
||||||
|
t.Square(&t) // 2^200 - 2^100
|
||||||
|
}
|
||||||
|
t.Multiply(&t, &z2_100_0) // 2^200 - 2^0
|
||||||
|
|
||||||
|
t.Square(&t) // 2^201 - 2^1
|
||||||
|
for i := 0; i < 49; i++ {
|
||||||
|
t.Square(&t) // 2^250 - 2^50
|
||||||
|
}
|
||||||
|
t.Multiply(&t, &z2_50_0) // 2^250 - 2^0
|
||||||
|
|
||||||
|
t.Square(&t) // 2^251 - 2^1
|
||||||
|
t.Square(&t) // 2^252 - 2^2
|
||||||
|
t.Square(&t) // 2^253 - 2^3
|
||||||
|
t.Square(&t) // 2^254 - 2^4
|
||||||
|
t.Square(&t) // 2^255 - 2^5
|
||||||
|
|
||||||
|
return v.Multiply(&t, &z11) // 2^255 - 21
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets v = a, and returns v.
|
||||||
|
func (v *Element) Set(a *Element) *Element {
|
||||||
|
*v = *a
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBytes sets v to x, where x is a 32-byte little-endian encoding. If x is
|
||||||
|
// not of the right length, SetBytes returns nil and an error, and the
|
||||||
|
// receiver is unchanged.
|
||||||
|
//
|
||||||
|
// Consistent with RFC 7748, the most significant bit (the high bit of the
|
||||||
|
// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1)
|
||||||
|
// are accepted. Note that this is laxer than specified by RFC 8032, but
|
||||||
|
// consistent with most Ed25519 implementations.
|
||||||
|
func (v *Element) SetBytes(x []byte) (*Element, error) {
|
||||||
|
if len(x) != 32 {
|
||||||
|
return nil, errors.New("edwards25519: invalid field element input size")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51).
|
||||||
|
v.l0 = binary.LittleEndian.Uint64(x[0:8])
|
||||||
|
v.l0 &= maskLow51Bits
|
||||||
|
// Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51).
|
||||||
|
v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3
|
||||||
|
v.l1 &= maskLow51Bits
|
||||||
|
// Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51).
|
||||||
|
v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6
|
||||||
|
v.l2 &= maskLow51Bits
|
||||||
|
// Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51).
|
||||||
|
v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1
|
||||||
|
v.l3 &= maskLow51Bits
|
||||||
|
// Bits 204:255 (bytes 24:32, bits 192:256, shift 12, mask 51).
|
||||||
|
// Note: not bytes 25:33, shift 4, to avoid overread.
|
||||||
|
v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12
|
||||||
|
v.l4 &= maskLow51Bits
|
||||||
|
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the canonical 32-byte little-endian encoding of v.
|
||||||
|
func (v *Element) Bytes() []byte {
|
||||||
|
// This function is outlined to make the allocations inline in the caller
|
||||||
|
// rather than happen on the heap.
|
||||||
|
var out [32]byte
|
||||||
|
return v.bytes(&out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Element) bytes(out *[32]byte) []byte {
|
||||||
|
t := *v
|
||||||
|
t.reduce()
|
||||||
|
|
||||||
|
var buf [8]byte
|
||||||
|
for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} {
|
||||||
|
bitsOffset := i * 51
|
||||||
|
binary.LittleEndian.PutUint64(buf[:], l<<uint(bitsOffset%8))
|
||||||
|
for i, bb := range buf {
|
||||||
|
off := bitsOffset/8 + i
|
||||||
|
if off >= len(out) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
out[off] |= bb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns 1 if v and u are equal, and 0 otherwise.
|
||||||
|
func (v *Element) Equal(u *Element) int {
|
||||||
|
sa, sv := u.Bytes(), v.Bytes()
|
||||||
|
return subtle.ConstantTimeCompare(sa, sv)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise.
|
||||||
|
func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) }
|
||||||
|
|
||||||
|
// Select sets v to a if cond == 1, and to b if cond == 0.
|
||||||
|
func (v *Element) Select(a, b *Element, cond int) *Element {
|
||||||
|
m := mask64Bits(cond)
|
||||||
|
v.l0 = (m & a.l0) | (^m & b.l0)
|
||||||
|
v.l1 = (m & a.l1) | (^m & b.l1)
|
||||||
|
v.l2 = (m & a.l2) | (^m & b.l2)
|
||||||
|
v.l3 = (m & a.l3) | (^m & b.l3)
|
||||||
|
v.l4 = (m & a.l4) | (^m & b.l4)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v.
|
||||||
|
func (v *Element) Swap(u *Element, cond int) {
|
||||||
|
m := mask64Bits(cond)
|
||||||
|
t := m & (v.l0 ^ u.l0)
|
||||||
|
v.l0 ^= t
|
||||||
|
u.l0 ^= t
|
||||||
|
t = m & (v.l1 ^ u.l1)
|
||||||
|
v.l1 ^= t
|
||||||
|
u.l1 ^= t
|
||||||
|
t = m & (v.l2 ^ u.l2)
|
||||||
|
v.l2 ^= t
|
||||||
|
u.l2 ^= t
|
||||||
|
t = m & (v.l3 ^ u.l3)
|
||||||
|
v.l3 ^= t
|
||||||
|
u.l3 ^= t
|
||||||
|
t = m & (v.l4 ^ u.l4)
|
||||||
|
v.l4 ^= t
|
||||||
|
u.l4 ^= t
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNegative returns 1 if v is negative, and 0 otherwise.
|
||||||
|
func (v *Element) IsNegative() int {
|
||||||
|
return int(v.Bytes()[0] & 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Absolute sets v to |u|, and returns v.
|
||||||
|
func (v *Element) Absolute(u *Element) *Element {
|
||||||
|
return v.Select(new(Element).Negate(u), u, u.IsNegative())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply sets v = x * y, and returns v.
|
||||||
|
func (v *Element) Multiply(x, y *Element) *Element {
|
||||||
|
feMul(v, x, y)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Square sets v = x * x, and returns v.
|
||||||
|
func (v *Element) Square(x *Element) *Element {
|
||||||
|
feSquare(v, x)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mult32 sets v = x * y, and returns v.
|
||||||
|
func (v *Element) Mult32(x *Element, y uint32) *Element {
|
||||||
|
x0lo, x0hi := mul51(x.l0, y)
|
||||||
|
x1lo, x1hi := mul51(x.l1, y)
|
||||||
|
x2lo, x2hi := mul51(x.l2, y)
|
||||||
|
x3lo, x3hi := mul51(x.l3, y)
|
||||||
|
x4lo, x4hi := mul51(x.l4, y)
|
||||||
|
v.l0 = x0lo + 19*x4hi // carried over per the reduction identity
|
||||||
|
v.l1 = x1lo + x0hi
|
||||||
|
v.l2 = x2lo + x1hi
|
||||||
|
v.l3 = x3lo + x2hi
|
||||||
|
v.l4 = x4lo + x3hi
|
||||||
|
// The hi portions are going to be only 32 bits, plus any previous excess,
|
||||||
|
// so we can skip the carry propagation.
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// mul51 returns lo + hi * 2⁵¹ = a * b.
|
||||||
|
func mul51(a uint64, b uint32) (lo uint64, hi uint64) {
|
||||||
|
mh, ml := bits.Mul64(a, uint64(b))
|
||||||
|
lo = ml & maskLow51Bits
|
||||||
|
hi = (mh << 13) | (ml >> 51)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3.
|
||||||
|
func (v *Element) Pow22523(x *Element) *Element {
|
||||||
|
var t0, t1, t2 Element
|
||||||
|
|
||||||
|
t0.Square(x) // x^2
|
||||||
|
t1.Square(&t0) // x^4
|
||||||
|
t1.Square(&t1) // x^8
|
||||||
|
t1.Multiply(x, &t1) // x^9
|
||||||
|
t0.Multiply(&t0, &t1) // x^11
|
||||||
|
t0.Square(&t0) // x^22
|
||||||
|
t0.Multiply(&t1, &t0) // x^31
|
||||||
|
t1.Square(&t0) // x^62
|
||||||
|
for i := 1; i < 5; i++ { // x^992
|
||||||
|
t1.Square(&t1)
|
||||||
|
}
|
||||||
|
t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1
|
||||||
|
t1.Square(&t0) // 2^11 - 2
|
||||||
|
for i := 1; i < 10; i++ { // 2^20 - 2^10
|
||||||
|
t1.Square(&t1)
|
||||||
|
}
|
||||||
|
t1.Multiply(&t1, &t0) // 2^20 - 1
|
||||||
|
t2.Square(&t1) // 2^21 - 2
|
||||||
|
for i := 1; i < 20; i++ { // 2^40 - 2^20
|
||||||
|
t2.Square(&t2)
|
||||||
|
}
|
||||||
|
t1.Multiply(&t2, &t1) // 2^40 - 1
|
||||||
|
t1.Square(&t1) // 2^41 - 2
|
||||||
|
for i := 1; i < 10; i++ { // 2^50 - 2^10
|
||||||
|
t1.Square(&t1)
|
||||||
|
}
|
||||||
|
t0.Multiply(&t1, &t0) // 2^50 - 1
|
||||||
|
t1.Square(&t0) // 2^51 - 2
|
||||||
|
for i := 1; i < 50; i++ { // 2^100 - 2^50
|
||||||
|
t1.Square(&t1)
|
||||||
|
}
|
||||||
|
t1.Multiply(&t1, &t0) // 2^100 - 1
|
||||||
|
t2.Square(&t1) // 2^101 - 2
|
||||||
|
for i := 1; i < 100; i++ { // 2^200 - 2^100
|
||||||
|
t2.Square(&t2)
|
||||||
|
}
|
||||||
|
t1.Multiply(&t2, &t1) // 2^200 - 1
|
||||||
|
t1.Square(&t1) // 2^201 - 2
|
||||||
|
for i := 1; i < 50; i++ { // 2^250 - 2^50
|
||||||
|
t1.Square(&t1)
|
||||||
|
}
|
||||||
|
t0.Multiply(&t1, &t0) // 2^250 - 1
|
||||||
|
t0.Square(&t0) // 2^251 - 2
|
||||||
|
t0.Square(&t0) // 2^252 - 4
|
||||||
|
return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion.
|
||||||
|
var sqrtM1 = &Element{1718705420411056, 234908883556509,
|
||||||
|
2233514472574048, 2117202627021982, 765476049583133}
|
||||||
|
|
||||||
|
// SqrtRatio sets r to the non-negative square root of the ratio of u and v.
|
||||||
|
//
|
||||||
|
// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio
|
||||||
|
// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00,
|
||||||
|
// and returns r and 0.
|
||||||
|
func (r *Element) SqrtRatio(u, v *Element) (R *Element, wasSquare int) {
|
||||||
|
t0 := new(Element)
|
||||||
|
|
||||||
|
// r = (u * v3) * (u * v7)^((p-5)/8)
|
||||||
|
v2 := new(Element).Square(v)
|
||||||
|
uv3 := new(Element).Multiply(u, t0.Multiply(v2, v))
|
||||||
|
uv7 := new(Element).Multiply(uv3, t0.Square(v2))
|
||||||
|
rr := new(Element).Multiply(uv3, t0.Pow22523(uv7))
|
||||||
|
|
||||||
|
check := new(Element).Multiply(v, t0.Square(rr)) // check = v * r^2
|
||||||
|
|
||||||
|
uNeg := new(Element).Negate(u)
|
||||||
|
correctSignSqrt := check.Equal(u)
|
||||||
|
flippedSignSqrt := check.Equal(uNeg)
|
||||||
|
flippedSignSqrtI := check.Equal(t0.Multiply(uNeg, sqrtM1))
|
||||||
|
|
||||||
|
rPrime := new(Element).Multiply(rr, sqrtM1) // r_prime = SQRT_M1 * r
|
||||||
|
// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
|
||||||
|
rr.Select(rPrime, rr, flippedSignSqrt|flippedSignSqrtI)
|
||||||
|
|
||||||
|
r.Absolute(rr) // Choose the nonnegative square root.
|
||||||
|
return r, correctSignSqrt | flippedSignSqrt
|
||||||
|
}
|
||||||
16
vendor/filippo.io/edwards25519/field/fe_amd64.go
generated
vendored
Normal file
16
vendor/filippo.io/edwards25519/field/fe_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build amd64 && gc && !purego
|
||||||
|
// +build amd64,gc,!purego
|
||||||
|
|
||||||
|
package field
|
||||||
|
|
||||||
|
// feMul sets out = a * b. It works like feMulGeneric.
|
||||||
|
//
|
||||||
|
//go:noescape
|
||||||
|
func feMul(out *Element, a *Element, b *Element)
|
||||||
|
|
||||||
|
// feSquare sets out = a * a. It works like feSquareGeneric.
|
||||||
|
//
|
||||||
|
//go:noescape
|
||||||
|
func feSquare(out *Element, a *Element)
|
||||||
379
vendor/filippo.io/edwards25519/field/fe_amd64.s
generated
vendored
Normal file
379
vendor/filippo.io/edwards25519/field/fe_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,379 @@
|
||||||
|
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build amd64 && gc && !purego
|
||||||
|
// +build amd64,gc,!purego
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// func feMul(out *Element, a *Element, b *Element)
|
||||||
|
TEXT ·feMul(SB), NOSPLIT, $0-24
|
||||||
|
MOVQ a+8(FP), CX
|
||||||
|
MOVQ b+16(FP), BX
|
||||||
|
|
||||||
|
// r0 = a0×b0
|
||||||
|
MOVQ (CX), AX
|
||||||
|
MULQ (BX)
|
||||||
|
MOVQ AX, DI
|
||||||
|
MOVQ DX, SI
|
||||||
|
|
||||||
|
// r0 += 19×a1×b4
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 32(BX)
|
||||||
|
ADDQ AX, DI
|
||||||
|
ADCQ DX, SI
|
||||||
|
|
||||||
|
// r0 += 19×a2×b3
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 24(BX)
|
||||||
|
ADDQ AX, DI
|
||||||
|
ADCQ DX, SI
|
||||||
|
|
||||||
|
// r0 += 19×a3×b2
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 16(BX)
|
||||||
|
ADDQ AX, DI
|
||||||
|
ADCQ DX, SI
|
||||||
|
|
||||||
|
// r0 += 19×a4×b1
|
||||||
|
MOVQ 32(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 8(BX)
|
||||||
|
ADDQ AX, DI
|
||||||
|
ADCQ DX, SI
|
||||||
|
|
||||||
|
// r1 = a0×b1
|
||||||
|
MOVQ (CX), AX
|
||||||
|
MULQ 8(BX)
|
||||||
|
MOVQ AX, R9
|
||||||
|
MOVQ DX, R8
|
||||||
|
|
||||||
|
// r1 += a1×b0
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
MULQ (BX)
|
||||||
|
ADDQ AX, R9
|
||||||
|
ADCQ DX, R8
|
||||||
|
|
||||||
|
// r1 += 19×a2×b4
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 32(BX)
|
||||||
|
ADDQ AX, R9
|
||||||
|
ADCQ DX, R8
|
||||||
|
|
||||||
|
// r1 += 19×a3×b3
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 24(BX)
|
||||||
|
ADDQ AX, R9
|
||||||
|
ADCQ DX, R8
|
||||||
|
|
||||||
|
// r1 += 19×a4×b2
|
||||||
|
MOVQ 32(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 16(BX)
|
||||||
|
ADDQ AX, R9
|
||||||
|
ADCQ DX, R8
|
||||||
|
|
||||||
|
// r2 = a0×b2
|
||||||
|
MOVQ (CX), AX
|
||||||
|
MULQ 16(BX)
|
||||||
|
MOVQ AX, R11
|
||||||
|
MOVQ DX, R10
|
||||||
|
|
||||||
|
// r2 += a1×b1
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
MULQ 8(BX)
|
||||||
|
ADDQ AX, R11
|
||||||
|
ADCQ DX, R10
|
||||||
|
|
||||||
|
// r2 += a2×b0
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
MULQ (BX)
|
||||||
|
ADDQ AX, R11
|
||||||
|
ADCQ DX, R10
|
||||||
|
|
||||||
|
// r2 += 19×a3×b4
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 32(BX)
|
||||||
|
ADDQ AX, R11
|
||||||
|
ADCQ DX, R10
|
||||||
|
|
||||||
|
// r2 += 19×a4×b3
|
||||||
|
MOVQ 32(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 24(BX)
|
||||||
|
ADDQ AX, R11
|
||||||
|
ADCQ DX, R10
|
||||||
|
|
||||||
|
// r3 = a0×b3
|
||||||
|
MOVQ (CX), AX
|
||||||
|
MULQ 24(BX)
|
||||||
|
MOVQ AX, R13
|
||||||
|
MOVQ DX, R12
|
||||||
|
|
||||||
|
// r3 += a1×b2
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
MULQ 16(BX)
|
||||||
|
ADDQ AX, R13
|
||||||
|
ADCQ DX, R12
|
||||||
|
|
||||||
|
// r3 += a2×b1
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
MULQ 8(BX)
|
||||||
|
ADDQ AX, R13
|
||||||
|
ADCQ DX, R12
|
||||||
|
|
||||||
|
// r3 += a3×b0
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
MULQ (BX)
|
||||||
|
ADDQ AX, R13
|
||||||
|
ADCQ DX, R12
|
||||||
|
|
||||||
|
// r3 += 19×a4×b4
|
||||||
|
MOVQ 32(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 32(BX)
|
||||||
|
ADDQ AX, R13
|
||||||
|
ADCQ DX, R12
|
||||||
|
|
||||||
|
// r4 = a0×b4
|
||||||
|
MOVQ (CX), AX
|
||||||
|
MULQ 32(BX)
|
||||||
|
MOVQ AX, R15
|
||||||
|
MOVQ DX, R14
|
||||||
|
|
||||||
|
// r4 += a1×b3
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
MULQ 24(BX)
|
||||||
|
ADDQ AX, R15
|
||||||
|
ADCQ DX, R14
|
||||||
|
|
||||||
|
// r4 += a2×b2
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
MULQ 16(BX)
|
||||||
|
ADDQ AX, R15
|
||||||
|
ADCQ DX, R14
|
||||||
|
|
||||||
|
// r4 += a3×b1
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
MULQ 8(BX)
|
||||||
|
ADDQ AX, R15
|
||||||
|
ADCQ DX, R14
|
||||||
|
|
||||||
|
// r4 += a4×b0
|
||||||
|
MOVQ 32(CX), AX
|
||||||
|
MULQ (BX)
|
||||||
|
ADDQ AX, R15
|
||||||
|
ADCQ DX, R14
|
||||||
|
|
||||||
|
// First reduction chain
|
||||||
|
MOVQ $0x0007ffffffffffff, AX
|
||||||
|
SHLQ $0x0d, DI, SI
|
||||||
|
SHLQ $0x0d, R9, R8
|
||||||
|
SHLQ $0x0d, R11, R10
|
||||||
|
SHLQ $0x0d, R13, R12
|
||||||
|
SHLQ $0x0d, R15, R14
|
||||||
|
ANDQ AX, DI
|
||||||
|
IMUL3Q $0x13, R14, R14
|
||||||
|
ADDQ R14, DI
|
||||||
|
ANDQ AX, R9
|
||||||
|
ADDQ SI, R9
|
||||||
|
ANDQ AX, R11
|
||||||
|
ADDQ R8, R11
|
||||||
|
ANDQ AX, R13
|
||||||
|
ADDQ R10, R13
|
||||||
|
ANDQ AX, R15
|
||||||
|
ADDQ R12, R15
|
||||||
|
|
||||||
|
// Second reduction chain (carryPropagate)
|
||||||
|
MOVQ DI, SI
|
||||||
|
SHRQ $0x33, SI
|
||||||
|
MOVQ R9, R8
|
||||||
|
SHRQ $0x33, R8
|
||||||
|
MOVQ R11, R10
|
||||||
|
SHRQ $0x33, R10
|
||||||
|
MOVQ R13, R12
|
||||||
|
SHRQ $0x33, R12
|
||||||
|
MOVQ R15, R14
|
||||||
|
SHRQ $0x33, R14
|
||||||
|
ANDQ AX, DI
|
||||||
|
IMUL3Q $0x13, R14, R14
|
||||||
|
ADDQ R14, DI
|
||||||
|
ANDQ AX, R9
|
||||||
|
ADDQ SI, R9
|
||||||
|
ANDQ AX, R11
|
||||||
|
ADDQ R8, R11
|
||||||
|
ANDQ AX, R13
|
||||||
|
ADDQ R10, R13
|
||||||
|
ANDQ AX, R15
|
||||||
|
ADDQ R12, R15
|
||||||
|
|
||||||
|
// Store output
|
||||||
|
MOVQ out+0(FP), AX
|
||||||
|
MOVQ DI, (AX)
|
||||||
|
MOVQ R9, 8(AX)
|
||||||
|
MOVQ R11, 16(AX)
|
||||||
|
MOVQ R13, 24(AX)
|
||||||
|
MOVQ R15, 32(AX)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func feSquare(out *Element, a *Element)
|
||||||
|
TEXT ·feSquare(SB), NOSPLIT, $0-16
|
||||||
|
MOVQ a+8(FP), CX
|
||||||
|
|
||||||
|
// r0 = l0×l0
|
||||||
|
MOVQ (CX), AX
|
||||||
|
MULQ (CX)
|
||||||
|
MOVQ AX, SI
|
||||||
|
MOVQ DX, BX
|
||||||
|
|
||||||
|
// r0 += 38×l1×l4
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
IMUL3Q $0x26, AX, AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX, SI
|
||||||
|
ADCQ DX, BX
|
||||||
|
|
||||||
|
// r0 += 38×l2×l3
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
IMUL3Q $0x26, AX, AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX, SI
|
||||||
|
ADCQ DX, BX
|
||||||
|
|
||||||
|
// r1 = 2×l0×l1
|
||||||
|
MOVQ (CX), AX
|
||||||
|
SHLQ $0x01, AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
MOVQ AX, R8
|
||||||
|
MOVQ DX, DI
|
||||||
|
|
||||||
|
// r1 += 38×l2×l4
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
IMUL3Q $0x26, AX, AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX, R8
|
||||||
|
ADCQ DX, DI
|
||||||
|
|
||||||
|
// r1 += 19×l3×l3
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX, R8
|
||||||
|
ADCQ DX, DI
|
||||||
|
|
||||||
|
// r2 = 2×l0×l2
|
||||||
|
MOVQ (CX), AX
|
||||||
|
SHLQ $0x01, AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
MOVQ AX, R10
|
||||||
|
MOVQ DX, R9
|
||||||
|
|
||||||
|
// r2 += l1×l1
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
MULQ 8(CX)
|
||||||
|
ADDQ AX, R10
|
||||||
|
ADCQ DX, R9
|
||||||
|
|
||||||
|
// r2 += 38×l3×l4
|
||||||
|
MOVQ 24(CX), AX
|
||||||
|
IMUL3Q $0x26, AX, AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX, R10
|
||||||
|
ADCQ DX, R9
|
||||||
|
|
||||||
|
// r3 = 2×l0×l3
|
||||||
|
MOVQ (CX), AX
|
||||||
|
SHLQ $0x01, AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
MOVQ AX, R12
|
||||||
|
MOVQ DX, R11
|
||||||
|
|
||||||
|
// r3 += 2×l1×l2
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
IMUL3Q $0x02, AX, AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX, R12
|
||||||
|
ADCQ DX, R11
|
||||||
|
|
||||||
|
// r3 += 19×l4×l4
|
||||||
|
MOVQ 32(CX), AX
|
||||||
|
IMUL3Q $0x13, AX, AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
ADDQ AX, R12
|
||||||
|
ADCQ DX, R11
|
||||||
|
|
||||||
|
// r4 = 2×l0×l4
|
||||||
|
MOVQ (CX), AX
|
||||||
|
SHLQ $0x01, AX
|
||||||
|
MULQ 32(CX)
|
||||||
|
MOVQ AX, R14
|
||||||
|
MOVQ DX, R13
|
||||||
|
|
||||||
|
// r4 += 2×l1×l3
|
||||||
|
MOVQ 8(CX), AX
|
||||||
|
IMUL3Q $0x02, AX, AX
|
||||||
|
MULQ 24(CX)
|
||||||
|
ADDQ AX, R14
|
||||||
|
ADCQ DX, R13
|
||||||
|
|
||||||
|
// r4 += l2×l2
|
||||||
|
MOVQ 16(CX), AX
|
||||||
|
MULQ 16(CX)
|
||||||
|
ADDQ AX, R14
|
||||||
|
ADCQ DX, R13
|
||||||
|
|
||||||
|
// First reduction chain
|
||||||
|
MOVQ $0x0007ffffffffffff, AX
|
||||||
|
SHLQ $0x0d, SI, BX
|
||||||
|
SHLQ $0x0d, R8, DI
|
||||||
|
SHLQ $0x0d, R10, R9
|
||||||
|
SHLQ $0x0d, R12, R11
|
||||||
|
SHLQ $0x0d, R14, R13
|
||||||
|
ANDQ AX, SI
|
||||||
|
IMUL3Q $0x13, R13, R13
|
||||||
|
ADDQ R13, SI
|
||||||
|
ANDQ AX, R8
|
||||||
|
ADDQ BX, R8
|
||||||
|
ANDQ AX, R10
|
||||||
|
ADDQ DI, R10
|
||||||
|
ANDQ AX, R12
|
||||||
|
ADDQ R9, R12
|
||||||
|
ANDQ AX, R14
|
||||||
|
ADDQ R11, R14
|
||||||
|
|
||||||
|
// Second reduction chain (carryPropagate)
|
||||||
|
MOVQ SI, BX
|
||||||
|
SHRQ $0x33, BX
|
||||||
|
MOVQ R8, DI
|
||||||
|
SHRQ $0x33, DI
|
||||||
|
MOVQ R10, R9
|
||||||
|
SHRQ $0x33, R9
|
||||||
|
MOVQ R12, R11
|
||||||
|
SHRQ $0x33, R11
|
||||||
|
MOVQ R14, R13
|
||||||
|
SHRQ $0x33, R13
|
||||||
|
ANDQ AX, SI
|
||||||
|
IMUL3Q $0x13, R13, R13
|
||||||
|
ADDQ R13, SI
|
||||||
|
ANDQ AX, R8
|
||||||
|
ADDQ BX, R8
|
||||||
|
ANDQ AX, R10
|
||||||
|
ADDQ DI, R10
|
||||||
|
ANDQ AX, R12
|
||||||
|
ADDQ R9, R12
|
||||||
|
ANDQ AX, R14
|
||||||
|
ADDQ R11, R14
|
||||||
|
|
||||||
|
// Store output
|
||||||
|
MOVQ out+0(FP), AX
|
||||||
|
MOVQ SI, (AX)
|
||||||
|
MOVQ R8, 8(AX)
|
||||||
|
MOVQ R10, 16(AX)
|
||||||
|
MOVQ R12, 24(AX)
|
||||||
|
MOVQ R14, 32(AX)
|
||||||
|
RET
|
||||||
12
vendor/filippo.io/edwards25519/field/fe_amd64_noasm.go
generated
vendored
Normal file
12
vendor/filippo.io/edwards25519/field/fe_amd64_noasm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !amd64 || !gc || purego
|
||||||
|
// +build !amd64 !gc purego
|
||||||
|
|
||||||
|
package field
|
||||||
|
|
||||||
|
func feMul(v, x, y *Element) { feMulGeneric(v, x, y) }
|
||||||
|
|
||||||
|
func feSquare(v, x *Element) { feSquareGeneric(v, x) }
|
||||||
16
vendor/filippo.io/edwards25519/field/fe_arm64.go
generated
vendored
Normal file
16
vendor/filippo.io/edwards25519/field/fe_arm64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright (c) 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build arm64 && gc && !purego
|
||||||
|
// +build arm64,gc,!purego
|
||||||
|
|
||||||
|
package field
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func carryPropagate(v *Element)
|
||||||
|
|
||||||
|
func (v *Element) carryPropagate() *Element {
|
||||||
|
carryPropagate(v)
|
||||||
|
return v
|
||||||
|
}
|
||||||
42
vendor/filippo.io/edwards25519/field/fe_arm64.s
generated
vendored
Normal file
42
vendor/filippo.io/edwards25519/field/fe_arm64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (c) 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build arm64 && gc && !purego
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// carryPropagate works exactly like carryPropagateGeneric and uses the
|
||||||
|
// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but
|
||||||
|
// avoids loading R0-R4 twice and uses LDP and STP.
|
||||||
|
//
|
||||||
|
// See https://golang.org/issues/43145 for the main compiler issue.
|
||||||
|
//
|
||||||
|
// func carryPropagate(v *Element)
|
||||||
|
TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8
|
||||||
|
MOVD v+0(FP), R20
|
||||||
|
|
||||||
|
LDP 0(R20), (R0, R1)
|
||||||
|
LDP 16(R20), (R2, R3)
|
||||||
|
MOVD 32(R20), R4
|
||||||
|
|
||||||
|
AND $0x7ffffffffffff, R0, R10
|
||||||
|
AND $0x7ffffffffffff, R1, R11
|
||||||
|
AND $0x7ffffffffffff, R2, R12
|
||||||
|
AND $0x7ffffffffffff, R3, R13
|
||||||
|
AND $0x7ffffffffffff, R4, R14
|
||||||
|
|
||||||
|
ADD R0>>51, R11, R11
|
||||||
|
ADD R1>>51, R12, R12
|
||||||
|
ADD R2>>51, R13, R13
|
||||||
|
ADD R3>>51, R14, R14
|
||||||
|
// R4>>51 * 19 + R10 -> R10
|
||||||
|
LSR $51, R4, R21
|
||||||
|
MOVD $19, R22
|
||||||
|
MADD R22, R10, R21, R10
|
||||||
|
|
||||||
|
STP (R10, R11), 0(R20)
|
||||||
|
STP (R12, R13), 16(R20)
|
||||||
|
MOVD R14, 32(R20)
|
||||||
|
|
||||||
|
RET
|
||||||
12
vendor/filippo.io/edwards25519/field/fe_arm64_noasm.go
generated
vendored
Normal file
12
vendor/filippo.io/edwards25519/field/fe_arm64_noasm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !arm64 || !gc || purego
|
||||||
|
// +build !arm64 !gc purego
|
||||||
|
|
||||||
|
package field
|
||||||
|
|
||||||
|
func (v *Element) carryPropagate() *Element {
|
||||||
|
return v.carryPropagateGeneric()
|
||||||
|
}
|
||||||
50
vendor/filippo.io/edwards25519/field/fe_extra.go
generated
vendored
Normal file
50
vendor/filippo.io/edwards25519/field/fe_extra.go
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright (c) 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package field
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// This file contains additional functionality that is not included in the
|
||||||
|
// upstream crypto/ed25519/edwards25519/field package.
|
||||||
|
|
||||||
|
// SetWideBytes sets v to x, where x is a 64-byte little-endian encoding, which
|
||||||
|
// is reduced modulo the field order. If x is not of the right length,
|
||||||
|
// SetWideBytes returns nil and an error, and the receiver is unchanged.
|
||||||
|
//
|
||||||
|
// SetWideBytes is not necessary to select a uniformly distributed value, and is
|
||||||
|
// only provided for compatibility: SetBytes can be used instead as the chance
|
||||||
|
// of bias is less than 2⁻²⁵⁰.
|
||||||
|
func (v *Element) SetWideBytes(x []byte) (*Element, error) {
|
||||||
|
if len(x) != 64 {
|
||||||
|
return nil, errors.New("edwards25519: invalid SetWideBytes input size")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the 64 bytes into two elements, and extract the most significant
|
||||||
|
// bit of each, which is ignored by SetBytes.
|
||||||
|
lo, _ := new(Element).SetBytes(x[:32])
|
||||||
|
loMSB := uint64(x[31] >> 7)
|
||||||
|
hi, _ := new(Element).SetBytes(x[32:])
|
||||||
|
hiMSB := uint64(x[63] >> 7)
|
||||||
|
|
||||||
|
// The output we want is
|
||||||
|
//
|
||||||
|
// v = lo + loMSB * 2²⁵⁵ + hi * 2²⁵⁶ + hiMSB * 2⁵¹¹
|
||||||
|
//
|
||||||
|
// which applying the reduction identity comes out to
|
||||||
|
//
|
||||||
|
// v = lo + loMSB * 19 + hi * 2 * 19 + hiMSB * 2 * 19²
|
||||||
|
//
|
||||||
|
// l0 will be the sum of a 52 bits value (lo.l0), plus a 5 bits value
|
||||||
|
// (loMSB * 19), a 6 bits value (hi.l0 * 2 * 19), and a 10 bits value
|
||||||
|
// (hiMSB * 2 * 19²), so it fits in a uint64.
|
||||||
|
|
||||||
|
v.l0 = lo.l0 + loMSB*19 + hi.l0*2*19 + hiMSB*2*19*19
|
||||||
|
v.l1 = lo.l1 + hi.l1*2*19
|
||||||
|
v.l2 = lo.l2 + hi.l2*2*19
|
||||||
|
v.l3 = lo.l3 + hi.l3*2*19
|
||||||
|
v.l4 = lo.l4 + hi.l4*2*19
|
||||||
|
|
||||||
|
return v.carryPropagate(), nil
|
||||||
|
}
|
||||||
266
vendor/filippo.io/edwards25519/field/fe_generic.go
generated
vendored
Normal file
266
vendor/filippo.io/edwards25519/field/fe_generic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package field
|
||||||
|
|
||||||
|
import "math/bits"
|
||||||
|
|
||||||
|
// uint128 holds a 128-bit number as two 64-bit limbs, for use with the
|
||||||
|
// bits.Mul64 and bits.Add64 intrinsics.
|
||||||
|
type uint128 struct {
|
||||||
|
lo, hi uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// mul64 returns a * b.
|
||||||
|
func mul64(a, b uint64) uint128 {
|
||||||
|
hi, lo := bits.Mul64(a, b)
|
||||||
|
return uint128{lo, hi}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addMul64 returns v + a * b.
|
||||||
|
func addMul64(v uint128, a, b uint64) uint128 {
|
||||||
|
hi, lo := bits.Mul64(a, b)
|
||||||
|
lo, c := bits.Add64(lo, v.lo, 0)
|
||||||
|
hi, _ = bits.Add64(hi, v.hi, c)
|
||||||
|
return uint128{lo, hi}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits.
|
||||||
|
func shiftRightBy51(a uint128) uint64 {
|
||||||
|
return (a.hi << (64 - 51)) | (a.lo >> 51)
|
||||||
|
}
|
||||||
|
|
||||||
|
func feMulGeneric(v, a, b *Element) {
|
||||||
|
a0 := a.l0
|
||||||
|
a1 := a.l1
|
||||||
|
a2 := a.l2
|
||||||
|
a3 := a.l3
|
||||||
|
a4 := a.l4
|
||||||
|
|
||||||
|
b0 := b.l0
|
||||||
|
b1 := b.l1
|
||||||
|
b2 := b.l2
|
||||||
|
b3 := b.l3
|
||||||
|
b4 := b.l4
|
||||||
|
|
||||||
|
// Limb multiplication works like pen-and-paper columnar multiplication, but
|
||||||
|
// with 51-bit limbs instead of digits.
|
||||||
|
//
|
||||||
|
// a4 a3 a2 a1 a0 x
|
||||||
|
// b4 b3 b2 b1 b0 =
|
||||||
|
// ------------------------
|
||||||
|
// a4b0 a3b0 a2b0 a1b0 a0b0 +
|
||||||
|
// a4b1 a3b1 a2b1 a1b1 a0b1 +
|
||||||
|
// a4b2 a3b2 a2b2 a1b2 a0b2 +
|
||||||
|
// a4b3 a3b3 a2b3 a1b3 a0b3 +
|
||||||
|
// a4b4 a3b4 a2b4 a1b4 a0b4 =
|
||||||
|
// ----------------------------------------------
|
||||||
|
// r8 r7 r6 r5 r4 r3 r2 r1 r0
|
||||||
|
//
|
||||||
|
// We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to
|
||||||
|
// reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5,
|
||||||
|
// r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc.
|
||||||
|
//
|
||||||
|
// Reduction can be carried out simultaneously to multiplication. For
|
||||||
|
// example, we do not compute r5: whenever the result of a multiplication
|
||||||
|
// belongs to r5, like a1b4, we multiply it by 19 and add the result to r0.
|
||||||
|
//
|
||||||
|
// a4b0 a3b0 a2b0 a1b0 a0b0 +
|
||||||
|
// a3b1 a2b1 a1b1 a0b1 19×a4b1 +
|
||||||
|
// a2b2 a1b2 a0b2 19×a4b2 19×a3b2 +
|
||||||
|
// a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 +
|
||||||
|
// a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 =
|
||||||
|
// --------------------------------------
|
||||||
|
// r4 r3 r2 r1 r0
|
||||||
|
//
|
||||||
|
// Finally we add up the columns into wide, overlapping limbs.
|
||||||
|
|
||||||
|
a1_19 := a1 * 19
|
||||||
|
a2_19 := a2 * 19
|
||||||
|
a3_19 := a3 * 19
|
||||||
|
a4_19 := a4 * 19
|
||||||
|
|
||||||
|
// r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
|
||||||
|
r0 := mul64(a0, b0)
|
||||||
|
r0 = addMul64(r0, a1_19, b4)
|
||||||
|
r0 = addMul64(r0, a2_19, b3)
|
||||||
|
r0 = addMul64(r0, a3_19, b2)
|
||||||
|
r0 = addMul64(r0, a4_19, b1)
|
||||||
|
|
||||||
|
// r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2)
|
||||||
|
r1 := mul64(a0, b1)
|
||||||
|
r1 = addMul64(r1, a1, b0)
|
||||||
|
r1 = addMul64(r1, a2_19, b4)
|
||||||
|
r1 = addMul64(r1, a3_19, b3)
|
||||||
|
r1 = addMul64(r1, a4_19, b2)
|
||||||
|
|
||||||
|
// r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3)
|
||||||
|
r2 := mul64(a0, b2)
|
||||||
|
r2 = addMul64(r2, a1, b1)
|
||||||
|
r2 = addMul64(r2, a2, b0)
|
||||||
|
r2 = addMul64(r2, a3_19, b4)
|
||||||
|
r2 = addMul64(r2, a4_19, b3)
|
||||||
|
|
||||||
|
// r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4
|
||||||
|
r3 := mul64(a0, b3)
|
||||||
|
r3 = addMul64(r3, a1, b2)
|
||||||
|
r3 = addMul64(r3, a2, b1)
|
||||||
|
r3 = addMul64(r3, a3, b0)
|
||||||
|
r3 = addMul64(r3, a4_19, b4)
|
||||||
|
|
||||||
|
// r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
|
||||||
|
r4 := mul64(a0, b4)
|
||||||
|
r4 = addMul64(r4, a1, b3)
|
||||||
|
r4 = addMul64(r4, a2, b2)
|
||||||
|
r4 = addMul64(r4, a3, b1)
|
||||||
|
r4 = addMul64(r4, a4, b0)
|
||||||
|
|
||||||
|
// After the multiplication, we need to reduce (carry) the five coefficients
|
||||||
|
// to obtain a result with limbs that are at most slightly larger than 2⁵¹,
|
||||||
|
// to respect the Element invariant.
|
||||||
|
//
|
||||||
|
// Overall, the reduction works the same as carryPropagate, except with
|
||||||
|
// wider inputs: we take the carry for each coefficient by shifting it right
|
||||||
|
// by 51, and add it to the limb above it. The top carry is multiplied by 19
|
||||||
|
// according to the reduction identity and added to the lowest limb.
|
||||||
|
//
|
||||||
|
// The largest coefficient (r0) will be at most 111 bits, which guarantees
|
||||||
|
// that all carries are at most 111 - 51 = 60 bits, which fits in a uint64.
|
||||||
|
//
|
||||||
|
// r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
|
||||||
|
// r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²)
|
||||||
|
// r0 < (1 + 19 × 4) × 2⁵² × 2⁵²
|
||||||
|
// r0 < 2⁷ × 2⁵² × 2⁵²
|
||||||
|
// r0 < 2¹¹¹
|
||||||
|
//
|
||||||
|
// Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most
|
||||||
|
// 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and
|
||||||
|
// allows us to easily apply the reduction identity.
|
||||||
|
//
|
||||||
|
// r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
|
||||||
|
// r4 < 5 × 2⁵² × 2⁵²
|
||||||
|
// r4 < 2¹⁰⁷
|
||||||
|
//
|
||||||
|
|
||||||
|
c0 := shiftRightBy51(r0)
|
||||||
|
c1 := shiftRightBy51(r1)
|
||||||
|
c2 := shiftRightBy51(r2)
|
||||||
|
c3 := shiftRightBy51(r3)
|
||||||
|
c4 := shiftRightBy51(r4)
|
||||||
|
|
||||||
|
rr0 := r0.lo&maskLow51Bits + c4*19
|
||||||
|
rr1 := r1.lo&maskLow51Bits + c0
|
||||||
|
rr2 := r2.lo&maskLow51Bits + c1
|
||||||
|
rr3 := r3.lo&maskLow51Bits + c2
|
||||||
|
rr4 := r4.lo&maskLow51Bits + c3
|
||||||
|
|
||||||
|
// Now all coefficients fit into 64-bit registers but are still too large to
|
||||||
|
// be passed around as an Element. We therefore do one last carry chain,
|
||||||
|
// where the carries will be small enough to fit in the wiggle room above 2⁵¹.
|
||||||
|
*v = Element{rr0, rr1, rr2, rr3, rr4}
|
||||||
|
v.carryPropagate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func feSquareGeneric(v, a *Element) {
|
||||||
|
l0 := a.l0
|
||||||
|
l1 := a.l1
|
||||||
|
l2 := a.l2
|
||||||
|
l3 := a.l3
|
||||||
|
l4 := a.l4
|
||||||
|
|
||||||
|
// Squaring works precisely like multiplication above, but thanks to its
|
||||||
|
// symmetry we get to group a few terms together.
|
||||||
|
//
|
||||||
|
// l4 l3 l2 l1 l0 x
|
||||||
|
// l4 l3 l2 l1 l0 =
|
||||||
|
// ------------------------
|
||||||
|
// l4l0 l3l0 l2l0 l1l0 l0l0 +
|
||||||
|
// l4l1 l3l1 l2l1 l1l1 l0l1 +
|
||||||
|
// l4l2 l3l2 l2l2 l1l2 l0l2 +
|
||||||
|
// l4l3 l3l3 l2l3 l1l3 l0l3 +
|
||||||
|
// l4l4 l3l4 l2l4 l1l4 l0l4 =
|
||||||
|
// ----------------------------------------------
|
||||||
|
// r8 r7 r6 r5 r4 r3 r2 r1 r0
|
||||||
|
//
|
||||||
|
// l4l0 l3l0 l2l0 l1l0 l0l0 +
|
||||||
|
// l3l1 l2l1 l1l1 l0l1 19×l4l1 +
|
||||||
|
// l2l2 l1l2 l0l2 19×l4l2 19×l3l2 +
|
||||||
|
// l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 +
|
||||||
|
// l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 =
|
||||||
|
// --------------------------------------
|
||||||
|
// r4 r3 r2 r1 r0
|
||||||
|
//
|
||||||
|
// With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with
|
||||||
|
// only three Mul64 and four Add64, instead of five and eight.
|
||||||
|
|
||||||
|
l0_2 := l0 * 2
|
||||||
|
l1_2 := l1 * 2
|
||||||
|
|
||||||
|
l1_38 := l1 * 38
|
||||||
|
l2_38 := l2 * 38
|
||||||
|
l3_38 := l3 * 38
|
||||||
|
|
||||||
|
l3_19 := l3 * 19
|
||||||
|
l4_19 := l4 * 19
|
||||||
|
|
||||||
|
// r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3)
|
||||||
|
r0 := mul64(l0, l0)
|
||||||
|
r0 = addMul64(r0, l1_38, l4)
|
||||||
|
r0 = addMul64(r0, l2_38, l3)
|
||||||
|
|
||||||
|
// r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3
|
||||||
|
r1 := mul64(l0_2, l1)
|
||||||
|
r1 = addMul64(r1, l2_38, l4)
|
||||||
|
r1 = addMul64(r1, l3_19, l3)
|
||||||
|
|
||||||
|
// r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4
|
||||||
|
r2 := mul64(l0_2, l2)
|
||||||
|
r2 = addMul64(r2, l1, l1)
|
||||||
|
r2 = addMul64(r2, l3_38, l4)
|
||||||
|
|
||||||
|
// r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4
|
||||||
|
r3 := mul64(l0_2, l3)
|
||||||
|
r3 = addMul64(r3, l1_2, l2)
|
||||||
|
r3 = addMul64(r3, l4_19, l4)
|
||||||
|
|
||||||
|
// r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2
|
||||||
|
r4 := mul64(l0_2, l4)
|
||||||
|
r4 = addMul64(r4, l1_2, l3)
|
||||||
|
r4 = addMul64(r4, l2, l2)
|
||||||
|
|
||||||
|
c0 := shiftRightBy51(r0)
|
||||||
|
c1 := shiftRightBy51(r1)
|
||||||
|
c2 := shiftRightBy51(r2)
|
||||||
|
c3 := shiftRightBy51(r3)
|
||||||
|
c4 := shiftRightBy51(r4)
|
||||||
|
|
||||||
|
rr0 := r0.lo&maskLow51Bits + c4*19
|
||||||
|
rr1 := r1.lo&maskLow51Bits + c0
|
||||||
|
rr2 := r2.lo&maskLow51Bits + c1
|
||||||
|
rr3 := r3.lo&maskLow51Bits + c2
|
||||||
|
rr4 := r4.lo&maskLow51Bits + c3
|
||||||
|
|
||||||
|
*v = Element{rr0, rr1, rr2, rr3, rr4}
|
||||||
|
v.carryPropagate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction
|
||||||
|
// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry.
|
||||||
|
func (v *Element) carryPropagateGeneric() *Element {
|
||||||
|
c0 := v.l0 >> 51
|
||||||
|
c1 := v.l1 >> 51
|
||||||
|
c2 := v.l2 >> 51
|
||||||
|
c3 := v.l3 >> 51
|
||||||
|
c4 := v.l4 >> 51
|
||||||
|
|
||||||
|
// c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and
|
||||||
|
// the final l0 will be at most 52 bits. Similarly for the rest.
|
||||||
|
v.l0 = v.l0&maskLow51Bits + c4*19
|
||||||
|
v.l1 = v.l1&maskLow51Bits + c0
|
||||||
|
v.l2 = v.l2&maskLow51Bits + c1
|
||||||
|
v.l3 = v.l3&maskLow51Bits + c2
|
||||||
|
v.l4 = v.l4&maskLow51Bits + c3
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
343
vendor/filippo.io/edwards25519/scalar.go
generated
vendored
Normal file
343
vendor/filippo.io/edwards25519/scalar.go
generated
vendored
Normal file
|
|
@ -0,0 +1,343 @@
|
||||||
|
// Copyright (c) 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package edwards25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Scalar is an integer modulo
|
||||||
|
//
|
||||||
|
// l = 2^252 + 27742317777372353535851937790883648493
|
||||||
|
//
|
||||||
|
// which is the prime order of the edwards25519 group.
|
||||||
|
//
|
||||||
|
// This type works similarly to math/big.Int, and all arguments and
|
||||||
|
// receivers are allowed to alias.
|
||||||
|
//
|
||||||
|
// The zero value is a valid zero element.
|
||||||
|
type Scalar struct {
|
||||||
|
// s is the scalar in the Montgomery domain, in the format of the
|
||||||
|
// fiat-crypto implementation.
|
||||||
|
s fiatScalarMontgomeryDomainFieldElement
|
||||||
|
}
|
||||||
|
|
||||||
|
// The field implementation in scalar_fiat.go is generated by the fiat-crypto
|
||||||
|
// project (https://github.com/mit-plv/fiat-crypto) at version v0.0.9 (23d2dbc)
|
||||||
|
// from a formally verified model.
|
||||||
|
//
|
||||||
|
// fiat-crypto code comes under the following license.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design,
|
||||||
|
// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
|
||||||
|
// NewScalar returns a new zero Scalar.
|
||||||
|
func NewScalar() *Scalar {
|
||||||
|
return &Scalar{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiplyAdd sets s = x * y + z mod l, and returns s. It is equivalent to
|
||||||
|
// using Multiply and then Add.
|
||||||
|
func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar {
|
||||||
|
// Make a copy of z in case it aliases s.
|
||||||
|
zCopy := new(Scalar).Set(z)
|
||||||
|
return s.Multiply(x, y).Add(s, zCopy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets s = x + y mod l, and returns s.
|
||||||
|
func (s *Scalar) Add(x, y *Scalar) *Scalar {
|
||||||
|
// s = 1 * x + y mod l
|
||||||
|
fiatScalarAdd(&s.s, &x.s, &y.s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtract sets s = x - y mod l, and returns s.
|
||||||
|
func (s *Scalar) Subtract(x, y *Scalar) *Scalar {
|
||||||
|
// s = -1 * y + x mod l
|
||||||
|
fiatScalarSub(&s.s, &x.s, &y.s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negate sets s = -x mod l, and returns s.
|
||||||
|
func (s *Scalar) Negate(x *Scalar) *Scalar {
|
||||||
|
// s = -1 * x + 0 mod l
|
||||||
|
fiatScalarOpp(&s.s, &x.s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply sets s = x * y mod l, and returns s.
|
||||||
|
func (s *Scalar) Multiply(x, y *Scalar) *Scalar {
|
||||||
|
// s = x * y + 0 mod l
|
||||||
|
fiatScalarMul(&s.s, &x.s, &y.s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets s = x, and returns s.
|
||||||
|
func (s *Scalar) Set(x *Scalar) *Scalar {
|
||||||
|
*s = *x
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUniformBytes sets s = x mod l, where x is a 64-byte little-endian integer.
|
||||||
|
// If x is not of the right length, SetUniformBytes returns nil and an error,
|
||||||
|
// and the receiver is unchanged.
|
||||||
|
//
|
||||||
|
// SetUniformBytes can be used to set s to a uniformly distributed value given
|
||||||
|
// 64 uniformly distributed random bytes.
|
||||||
|
func (s *Scalar) SetUniformBytes(x []byte) (*Scalar, error) {
|
||||||
|
if len(x) != 64 {
|
||||||
|
return nil, errors.New("edwards25519: invalid SetUniformBytes input length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a value x of 512 bits, but our fiatScalarFromBytes function
|
||||||
|
// expects an input lower than l, which is a little over 252 bits.
|
||||||
|
//
|
||||||
|
// Instead of writing a reduction function that operates on wider inputs, we
|
||||||
|
// can interpret x as the sum of three shorter values a, b, and c.
|
||||||
|
//
|
||||||
|
// x = a + b * 2^168 + c * 2^336 mod l
|
||||||
|
//
|
||||||
|
// We then precompute 2^168 and 2^336 modulo l, and perform the reduction
|
||||||
|
// with two multiplications and two additions.
|
||||||
|
|
||||||
|
s.setShortBytes(x[:21])
|
||||||
|
t := new(Scalar).setShortBytes(x[21:42])
|
||||||
|
s.Add(s, t.Multiply(t, scalarTwo168))
|
||||||
|
t.setShortBytes(x[42:])
|
||||||
|
s.Add(s, t.Multiply(t, scalarTwo336))
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// scalarTwo168 and scalarTwo336 are 2^168 and 2^336 modulo l, encoded as a
|
||||||
|
// fiatScalarMontgomeryDomainFieldElement, which is a little-endian 4-limb value
|
||||||
|
// in the 2^256 Montgomery domain.
|
||||||
|
var scalarTwo168 = &Scalar{s: [4]uint64{0x5b8ab432eac74798, 0x38afddd6de59d5d7,
|
||||||
|
0xa2c131b399411b7c, 0x6329a7ed9ce5a30}}
|
||||||
|
var scalarTwo336 = &Scalar{s: [4]uint64{0xbd3d108e2b35ecc5, 0x5c3a3718bdf9c90b,
|
||||||
|
0x63aa97a331b4f2ee, 0x3d217f5be65cb5c}}
|
||||||
|
|
||||||
|
// setShortBytes sets s = x mod l, where x is a little-endian integer shorter
|
||||||
|
// than 32 bytes.
|
||||||
|
func (s *Scalar) setShortBytes(x []byte) *Scalar {
|
||||||
|
if len(x) >= 32 {
|
||||||
|
panic("edwards25519: internal error: setShortBytes called with a long string")
|
||||||
|
}
|
||||||
|
var buf [32]byte
|
||||||
|
copy(buf[:], x)
|
||||||
|
fiatScalarFromBytes((*[4]uint64)(&s.s), &buf)
|
||||||
|
fiatScalarToMontgomery(&s.s, (*fiatScalarNonMontgomeryDomainFieldElement)(&s.s))
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of
|
||||||
|
// s, and returns s. If x is not a canonical encoding of s, SetCanonicalBytes
|
||||||
|
// returns nil and an error, and the receiver is unchanged.
|
||||||
|
func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) {
|
||||||
|
if len(x) != 32 {
|
||||||
|
return nil, errors.New("invalid scalar length")
|
||||||
|
}
|
||||||
|
if !isReduced(x) {
|
||||||
|
return nil, errors.New("invalid scalar encoding")
|
||||||
|
}
|
||||||
|
|
||||||
|
fiatScalarFromBytes((*[4]uint64)(&s.s), (*[32]byte)(x))
|
||||||
|
fiatScalarToMontgomery(&s.s, (*fiatScalarNonMontgomeryDomainFieldElement)(&s.s))
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// scalarMinusOneBytes is l - 1 in little endian.
|
||||||
|
var scalarMinusOneBytes = [32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}
|
||||||
|
|
||||||
|
// isReduced returns whether the given scalar in 32-byte little endian encoded
|
||||||
|
// form is reduced modulo l.
|
||||||
|
func isReduced(s []byte) bool {
|
||||||
|
if len(s) != 32 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := len(s) - 1; i >= 0; i-- {
|
||||||
|
switch {
|
||||||
|
case s[i] > scalarMinusOneBytes[i]:
|
||||||
|
return false
|
||||||
|
case s[i] < scalarMinusOneBytes[i]:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBytesWithClamping applies the buffer pruning described in RFC 8032,
|
||||||
|
// Section 5.1.5 (also known as clamping) and sets s to the result. The input
|
||||||
|
// must be 32 bytes, and it is not modified. If x is not of the right length,
|
||||||
|
// SetBytesWithClamping returns nil and an error, and the receiver is unchanged.
|
||||||
|
//
|
||||||
|
// Note that since Scalar values are always reduced modulo the prime order of
|
||||||
|
// the curve, the resulting value will not preserve any of the cofactor-clearing
|
||||||
|
// properties that clamping is meant to provide. It will however work as
|
||||||
|
// expected as long as it is applied to points on the prime order subgroup, like
|
||||||
|
// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the
|
||||||
|
// irrelevant RFC 7748 clamping, but it is now required for compatibility.
|
||||||
|
func (s *Scalar) SetBytesWithClamping(x []byte) (*Scalar, error) {
|
||||||
|
// The description above omits the purpose of the high bits of the clamping
|
||||||
|
// for brevity, but those are also lost to reductions, and are also
|
||||||
|
// irrelevant to edwards25519 as they protect against a specific
|
||||||
|
// implementation bug that was once observed in a generic Montgomery ladder.
|
||||||
|
if len(x) != 32 {
|
||||||
|
return nil, errors.New("edwards25519: invalid SetBytesWithClamping input length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to use the wide reduction from SetUniformBytes, since clamping
|
||||||
|
// sets the 2^254 bit, making the value higher than the order.
|
||||||
|
var wideBytes [64]byte
|
||||||
|
copy(wideBytes[:], x[:])
|
||||||
|
wideBytes[0] &= 248
|
||||||
|
wideBytes[31] &= 63
|
||||||
|
wideBytes[31] |= 64
|
||||||
|
return s.SetUniformBytes(wideBytes[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the canonical 32-byte little-endian encoding of s.
|
||||||
|
func (s *Scalar) Bytes() []byte {
|
||||||
|
// This function is outlined to make the allocations inline in the caller
|
||||||
|
// rather than happen on the heap.
|
||||||
|
var encoded [32]byte
|
||||||
|
return s.bytes(&encoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scalar) bytes(out *[32]byte) []byte {
|
||||||
|
var ss fiatScalarNonMontgomeryDomainFieldElement
|
||||||
|
fiatScalarFromMontgomery(&ss, &s.s)
|
||||||
|
fiatScalarToBytes(out, (*[4]uint64)(&ss))
|
||||||
|
return out[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns 1 if s and t are equal, and 0 otherwise.
|
||||||
|
func (s *Scalar) Equal(t *Scalar) int {
|
||||||
|
var diff fiatScalarMontgomeryDomainFieldElement
|
||||||
|
fiatScalarSub(&diff, &s.s, &t.s)
|
||||||
|
var nonzero uint64
|
||||||
|
fiatScalarNonzero(&nonzero, (*[4]uint64)(&diff))
|
||||||
|
nonzero |= nonzero >> 32
|
||||||
|
nonzero |= nonzero >> 16
|
||||||
|
nonzero |= nonzero >> 8
|
||||||
|
nonzero |= nonzero >> 4
|
||||||
|
nonzero |= nonzero >> 2
|
||||||
|
nonzero |= nonzero >> 1
|
||||||
|
return int(^nonzero) & 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// nonAdjacentForm computes a width-w non-adjacent form for this scalar.
|
||||||
|
//
|
||||||
|
// w must be between 2 and 8, or nonAdjacentForm will panic.
|
||||||
|
func (s *Scalar) nonAdjacentForm(w uint) [256]int8 {
|
||||||
|
// This implementation is adapted from the one
|
||||||
|
// in curve25519-dalek and is documented there:
|
||||||
|
// https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871
|
||||||
|
b := s.Bytes()
|
||||||
|
if b[31] > 127 {
|
||||||
|
panic("scalar has high bit set illegally")
|
||||||
|
}
|
||||||
|
if w < 2 {
|
||||||
|
panic("w must be at least 2 by the definition of NAF")
|
||||||
|
} else if w > 8 {
|
||||||
|
panic("NAF digits must fit in int8")
|
||||||
|
}
|
||||||
|
|
||||||
|
var naf [256]int8
|
||||||
|
var digits [5]uint64
|
||||||
|
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
digits[i] = binary.LittleEndian.Uint64(b[i*8:])
|
||||||
|
}
|
||||||
|
|
||||||
|
width := uint64(1 << w)
|
||||||
|
windowMask := uint64(width - 1)
|
||||||
|
|
||||||
|
pos := uint(0)
|
||||||
|
carry := uint64(0)
|
||||||
|
for pos < 256 {
|
||||||
|
indexU64 := pos / 64
|
||||||
|
indexBit := pos % 64
|
||||||
|
var bitBuf uint64
|
||||||
|
if indexBit < 64-w {
|
||||||
|
// This window's bits are contained in a single u64
|
||||||
|
bitBuf = digits[indexU64] >> indexBit
|
||||||
|
} else {
|
||||||
|
// Combine the current 64 bits with bits from the next 64
|
||||||
|
bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add carry into the current window
|
||||||
|
window := carry + (bitBuf & windowMask)
|
||||||
|
|
||||||
|
if window&1 == 0 {
|
||||||
|
// If the window value is even, preserve the carry and continue.
|
||||||
|
// Why is the carry preserved?
|
||||||
|
// If carry == 0 and window & 1 == 0,
|
||||||
|
// then the next carry should be 0
|
||||||
|
// If carry == 1 and window & 1 == 0,
|
||||||
|
// then bit_buf & 1 == 1 so the next carry should be 1
|
||||||
|
pos += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if window < width/2 {
|
||||||
|
carry = 0
|
||||||
|
naf[pos] = int8(window)
|
||||||
|
} else {
|
||||||
|
carry = 1
|
||||||
|
naf[pos] = int8(window) - int8(width)
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += w
|
||||||
|
}
|
||||||
|
return naf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scalar) signedRadix16() [64]int8 {
|
||||||
|
b := s.Bytes()
|
||||||
|
if b[31] > 127 {
|
||||||
|
panic("scalar has high bit set illegally")
|
||||||
|
}
|
||||||
|
|
||||||
|
var digits [64]int8
|
||||||
|
|
||||||
|
// Compute unsigned radix-16 digits:
|
||||||
|
for i := 0; i < 32; i++ {
|
||||||
|
digits[2*i] = int8(b[i] & 15)
|
||||||
|
digits[2*i+1] = int8((b[i] >> 4) & 15)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recenter coefficients:
|
||||||
|
for i := 0; i < 63; i++ {
|
||||||
|
carry := (digits[i] + 8) >> 4
|
||||||
|
digits[i] -= carry << 4
|
||||||
|
digits[i+1] += carry
|
||||||
|
}
|
||||||
|
|
||||||
|
return digits
|
||||||
|
}
|
||||||
1147
vendor/filippo.io/edwards25519/scalar_fiat.go
generated
vendored
Normal file
1147
vendor/filippo.io/edwards25519/scalar_fiat.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
214
vendor/filippo.io/edwards25519/scalarmult.go
generated
vendored
Normal file
214
vendor/filippo.io/edwards25519/scalarmult.go
generated
vendored
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package edwards25519
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
// basepointTable is a set of 32 affineLookupTables, where table i is generated
|
||||||
|
// from 256i * basepoint. It is precomputed the first time it's used.
|
||||||
|
func basepointTable() *[32]affineLookupTable {
|
||||||
|
basepointTablePrecomp.initOnce.Do(func() {
|
||||||
|
p := NewGeneratorPoint()
|
||||||
|
for i := 0; i < 32; i++ {
|
||||||
|
basepointTablePrecomp.table[i].FromP3(p)
|
||||||
|
for j := 0; j < 8; j++ {
|
||||||
|
p.Add(p, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return &basepointTablePrecomp.table
|
||||||
|
}
|
||||||
|
|
||||||
|
var basepointTablePrecomp struct {
|
||||||
|
table [32]affineLookupTable
|
||||||
|
initOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarBaseMult sets v = x * B, where B is the canonical generator, and
|
||||||
|
// returns v.
|
||||||
|
//
|
||||||
|
// The scalar multiplication is done in constant time.
|
||||||
|
func (v *Point) ScalarBaseMult(x *Scalar) *Point {
|
||||||
|
basepointTable := basepointTable()
|
||||||
|
|
||||||
|
// Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i )
|
||||||
|
// as described in the Ed25519 paper
|
||||||
|
//
|
||||||
|
// Group even and odd coefficients
|
||||||
|
// x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
|
||||||
|
// + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B
|
||||||
|
// x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
|
||||||
|
// + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B)
|
||||||
|
//
|
||||||
|
// We use a lookup table for each i to get x_i*16^(2*i)*B
|
||||||
|
// and do four doublings to multiply by 16.
|
||||||
|
digits := x.signedRadix16()
|
||||||
|
|
||||||
|
multiple := &affineCached{}
|
||||||
|
tmp1 := &projP1xP1{}
|
||||||
|
tmp2 := &projP2{}
|
||||||
|
|
||||||
|
// Accumulate the odd components first
|
||||||
|
v.Set(NewIdentityPoint())
|
||||||
|
for i := 1; i < 64; i += 2 {
|
||||||
|
basepointTable[i/2].SelectInto(multiple, digits[i])
|
||||||
|
tmp1.AddAffine(v, multiple)
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply by 16
|
||||||
|
tmp2.FromP3(v) // tmp2 = v in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords
|
||||||
|
v.fromP1xP1(tmp1) // now v = 16*(odd components)
|
||||||
|
|
||||||
|
// Accumulate the even components
|
||||||
|
for i := 0; i < 64; i += 2 {
|
||||||
|
basepointTable[i/2].SelectInto(multiple, digits[i])
|
||||||
|
tmp1.AddAffine(v, multiple)
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScalarMult sets v = x * q, and returns v.
|
||||||
|
//
|
||||||
|
// The scalar multiplication is done in constant time.
|
||||||
|
func (v *Point) ScalarMult(x *Scalar, q *Point) *Point {
|
||||||
|
checkInitialized(q)
|
||||||
|
|
||||||
|
var table projLookupTable
|
||||||
|
table.FromP3(q)
|
||||||
|
|
||||||
|
// Write x = sum(x_i * 16^i)
|
||||||
|
// so x*Q = sum( Q*x_i*16^i )
|
||||||
|
// = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... )
|
||||||
|
// <------compute inside out---------
|
||||||
|
//
|
||||||
|
// We use the lookup table to get the x_i*Q values
|
||||||
|
// and do four doublings to compute 16*Q
|
||||||
|
digits := x.signedRadix16()
|
||||||
|
|
||||||
|
// Unwrap first loop iteration to save computing 16*identity
|
||||||
|
multiple := &projCached{}
|
||||||
|
tmp1 := &projP1xP1{}
|
||||||
|
tmp2 := &projP2{}
|
||||||
|
table.SelectInto(multiple, digits[63])
|
||||||
|
|
||||||
|
v.Set(NewIdentityPoint())
|
||||||
|
tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords
|
||||||
|
for i := 62; i >= 0; i-- {
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords
|
||||||
|
tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords
|
||||||
|
tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords
|
||||||
|
v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords
|
||||||
|
table.SelectInto(multiple, digits[i])
|
||||||
|
tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords
|
||||||
|
}
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// basepointNafTable is the nafLookupTable8 for the basepoint.
|
||||||
|
// It is precomputed the first time it's used.
|
||||||
|
func basepointNafTable() *nafLookupTable8 {
|
||||||
|
basepointNafTablePrecomp.initOnce.Do(func() {
|
||||||
|
basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint())
|
||||||
|
})
|
||||||
|
return &basepointNafTablePrecomp.table
|
||||||
|
}
|
||||||
|
|
||||||
|
var basepointNafTablePrecomp struct {
|
||||||
|
table nafLookupTable8
|
||||||
|
initOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
// VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical
|
||||||
|
// generator, and returns v.
|
||||||
|
//
|
||||||
|
// Execution time depends on the inputs.
|
||||||
|
func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point {
|
||||||
|
checkInitialized(A)
|
||||||
|
|
||||||
|
// Similarly to the single variable-base approach, we compute
|
||||||
|
// digits and use them with a lookup table. However, because
|
||||||
|
// we are allowed to do variable-time operations, we don't
|
||||||
|
// need constant-time lookups or constant-time digit
|
||||||
|
// computations.
|
||||||
|
//
|
||||||
|
// So we use a non-adjacent form of some width w instead of
|
||||||
|
// radix 16. This is like a binary representation (one digit
|
||||||
|
// for each binary place) but we allow the digits to grow in
|
||||||
|
// magnitude up to 2^{w-1} so that the nonzero digits are as
|
||||||
|
// sparse as possible. Intuitively, this "condenses" the
|
||||||
|
// "mass" of the scalar onto sparse coefficients (meaning
|
||||||
|
// fewer additions).
|
||||||
|
|
||||||
|
basepointNafTable := basepointNafTable()
|
||||||
|
var aTable nafLookupTable5
|
||||||
|
aTable.FromP3(A)
|
||||||
|
// Because the basepoint is fixed, we can use a wider NAF
|
||||||
|
// corresponding to a bigger table.
|
||||||
|
aNaf := a.nonAdjacentForm(5)
|
||||||
|
bNaf := b.nonAdjacentForm(8)
|
||||||
|
|
||||||
|
// Find the first nonzero coefficient.
|
||||||
|
i := 255
|
||||||
|
for j := i; j >= 0; j-- {
|
||||||
|
if aNaf[j] != 0 || bNaf[j] != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
multA := &projCached{}
|
||||||
|
multB := &affineCached{}
|
||||||
|
tmp1 := &projP1xP1{}
|
||||||
|
tmp2 := &projP2{}
|
||||||
|
tmp2.Zero()
|
||||||
|
|
||||||
|
// Move from high to low bits, doubling the accumulator
|
||||||
|
// at each iteration and checking whether there is a nonzero
|
||||||
|
// coefficient to look up a multiple of.
|
||||||
|
for ; i >= 0; i-- {
|
||||||
|
tmp1.Double(tmp2)
|
||||||
|
|
||||||
|
// Only update v if we have a nonzero coeff to add in.
|
||||||
|
if aNaf[i] > 0 {
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
aTable.SelectInto(multA, aNaf[i])
|
||||||
|
tmp1.Add(v, multA)
|
||||||
|
} else if aNaf[i] < 0 {
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
aTable.SelectInto(multA, -aNaf[i])
|
||||||
|
tmp1.Sub(v, multA)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bNaf[i] > 0 {
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
basepointNafTable.SelectInto(multB, bNaf[i])
|
||||||
|
tmp1.AddAffine(v, multB)
|
||||||
|
} else if bNaf[i] < 0 {
|
||||||
|
v.fromP1xP1(tmp1)
|
||||||
|
basepointNafTable.SelectInto(multB, -bNaf[i])
|
||||||
|
tmp1.SubAffine(v, multB)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp2.FromP1xP1(tmp1)
|
||||||
|
}
|
||||||
|
|
||||||
|
v.fromP2(tmp2)
|
||||||
|
return v
|
||||||
|
}
|
||||||
129
vendor/filippo.io/edwards25519/tables.go
generated
vendored
Normal file
129
vendor/filippo.io/edwards25519/tables.go
generated
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package edwards25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A dynamic lookup table for variable-base, constant-time scalar muls.
|
||||||
|
type projLookupTable struct {
|
||||||
|
points [8]projCached
|
||||||
|
}
|
||||||
|
|
||||||
|
// A precomputed lookup table for fixed-base, constant-time scalar muls.
|
||||||
|
type affineLookupTable struct {
|
||||||
|
points [8]affineCached
|
||||||
|
}
|
||||||
|
|
||||||
|
// A dynamic lookup table for variable-base, variable-time scalar muls.
|
||||||
|
type nafLookupTable5 struct {
|
||||||
|
points [8]projCached
|
||||||
|
}
|
||||||
|
|
||||||
|
// A precomputed lookup table for fixed-base, variable-time scalar muls.
|
||||||
|
type nafLookupTable8 struct {
|
||||||
|
points [64]affineCached
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructors.
|
||||||
|
|
||||||
|
// Builds a lookup table at runtime. Fast.
|
||||||
|
func (v *projLookupTable) FromP3(q *Point) {
|
||||||
|
// Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
|
||||||
|
// This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
|
||||||
|
v.points[0].FromP3(q)
|
||||||
|
tmpP3 := Point{}
|
||||||
|
tmpP1xP1 := projP1xP1{}
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
// Compute (i+1)*Q as Q + i*Q and convert to a projCached
|
||||||
|
// This is needlessly complicated because the API has explicit
|
||||||
|
// receivers instead of creating stack objects and relying on RVO
|
||||||
|
v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i])))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not optimised for speed; fixed-base tables should be precomputed.
|
||||||
|
func (v *affineLookupTable) FromP3(q *Point) {
|
||||||
|
// Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
|
||||||
|
// This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
|
||||||
|
v.points[0].FromP3(q)
|
||||||
|
tmpP3 := Point{}
|
||||||
|
tmpP1xP1 := projP1xP1{}
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
// Compute (i+1)*Q as Q + i*Q and convert to affineCached
|
||||||
|
v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i])))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builds a lookup table at runtime. Fast.
|
||||||
|
func (v *nafLookupTable5) FromP3(q *Point) {
|
||||||
|
// Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q
|
||||||
|
// This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q
|
||||||
|
v.points[0].FromP3(q)
|
||||||
|
q2 := Point{}
|
||||||
|
q2.Add(q, q)
|
||||||
|
tmpP3 := Point{}
|
||||||
|
tmpP1xP1 := projP1xP1{}
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(&q2, &v.points[i])))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not optimised for speed; fixed-base tables should be precomputed.
|
||||||
|
func (v *nafLookupTable8) FromP3(q *Point) {
|
||||||
|
v.points[0].FromP3(q)
|
||||||
|
q2 := Point{}
|
||||||
|
q2.Add(q, q)
|
||||||
|
tmpP3 := Point{}
|
||||||
|
tmpP1xP1 := projP1xP1{}
|
||||||
|
for i := 0; i < 63; i++ {
|
||||||
|
v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i])))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selectors.
|
||||||
|
|
||||||
|
// Set dest to x*Q, where -8 <= x <= 8, in constant time.
|
||||||
|
func (v *projLookupTable) SelectInto(dest *projCached, x int8) {
|
||||||
|
// Compute xabs = |x|
|
||||||
|
xmask := x >> 7
|
||||||
|
xabs := uint8((x + xmask) ^ xmask)
|
||||||
|
|
||||||
|
dest.Zero()
|
||||||
|
for j := 1; j <= 8; j++ {
|
||||||
|
// Set dest = j*Q if |x| = j
|
||||||
|
cond := subtle.ConstantTimeByteEq(xabs, uint8(j))
|
||||||
|
dest.Select(&v.points[j-1], dest, cond)
|
||||||
|
}
|
||||||
|
// Now dest = |x|*Q, conditionally negate to get x*Q
|
||||||
|
dest.CondNeg(int(xmask & 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set dest to x*Q, where -8 <= x <= 8, in constant time.
|
||||||
|
func (v *affineLookupTable) SelectInto(dest *affineCached, x int8) {
|
||||||
|
// Compute xabs = |x|
|
||||||
|
xmask := x >> 7
|
||||||
|
xabs := uint8((x + xmask) ^ xmask)
|
||||||
|
|
||||||
|
dest.Zero()
|
||||||
|
for j := 1; j <= 8; j++ {
|
||||||
|
// Set dest = j*Q if |x| = j
|
||||||
|
cond := subtle.ConstantTimeByteEq(xabs, uint8(j))
|
||||||
|
dest.Select(&v.points[j-1], dest, cond)
|
||||||
|
}
|
||||||
|
// Now dest = |x|*Q, conditionally negate to get x*Q
|
||||||
|
dest.CondNeg(int(xmask & 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given odd x with 0 < x < 2^4, return x*Q (in variable time).
|
||||||
|
func (v *nafLookupTable5) SelectInto(dest *projCached, x int8) {
|
||||||
|
*dest = v.points[x/2]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given odd x with 0 < x < 2^7, return x*Q (in variable time).
|
||||||
|
func (v *nafLookupTable8) SelectInto(dest *affineCached, x int8) {
|
||||||
|
*dest = v.points[x/2]
|
||||||
|
}
|
||||||
2
vendor/github.com/etkecc/go-linkpearl/.golangci.yml
generated
vendored
2
vendor/github.com/etkecc/go-linkpearl/.golangci.yml
generated
vendored
|
|
@ -76,6 +76,7 @@ linters:
|
||||||
- bidichk
|
- bidichk
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- containedctx
|
- containedctx
|
||||||
|
- copyloopvar
|
||||||
- decorder
|
- decorder
|
||||||
- dogsled
|
- dogsled
|
||||||
- dupl
|
- dupl
|
||||||
|
|
@ -86,7 +87,6 @@ linters:
|
||||||
- errname
|
- errname
|
||||||
- errorlint
|
- errorlint
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- exportloopref
|
|
||||||
- forcetypeassert
|
- forcetypeassert
|
||||||
- gocognit
|
- gocognit
|
||||||
- gocritic
|
- gocritic
|
||||||
|
|
|
||||||
90
vendor/github.com/etkecc/go-psd/client.go
generated
vendored
90
vendor/github.com/etkecc/go-psd/client.go
generated
vendored
|
|
@ -7,71 +7,111 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"runtime/debug"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/golang-lru/v2/expirable"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = func() string {
|
// DefaultUserAgent is the default user agent used by the client
|
||||||
if info, ok := debug.ReadBuildInfo(); ok {
|
const DefaultUserAgent = "Go-PSD-client/v0.0.0"
|
||||||
for _, setting := range info.Settings {
|
|
||||||
if setting.Key == "vcs.revision" {
|
|
||||||
return setting.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "0.0.0-unknown"
|
|
||||||
}()
|
|
||||||
|
|
||||||
|
// Client is the client to interact with the Prometheus Service Discovery HTTP API
|
||||||
type Client struct {
|
type Client struct {
|
||||||
url *url.URL
|
url *url.URL
|
||||||
|
cache *expirable.LRU[string, cacheValue]
|
||||||
login string
|
login string
|
||||||
password string
|
password string
|
||||||
|
userAgent string
|
||||||
|
}
|
||||||
|
|
||||||
|
type cacheValue struct {
|
||||||
|
data []byte
|
||||||
|
etag string
|
||||||
|
cachedAt string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new PSD client
|
// NewClient returns a new PSD client
|
||||||
func NewClient(baseURL, login, password string) *Client {
|
func NewClient(baseURL, login, password string, userAgentOverride ...string) *Client {
|
||||||
uri, err := url.Parse(baseURL)
|
uri, err := url.Parse(baseURL)
|
||||||
if err != nil || login == "" || password == "" {
|
if err != nil || login == "" || password == "" {
|
||||||
return &Client{}
|
return &Client{}
|
||||||
}
|
}
|
||||||
return &Client{url: uri, login: login, password: password}
|
|
||||||
|
cache := expirable.NewLRU[string, cacheValue](1000, nil, 5*time.Minute)
|
||||||
|
userAgent := DefaultUserAgent
|
||||||
|
if len(userAgentOverride) > 0 {
|
||||||
|
userAgent = userAgentOverride[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
url: uri,
|
||||||
|
cache: cache,
|
||||||
|
login: login,
|
||||||
|
password: password,
|
||||||
|
userAgent: userAgent,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWithContext returns the list of targets for the given identifier using the given context
|
// GetWithContext returns the list of targets for the given identifier using the given context
|
||||||
func (p *Client) GetWithContext(ctx context.Context, identifier string) ([]*Target, error) {
|
func (p *Client) GetWithContext(ctx context.Context, identifier string, jobOverride ...string) (Items, error) {
|
||||||
if p.url == nil {
|
if p.url == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
cloned := *p.url
|
cloned := *p.url
|
||||||
uri := cloned.JoinPath("/node/" + identifier)
|
job := "node"
|
||||||
|
if len(jobOverride) > 0 {
|
||||||
|
job = jobOverride[0]
|
||||||
|
}
|
||||||
|
uri := cloned.JoinPath("/" + job + "/" + identifier)
|
||||||
|
urlTarget := uri.String()
|
||||||
|
cachedData, cached := p.cache.Get(urlTarget)
|
||||||
|
|
||||||
childCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
childCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(childCtx, http.MethodGet, uri.String(), http.NoBody)
|
req, err := http.NewRequestWithContext(childCtx, http.MethodGet, urlTarget, http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.SetBasicAuth(p.login, p.password)
|
req.SetBasicAuth(p.login, p.password)
|
||||||
req.Header.Set("User-Agent", "Go-PSD-client/"+version)
|
if cached {
|
||||||
|
req.Header.Set("If-Modified-Since", cachedData.cachedAt)
|
||||||
|
req.Header.Set("If-None-Match", cachedData.etag)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("User-Agent", p.userAgent)
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
if resp.StatusCode != http.StatusOK {
|
var datab []byte
|
||||||
if resp.StatusCode == http.StatusGone { // not found, to distinguish from reverse proxy 404 error
|
if resp.StatusCode == http.StatusNotModified && cached {
|
||||||
|
datab = cachedData.data
|
||||||
|
} else if resp.StatusCode == http.StatusGone { // not found, to distinguish from reverse proxy 404 error
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
} else if resp.StatusCode != http.StatusOK {
|
||||||
|
err = fmt.Errorf("HTTP error: %s", resp.Status) //nolint:goerr113 // that's ok
|
||||||
err = fmt.Errorf("%s", resp.Status) //nolint:goerr113 // that's ok
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
datab, err := io.ReadAll(resp.Body)
|
|
||||||
|
if datab == nil {
|
||||||
|
datab, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var psd []*Target
|
|
||||||
|
lastModified := resp.Header.Get("Last-Modified")
|
||||||
|
if lastModified == "" {
|
||||||
|
lastModified = time.Now().Format(http.TimeFormat)
|
||||||
|
}
|
||||||
|
p.cache.Add(urlTarget, cacheValue{
|
||||||
|
data: datab,
|
||||||
|
etag: resp.Header.Get("ETag"),
|
||||||
|
cachedAt: lastModified,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var psd []*Item
|
||||||
err = json.Unmarshal(datab, &psd)
|
err = json.Unmarshal(datab, &psd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -81,6 +121,6 @@ func (p *Client) GetWithContext(ctx context.Context, identifier string) ([]*Targ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the list of targets for the given identifier
|
// Get returns the list of targets for the given identifier
|
||||||
func (p *Client) Get(identifier string) ([]*Target, error) {
|
func (p *Client) Get(identifier string) (Items, error) {
|
||||||
return p.GetWithContext(context.Background(), identifier)
|
return p.GetWithContext(context.Background(), identifier)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
91
vendor/github.com/etkecc/go-psd/model.go
generated
vendored
Normal file
91
vendor/github.com/etkecc/go-psd/model.go
generated
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
package psd
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Item is a struct that represents a single set of targets in Prometheus Service Discovery
|
||||||
|
type Item struct {
|
||||||
|
Targets []string `json:"targets"`
|
||||||
|
Labels map[string]string `json:"labels"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDomain returns the domain of the target
|
||||||
|
func (i *Item) GetDomain() string {
|
||||||
|
return i.Labels["domain"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Items is a slice of Prometheus Service Discovery items
|
||||||
|
type Items []*Item
|
||||||
|
|
||||||
|
// GetDomains - get domains from service discovery labels
|
||||||
|
func (items Items) GetDomains() []string {
|
||||||
|
if len(items) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
domainsMap := map[string]struct{}{}
|
||||||
|
for _, item := range items {
|
||||||
|
domain := item.GetDomain()
|
||||||
|
if domain == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := domainsMap[domain]; !ok {
|
||||||
|
domainsMap[domain] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
domains := make([]string, 0, len(domainsMap))
|
||||||
|
for domain := range domainsMap {
|
||||||
|
domains = append(domains, domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domains
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains - check if target exists in service discovery items
|
||||||
|
func (items Items) Contains(needle string) bool {
|
||||||
|
for _, item := range items {
|
||||||
|
for _, target := range item.Targets {
|
||||||
|
if target == needle {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsFederation - check if service discovery items contain matrix federation endpoint
|
||||||
|
func (items Items) ContainsFederation() bool {
|
||||||
|
for _, item := range items {
|
||||||
|
for _, target := range item.Targets {
|
||||||
|
if strings.HasSuffix(target, "_matrix/federation/v1/version") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsDelegation - check if service discovery items contain matrix server delegation endpoint
|
||||||
|
func (items Items) ContainsDelegation() bool {
|
||||||
|
for _, item := range items {
|
||||||
|
for _, target := range item.Targets {
|
||||||
|
if strings.HasSuffix(target, "/.well-known/matrix/server") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsMSC1929 - check if service discovery items contain matrix MSC1929 endpoint
|
||||||
|
func (items Items) ContainsMSC1929() bool {
|
||||||
|
for _, item := range items {
|
||||||
|
for _, target := range item.Targets {
|
||||||
|
if strings.HasSuffix(target, "/.well-known/matrix/support") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
12
vendor/github.com/etkecc/go-psd/target.go
generated
vendored
12
vendor/github.com/etkecc/go-psd/target.go
generated
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
package psd
|
|
||||||
|
|
||||||
// Target is a struct that represents a single set of targets in Prometheus Service Discovery
|
|
||||||
type Target struct {
|
|
||||||
Targets []string `json:"targets"`
|
|
||||||
Labels map[string]string `json:"labels"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDomain returns the domain of the target
|
|
||||||
func (t *Target) GetDomain() string {
|
|
||||||
return t.Labels["domain"]
|
|
||||||
}
|
|
||||||
8
vendor/github.com/etkecc/go-secgen/password.go
generated
vendored
8
vendor/github.com/etkecc/go-secgen/password.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package secgen
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -28,3 +29,10 @@ func Base64Bytes(length int) string {
|
||||||
rand.Read(randomBytes) //nolint:errcheck // nothing could be done anyway
|
rand.Read(randomBytes) //nolint:errcheck // nothing could be done anyway
|
||||||
return base64.StdEncoding.EncodeToString(randomBytes)
|
return base64.StdEncoding.EncodeToString(randomBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HexBytes generates secure bytes with the given length and returns it as a hex string
|
||||||
|
func HexBytes(length int) string {
|
||||||
|
randomBytes := make([]byte, length)
|
||||||
|
rand.Read(randomBytes) //nolint:errcheck // nothing could be done anyway
|
||||||
|
return hex.EncodeToString(randomBytes)
|
||||||
|
}
|
||||||
|
|
|
||||||
8
vendor/github.com/etkecc/go-trysmtp/client.go
generated
vendored
8
vendor/github.com/etkecc/go-trysmtp/client.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package trysmtp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
|
|
@ -50,7 +51,7 @@ func unwrapErrors(errs []error) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf(text.String())
|
return errors.New(text.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func initClient(localname, hostname string) (*smtp.Client, error) {
|
func initClient(localname, hostname string) (*smtp.Client, error) {
|
||||||
|
|
@ -102,7 +103,10 @@ func trySMTP(localname, mxhost, addr string) (*smtp.Client, error) {
|
||||||
return nil, fmt.Errorf("%s: %w", target, err)
|
return nil, fmt.Errorf("%s: %w", target, err)
|
||||||
}
|
}
|
||||||
if ok, _ := conn.Extension("STARTTLS"); ok {
|
if ok, _ := conn.Extension("STARTTLS"); ok {
|
||||||
config := &tls.Config{ServerName: mxhost}
|
config := &tls.Config{
|
||||||
|
ServerName: mxhost,
|
||||||
|
InsecureSkipVerify: true, // we are using InsecureSkipVerify, because invalid SSL certs are too common in email world, alas
|
||||||
|
}
|
||||||
conn.StartTLS(config) //nolint:errcheck // if it doesn't work - we can't do anything anyway
|
conn.StartTLS(config) //nolint:errcheck // if it doesn't work - we can't do anything anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
vendor/github.com/etkecc/go-validator/v2/.golangci.yml
generated
vendored
2
vendor/github.com/etkecc/go-validator/v2/.golangci.yml
generated
vendored
|
|
@ -76,6 +76,7 @@ linters:
|
||||||
- bidichk
|
- bidichk
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- containedctx
|
- containedctx
|
||||||
|
- copyloopvar
|
||||||
- decorder
|
- decorder
|
||||||
- dogsled
|
- dogsled
|
||||||
- dupl
|
- dupl
|
||||||
|
|
@ -86,7 +87,6 @@ linters:
|
||||||
- errname
|
- errname
|
||||||
- errorlint
|
- errorlint
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- exportloopref
|
|
||||||
- forcetypeassert
|
- forcetypeassert
|
||||||
- gocognit
|
- gocognit
|
||||||
- gocritic
|
- gocritic
|
||||||
|
|
|
||||||
1
vendor/github.com/etkecc/go-validator/v2/emails.go
generated
vendored
1
vendor/github.com/etkecc/go-validator/v2/emails.go
generated
vendored
|
|
@ -122,6 +122,7 @@ func (v *V) emailNoSMTP(ctx context.Context, email string, errchan chan error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trysmtp.SMTPAddrs = []string{":25"}
|
||||||
client, err := trysmtp.Connect(v.cfg.Email.From, email)
|
client, err := trysmtp.Connect(v.cfg.Email.From, email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.HasPrefix(err.Error(), "45") {
|
if strings.HasPrefix(err.Error(), "45") {
|
||||||
|
|
|
||||||
2
vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go
generated
vendored
2
vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go
generated
vendored
|
|
@ -21,6 +21,8 @@ var (
|
||||||
SWF = prefix([]byte("CWS"), []byte("FWS"), []byte("ZWS"))
|
SWF = prefix([]byte("CWS"), []byte("FWS"), []byte("ZWS"))
|
||||||
// Torrent has bencoded text in the beginning.
|
// Torrent has bencoded text in the beginning.
|
||||||
Torrent = prefix([]byte("d8:announce"))
|
Torrent = prefix([]byte("d8:announce"))
|
||||||
|
// PAR1 matches a parquet file.
|
||||||
|
Par1 = prefix([]byte{0x50, 0x41, 0x52, 0x31})
|
||||||
)
|
)
|
||||||
|
|
||||||
// Java bytecode and Mach-O binaries share the same magic number.
|
// Java bytecode and Mach-O binaries share the same magic number.
|
||||||
|
|
|
||||||
43
vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go
generated
vendored
43
vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go
generated
vendored
|
|
@ -1,22 +1,14 @@
|
||||||
package magic
|
package magic
|
||||||
|
|
||||||
import "bytes"
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// AVIF matches an AV1 Image File Format still or animated.
|
// AVIF matches an AV1 Image File Format still or animated.
|
||||||
// Wikipedia page seems outdated listing image/avif-sequence for animations.
|
// Wikipedia page seems outdated listing image/avif-sequence for animations.
|
||||||
// https://github.com/AOMediaCodec/av1-avif/issues/59
|
// https://github.com/AOMediaCodec/av1-avif/issues/59
|
||||||
AVIF = ftyp([]byte("avif"), []byte("avis"))
|
AVIF = ftyp([]byte("avif"), []byte("avis"))
|
||||||
// Mp4 matches an MP4 file.
|
|
||||||
Mp4 = ftyp(
|
|
||||||
[]byte("avc1"), []byte("dash"), []byte("iso2"), []byte("iso3"),
|
|
||||||
[]byte("iso4"), []byte("iso5"), []byte("iso6"), []byte("isom"),
|
|
||||||
[]byte("mmp4"), []byte("mp41"), []byte("mp42"), []byte("mp4v"),
|
|
||||||
[]byte("mp71"), []byte("MSNV"), []byte("NDAS"), []byte("NDSC"),
|
|
||||||
[]byte("NSDC"), []byte("NSDH"), []byte("NDSM"), []byte("NDSP"),
|
|
||||||
[]byte("NDSS"), []byte("NDXC"), []byte("NDXH"), []byte("NDXM"),
|
|
||||||
[]byte("NDXP"), []byte("NDXS"), []byte("F4V "), []byte("F4P "),
|
|
||||||
)
|
|
||||||
// ThreeGP matches a 3GPP file.
|
// ThreeGP matches a 3GPP file.
|
||||||
ThreeGP = ftyp(
|
ThreeGP = ftyp(
|
||||||
[]byte("3gp1"), []byte("3gp2"), []byte("3gp3"), []byte("3gp4"),
|
[]byte("3gp1"), []byte("3gp2"), []byte("3gp3"), []byte("3gp4"),
|
||||||
|
|
@ -53,6 +45,17 @@ var (
|
||||||
Heif = ftyp([]byte("mif1"), []byte("heim"), []byte("heis"), []byte("avic"))
|
Heif = ftyp([]byte("mif1"), []byte("heim"), []byte("heis"), []byte("avic"))
|
||||||
// HeifSequence matches a High Efficiency Image File Format (HEIF) file sequence.
|
// HeifSequence matches a High Efficiency Image File Format (HEIF) file sequence.
|
||||||
HeifSequence = ftyp([]byte("msf1"), []byte("hevm"), []byte("hevs"), []byte("avcs"))
|
HeifSequence = ftyp([]byte("msf1"), []byte("hevm"), []byte("hevs"), []byte("avcs"))
|
||||||
|
// Mj2 matches a Motion JPEG 2000 file: https://en.wikipedia.org/wiki/Motion_JPEG_2000.
|
||||||
|
Mj2 = ftyp([]byte("mj2s"), []byte("mjp2"), []byte("MFSM"), []byte("MGSV"))
|
||||||
|
// Dvb matches a Digital Video Broadcasting file: https://dvb.org.
|
||||||
|
// https://cconcolato.github.io/mp4ra/filetype.html
|
||||||
|
// https://github.com/file/file/blob/512840337ead1076519332d24fefcaa8fac36e06/magic/Magdir/animation#L135-L154
|
||||||
|
Dvb = ftyp(
|
||||||
|
[]byte("dby1"), []byte("dsms"), []byte("dts1"), []byte("dts2"),
|
||||||
|
[]byte("dts3"), []byte("dxo "), []byte("dmb1"), []byte("dmpf"),
|
||||||
|
[]byte("drc1"), []byte("dv1a"), []byte("dv1b"), []byte("dv2a"),
|
||||||
|
[]byte("dv2b"), []byte("dv3a"), []byte("dv3b"), []byte("dvr1"),
|
||||||
|
[]byte("dvt1"), []byte("emsg"))
|
||||||
// TODO: add support for remaining video formats at ftyps.com.
|
// TODO: add support for remaining video formats at ftyps.com.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -86,3 +89,21 @@ func QuickTime(raw []byte, _ uint32) bool {
|
||||||
}
|
}
|
||||||
return bytes.Equal(raw[:8], []byte("\x00\x00\x00\x08wide"))
|
return bytes.Equal(raw[:8], []byte("\x00\x00\x00\x08wide"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mp4 detects an .mp4 file. Mp4 detections only does a basic ftyp check.
|
||||||
|
// Mp4 has many registered and unregistered code points so it's hard to keep track
|
||||||
|
// of all. Detection will default on video/mp4 for all ftyp files.
|
||||||
|
// ISO_IEC_14496-12 is the specification for the iso container.
|
||||||
|
func Mp4(raw []byte, _ uint32) bool {
|
||||||
|
if len(raw) < 12 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// ftyps are made out of boxes. The first 4 bytes of the box represent
|
||||||
|
// its size in big-endian uint32. First box is the ftyp box and it is small
|
||||||
|
// in size. Check most significant byte is 0 to filter out false positive
|
||||||
|
// text files that happen to contain the string "ftyp" at index 4.
|
||||||
|
if raw[0] != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return bytes.Equal(raw[4:8], []byte("ftyp"))
|
||||||
|
}
|
||||||
|
|
|
||||||
13
vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go
generated
vendored
13
vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go
generated
vendored
|
|
@ -153,9 +153,6 @@ func ftyp(sigs ...[]byte) Detector {
|
||||||
if len(raw) < 12 {
|
if len(raw) < 12 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !bytes.Equal(raw[4:8], []byte("ftyp")) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, s := range sigs {
|
for _, s := range sigs {
|
||||||
if bytes.Equal(raw[8:12], s) {
|
if bytes.Equal(raw[8:12], s) {
|
||||||
return true
|
return true
|
||||||
|
|
@ -242,3 +239,13 @@ func min(a, b int) int {
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type readBuf []byte
|
||||||
|
|
||||||
|
func (b *readBuf) advance(n int) bool {
|
||||||
|
if n < 0 || len(*b) < n {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
*b = (*b)[n:]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
||||||
45
vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go
generated
vendored
45
vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go
generated
vendored
|
|
@ -5,58 +5,19 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
xlsxSigFiles = [][]byte{
|
|
||||||
[]byte("xl/worksheets/"),
|
|
||||||
[]byte("xl/drawings/"),
|
|
||||||
[]byte("xl/theme/"),
|
|
||||||
[]byte("xl/_rels/"),
|
|
||||||
[]byte("xl/styles.xml"),
|
|
||||||
[]byte("xl/workbook.xml"),
|
|
||||||
[]byte("xl/sharedStrings.xml"),
|
|
||||||
}
|
|
||||||
docxSigFiles = [][]byte{
|
|
||||||
[]byte("word/media/"),
|
|
||||||
[]byte("word/_rels/document.xml.rels"),
|
|
||||||
[]byte("word/document.xml"),
|
|
||||||
[]byte("word/styles.xml"),
|
|
||||||
[]byte("word/fontTable.xml"),
|
|
||||||
[]byte("word/settings.xml"),
|
|
||||||
[]byte("word/numbering.xml"),
|
|
||||||
[]byte("word/header"),
|
|
||||||
[]byte("word/footer"),
|
|
||||||
}
|
|
||||||
pptxSigFiles = [][]byte{
|
|
||||||
[]byte("ppt/slides/"),
|
|
||||||
[]byte("ppt/media/"),
|
|
||||||
[]byte("ppt/slideLayouts/"),
|
|
||||||
[]byte("ppt/theme/"),
|
|
||||||
[]byte("ppt/slideMasters/"),
|
|
||||||
[]byte("ppt/tags/"),
|
|
||||||
[]byte("ppt/notesMasters/"),
|
|
||||||
[]byte("ppt/_rels/"),
|
|
||||||
[]byte("ppt/handoutMasters/"),
|
|
||||||
[]byte("ppt/notesSlides/"),
|
|
||||||
[]byte("ppt/presentation.xml"),
|
|
||||||
[]byte("ppt/tableStyles.xml"),
|
|
||||||
[]byte("ppt/presProps.xml"),
|
|
||||||
[]byte("ppt/viewProps.xml"),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Xlsx matches a Microsoft Excel 2007 file.
|
// Xlsx matches a Microsoft Excel 2007 file.
|
||||||
func Xlsx(raw []byte, limit uint32) bool {
|
func Xlsx(raw []byte, limit uint32) bool {
|
||||||
return zipContains(raw, xlsxSigFiles...)
|
return zipContains(raw, []byte("xl/"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Docx matches a Microsoft Word 2007 file.
|
// Docx matches a Microsoft Word 2007 file.
|
||||||
func Docx(raw []byte, limit uint32) bool {
|
func Docx(raw []byte, limit uint32) bool {
|
||||||
return zipContains(raw, docxSigFiles...)
|
return zipContains(raw, []byte("word/"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pptx matches a Microsoft PowerPoint 2007 file.
|
// Pptx matches a Microsoft PowerPoint 2007 file.
|
||||||
func Pptx(raw []byte, limit uint32) bool {
|
func Pptx(raw []byte, limit uint32) bool {
|
||||||
return zipContains(raw, pptxSigFiles...)
|
return zipContains(raw, []byte("ppt/"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ole matches an Open Linking and Embedding file.
|
// Ole matches an Open Linking and Embedding file.
|
||||||
|
|
|
||||||
22
vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go
generated
vendored
22
vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go
generated
vendored
|
|
@ -1,12 +1,28 @@
|
||||||
package magic
|
package magic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A bufio.Reader pool to alleviate problems with memory allocations.
|
||||||
|
var readerPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
// Initiate with empty source reader.
|
||||||
|
return bufio.NewReader(nil)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func newReader(r io.Reader) *bufio.Reader {
|
||||||
|
br := readerPool.Get().(*bufio.Reader)
|
||||||
|
br.Reset(r)
|
||||||
|
return br
|
||||||
|
}
|
||||||
|
|
||||||
// Csv matches a comma-separated values file.
|
// Csv matches a comma-separated values file.
|
||||||
func Csv(raw []byte, limit uint32) bool {
|
func Csv(raw []byte, limit uint32) bool {
|
||||||
return sv(raw, ',', limit)
|
return sv(raw, ',', limit)
|
||||||
|
|
@ -18,7 +34,11 @@ func Tsv(raw []byte, limit uint32) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sv(in []byte, comma rune, limit uint32) bool {
|
func sv(in []byte, comma rune, limit uint32) bool {
|
||||||
r := csv.NewReader(bytes.NewReader(dropLastLine(in, limit)))
|
in = dropLastLine(in, limit)
|
||||||
|
|
||||||
|
br := newReader(bytes.NewReader(in))
|
||||||
|
defer readerPool.Put(br)
|
||||||
|
r := csv.NewReader(br)
|
||||||
r.Comma = comma
|
r.Comma = comma
|
||||||
r.ReuseRecord = true
|
r.ReuseRecord = true
|
||||||
r.LazyQuotes = true
|
r.LazyQuotes = true
|
||||||
|
|
|
||||||
87
vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go
generated
vendored
87
vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go
generated
vendored
|
|
@ -42,50 +42,71 @@ func Zip(raw []byte, limit uint32) bool {
|
||||||
|
|
||||||
// Jar matches a Java archive file.
|
// Jar matches a Java archive file.
|
||||||
func Jar(raw []byte, limit uint32) bool {
|
func Jar(raw []byte, limit uint32) bool {
|
||||||
return zipContains(raw, []byte("META-INF/MANIFEST.MF"))
|
return zipContains(raw, []byte("META-INF/MANIFEST.MF"), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// zipTokenizer holds the source zip file and scanned index.
|
func zipContains(raw, sig []byte, msoCheck bool) bool {
|
||||||
type zipTokenizer struct {
|
b := readBuf(raw)
|
||||||
in []byte
|
pk := []byte("PK\003\004")
|
||||||
i int // current index
|
if len(b) < 0x1E {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// next returns the next file name from the zip headers.
|
if !b.advance(0x1E) {
|
||||||
// https://web.archive.org/web/20191129114319/https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html
|
return false
|
||||||
func (t *zipTokenizer) next() (fileName []byte) {
|
|
||||||
if t.i > len(t.in) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
in := t.in[t.i:]
|
if bytes.HasPrefix(b, sig) {
|
||||||
// pkSig is the signature of the zip local file header.
|
return true
|
||||||
pkSig := []byte("PK\003\004")
|
|
||||||
pkIndex := bytes.Index(in, pkSig)
|
|
||||||
// 30 is the offset of the file name in the header.
|
|
||||||
fNameOffset := pkIndex + 30
|
|
||||||
// end if signature not found or file name offset outside of file.
|
|
||||||
if pkIndex == -1 || fNameOffset > len(in) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fNameLen := int(binary.LittleEndian.Uint16(in[pkIndex+26 : pkIndex+28]))
|
if msoCheck {
|
||||||
if fNameLen <= 0 || fNameOffset+fNameLen > len(in) {
|
skipFiles := [][]byte{
|
||||||
return
|
[]byte("[Content_Types].xml"),
|
||||||
}
|
[]byte("_rels/.rels"),
|
||||||
t.i += fNameOffset + fNameLen
|
[]byte("docProps"),
|
||||||
return in[fNameOffset : fNameOffset+fNameLen]
|
[]byte("customXml"),
|
||||||
|
[]byte("[trash]"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// zipContains returns true if the zip file headers from in contain any of the paths.
|
hasSkipFile := false
|
||||||
func zipContains(in []byte, paths ...[]byte) bool {
|
for _, sf := range skipFiles {
|
||||||
t := zipTokenizer{in: in}
|
if bytes.HasPrefix(b, sf) {
|
||||||
for tok := t.next(); len(tok) != 0; tok = t.next() {
|
hasSkipFile = true
|
||||||
for p := range paths {
|
break
|
||||||
if bytes.HasPrefix(tok, paths[p]) {
|
}
|
||||||
|
}
|
||||||
|
if !hasSkipFile {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchOffset := binary.LittleEndian.Uint32(raw[18:]) + 49
|
||||||
|
if !b.advance(int(searchOffset)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
nextHeader := bytes.Index(raw[searchOffset:], pk)
|
||||||
|
if !b.advance(nextHeader) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bytes.HasPrefix(b, sig) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
if !b.advance(0x1A) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
nextHeader = bytes.Index(b, pk)
|
||||||
|
if nextHeader == -1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !b.advance(nextHeader + 0x1E) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bytes.HasPrefix(b, sig) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md
generated
vendored
27
vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md
generated
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
## 173 Supported MIME types
|
## 176 Supported MIME types
|
||||||
This file is automatically generated when running tests. Do not edit manually.
|
This file is automatically generated when running tests. Do not edit manually.
|
||||||
|
|
||||||
Extension | MIME type | Aliases
|
Extension | MIME type | Aliases
|
||||||
|
|
@ -75,21 +75,28 @@ Extension | MIME type | Aliases
|
||||||
**.au** | audio/basic | -
|
**.au** | audio/basic | -
|
||||||
**.mpeg** | video/mpeg | -
|
**.mpeg** | video/mpeg | -
|
||||||
**.mov** | video/quicktime | -
|
**.mov** | video/quicktime | -
|
||||||
**.mqv** | video/quicktime | -
|
|
||||||
**.mp4** | video/mp4 | -
|
**.mp4** | video/mp4 | -
|
||||||
**.webm** | video/webm | audio/webm
|
**.avif** | image/avif | -
|
||||||
**.3gp** | video/3gpp | video/3gp, audio/3gpp
|
**.3gp** | video/3gpp | video/3gp, audio/3gpp
|
||||||
**.3g2** | video/3gpp2 | video/3g2, audio/3gpp2
|
**.3g2** | video/3gpp2 | video/3g2, audio/3gpp2
|
||||||
|
**.mp4** | audio/mp4 | audio/x-m4a, audio/x-mp4a
|
||||||
|
**.mqv** | video/quicktime | -
|
||||||
|
**.m4a** | audio/x-m4a | -
|
||||||
|
**.m4v** | video/x-m4v | -
|
||||||
|
**.heic** | image/heic | -
|
||||||
|
**.heic** | image/heic-sequence | -
|
||||||
|
**.heif** | image/heif | -
|
||||||
|
**.heif** | image/heif-sequence | -
|
||||||
|
**.mj2** | video/mj2 | -
|
||||||
|
**.dvb** | video/vnd.dvb.file | -
|
||||||
|
**.webm** | video/webm | audio/webm
|
||||||
**.avi** | video/x-msvideo | video/avi, video/msvideo
|
**.avi** | video/x-msvideo | video/avi, video/msvideo
|
||||||
**.flv** | video/x-flv | -
|
**.flv** | video/x-flv | -
|
||||||
**.mkv** | video/x-matroska | -
|
**.mkv** | video/x-matroska | -
|
||||||
**.asf** | video/x-ms-asf | video/asf, video/x-ms-wmv
|
**.asf** | video/x-ms-asf | video/asf, video/x-ms-wmv
|
||||||
**.aac** | audio/aac | -
|
**.aac** | audio/aac | -
|
||||||
**.voc** | audio/x-unknown | -
|
**.voc** | audio/x-unknown | -
|
||||||
**.mp4** | audio/mp4 | audio/x-m4a, audio/x-mp4a
|
|
||||||
**.m4a** | audio/x-m4a | -
|
|
||||||
**.m3u** | application/vnd.apple.mpegurl | audio/mpegurl
|
**.m3u** | application/vnd.apple.mpegurl | audio/mpegurl
|
||||||
**.m4v** | video/x-m4v | -
|
|
||||||
**.rmvb** | application/vnd.rn-realmedia-vbr | -
|
**.rmvb** | application/vnd.rn-realmedia-vbr | -
|
||||||
**.gz** | application/gzip | application/x-gzip, application/x-gunzip, application/gzipped, application/gzip-compressed, application/x-gzip-compressed, gzip/document
|
**.gz** | application/gzip | application/x-gzip, application/x-gunzip, application/gzipped, application/gzip-compressed, application/x-gzip-compressed, gzip/document
|
||||||
**.class** | application/x-java-applet | -
|
**.class** | application/x-java-applet | -
|
||||||
|
|
@ -118,10 +125,6 @@ Extension | MIME type | Aliases
|
||||||
**.macho** | application/x-mach-binary | -
|
**.macho** | application/x-mach-binary | -
|
||||||
**.qcp** | audio/qcelp | -
|
**.qcp** | audio/qcelp | -
|
||||||
**.icns** | image/x-icns | -
|
**.icns** | image/x-icns | -
|
||||||
**.heic** | image/heic | -
|
|
||||||
**.heic** | image/heic-sequence | -
|
|
||||||
**.heif** | image/heif | -
|
|
||||||
**.heif** | image/heif-sequence | -
|
|
||||||
**.hdr** | image/vnd.radiance | -
|
**.hdr** | image/vnd.radiance | -
|
||||||
**.mrc** | application/marc | -
|
**.mrc** | application/marc | -
|
||||||
**.mdb** | application/x-msaccess | -
|
**.mdb** | application/x-msaccess | -
|
||||||
|
|
@ -138,13 +141,13 @@ Extension | MIME type | Aliases
|
||||||
**.pat** | image/x-gimp-pat | -
|
**.pat** | image/x-gimp-pat | -
|
||||||
**.gbr** | image/x-gimp-gbr | -
|
**.gbr** | image/x-gimp-gbr | -
|
||||||
**.glb** | model/gltf-binary | -
|
**.glb** | model/gltf-binary | -
|
||||||
**.avif** | image/avif | -
|
|
||||||
**.cab** | application/x-installshield | -
|
**.cab** | application/x-installshield | -
|
||||||
**.jxr** | image/jxr | image/vnd.ms-photo
|
**.jxr** | image/jxr | image/vnd.ms-photo
|
||||||
|
**.parquet** | application/vnd.apache.parquet | application/x-parquet
|
||||||
**.txt** | text/plain | -
|
**.txt** | text/plain | -
|
||||||
**.html** | text/html | -
|
**.html** | text/html | -
|
||||||
**.svg** | image/svg+xml | -
|
**.svg** | image/svg+xml | -
|
||||||
**.xml** | text/xml | -
|
**.xml** | text/xml | application/xml
|
||||||
**.rss** | application/rss+xml | text/rss
|
**.rss** | application/rss+xml | text/rss
|
||||||
**.atom** | application/atom+xml | -
|
**.atom** | application/atom+xml | -
|
||||||
**.x3d** | model/x3d+xml | -
|
**.x3d** | model/x3d+xml | -
|
||||||
|
|
|
||||||
24
vendor/github.com/gabriel-vasile/mimetype/tree.go
generated
vendored
24
vendor/github.com/gabriel-vasile/mimetype/tree.go
generated
vendored
|
|
@ -18,14 +18,13 @@ import (
|
||||||
var root = newMIME("application/octet-stream", "",
|
var root = newMIME("application/octet-stream", "",
|
||||||
func([]byte, uint32) bool { return true },
|
func([]byte, uint32) bool { return true },
|
||||||
xpm, sevenZ, zip, pdf, fdf, ole, ps, psd, p7s, ogg, png, jpg, jxl, jp2, jpx,
|
xpm, sevenZ, zip, pdf, fdf, ole, ps, psd, p7s, ogg, png, jpg, jxl, jp2, jpx,
|
||||||
jpm, jxs, gif, webp, exe, elf, ar, tar, xar, bz2, fits, tiff, bmp, ico, mp3, flac,
|
jpm, jxs, gif, webp, exe, elf, ar, tar, xar, bz2, fits, tiff, bmp, ico, mp3,
|
||||||
midi, ape, musePack, amr, wav, aiff, au, mpeg, quickTime, mqv, mp4, webM,
|
flac, midi, ape, musePack, amr, wav, aiff, au, mpeg, quickTime, mp4, webM,
|
||||||
threeGP, threeG2, avi, flv, mkv, asf, aac, voc, aMp4, m4a, m3u, m4v, rmvb,
|
avi, flv, mkv, asf, aac, voc, m3u, rmvb, gzip, class, swf, crx, ttf, woff,
|
||||||
gzip, class, swf, crx, ttf, woff, woff2, otf, ttc, eot, wasm, shx, dbf, dcm, rar,
|
woff2, otf, ttc, eot, wasm, shx, dbf, dcm, rar, djvu, mobi, lit, bpg,
|
||||||
djvu, mobi, lit, bpg, sqlite3, dwg, nes, lnk, macho, qcp, icns, heic,
|
sqlite3, dwg, nes, lnk, macho, qcp, icns, hdr, mrc, mdb, accdb, zstd, cab,
|
||||||
heicSeq, heif, heifSeq, hdr, mrc, mdb, accdb, zstd, cab, rpm, xz, lzip,
|
rpm, xz, lzip, torrent, cpio, tzif, xcf, pat, gbr, glb, cabIS, jxr, parquet,
|
||||||
torrent, cpio, tzif, xcf, pat, gbr, glb, avif, cabIS, jxr,
|
// Keep text last because it is the slowest check.
|
||||||
// Keep text last because it is the slowest check
|
|
||||||
text,
|
text,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -77,7 +76,8 @@ var (
|
||||||
oggAudio = newMIME("audio/ogg", ".oga", magic.OggAudio)
|
oggAudio = newMIME("audio/ogg", ".oga", magic.OggAudio)
|
||||||
oggVideo = newMIME("video/ogg", ".ogv", magic.OggVideo)
|
oggVideo = newMIME("video/ogg", ".ogv", magic.OggVideo)
|
||||||
text = newMIME("text/plain", ".txt", magic.Text, html, svg, xml, php, js, lua, perl, python, json, ndJSON, rtf, srt, tcl, csv, tsv, vCard, iCalendar, warc, vtt)
|
text = newMIME("text/plain", ".txt", magic.Text, html, svg, xml, php, js, lua, perl, python, json, ndJSON, rtf, srt, tcl, csv, tsv, vCard, iCalendar, warc, vtt)
|
||||||
xml = newMIME("text/xml", ".xml", magic.XML, rss, atom, x3d, kml, xliff, collada, gml, gpx, tcx, amf, threemf, xfdf, owl2)
|
xml = newMIME("text/xml", ".xml", magic.XML, rss, atom, x3d, kml, xliff, collada, gml, gpx, tcx, amf, threemf, xfdf, owl2).
|
||||||
|
alias("application/xml")
|
||||||
json = newMIME("application/json", ".json", magic.JSON, geoJSON, har)
|
json = newMIME("application/json", ".json", magic.JSON, geoJSON, har)
|
||||||
har = newMIME("application/json", ".har", magic.HAR)
|
har = newMIME("application/json", ".har", magic.HAR)
|
||||||
csv = newMIME("text/csv", ".csv", magic.Csv)
|
csv = newMIME("text/csv", ".csv", magic.Csv)
|
||||||
|
|
@ -161,7 +161,9 @@ var (
|
||||||
m3u = newMIME("application/vnd.apple.mpegurl", ".m3u", magic.M3u).
|
m3u = newMIME("application/vnd.apple.mpegurl", ".m3u", magic.M3u).
|
||||||
alias("audio/mpegurl")
|
alias("audio/mpegurl")
|
||||||
m4v = newMIME("video/x-m4v", ".m4v", magic.M4v)
|
m4v = newMIME("video/x-m4v", ".m4v", magic.M4v)
|
||||||
mp4 = newMIME("video/mp4", ".mp4", magic.Mp4)
|
mj2 = newMIME("video/mj2", ".mj2", magic.Mj2)
|
||||||
|
dvb = newMIME("video/vnd.dvb.file", ".dvb", magic.Dvb)
|
||||||
|
mp4 = newMIME("video/mp4", ".mp4", magic.Mp4, avif, threeGP, threeG2, aMp4, mqv, m4a, m4v, heic, heicSeq, heif, heifSeq, mj2, dvb)
|
||||||
webM = newMIME("video/webm", ".webm", magic.WebM).
|
webM = newMIME("video/webm", ".webm", magic.WebM).
|
||||||
alias("audio/webm")
|
alias("audio/webm")
|
||||||
mpeg = newMIME("video/mpeg", ".mpeg", magic.Mpeg)
|
mpeg = newMIME("video/mpeg", ".mpeg", magic.Mpeg)
|
||||||
|
|
@ -257,4 +259,6 @@ var (
|
||||||
xfdf = newMIME("application/vnd.adobe.xfdf", ".xfdf", magic.Xfdf)
|
xfdf = newMIME("application/vnd.adobe.xfdf", ".xfdf", magic.Xfdf)
|
||||||
glb = newMIME("model/gltf-binary", ".glb", magic.Glb)
|
glb = newMIME("model/gltf-binary", ".glb", magic.Glb)
|
||||||
jxr = newMIME("image/jxr", ".jxr", magic.Jxr).alias("image/vnd.ms-photo")
|
jxr = newMIME("image/jxr", ".jxr", magic.Jxr).alias("image/vnd.ms-photo")
|
||||||
|
parquet = newMIME("application/vnd.apache.parquet", ".parquet", magic.Par1).
|
||||||
|
alias("application/x-parquet")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
51
vendor/github.com/getsentry/sentry-go/CHANGELOG.md
generated
vendored
51
vendor/github.com/getsentry/sentry-go/CHANGELOG.md
generated
vendored
|
|
@ -1,5 +1,56 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.29.1
|
||||||
|
|
||||||
|
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.29.1.
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Correlate errors to the current trace ([#886](https://github.com/getsentry/sentry-go/pull/886))
|
||||||
|
- Set the trace context when the transaction finishes ([#888](https://github.com/getsentry/sentry-go/pull/888))
|
||||||
|
|
||||||
|
## 0.29.0
|
||||||
|
|
||||||
|
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.29.0.
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
- Remove the `sentrymartini` integration ([#861](https://github.com/getsentry/sentry-go/pull/861))
|
||||||
|
- The `WrapResponseWriter` has been moved from the `sentryhttp` package to the `internal/httputils` package. If you've imported it previosuly, you'll need to copy the implementation in your project. ([#871](https://github.com/getsentry/sentry-go/pull/871))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Add new convenience methods to continue a trace and propagate tracing headers for error-only use cases. ([#862](https://github.com/getsentry/sentry-go/pull/862))
|
||||||
|
|
||||||
|
If you are not using one of our integrations, you can manually continue an incoming trace by using `sentry.ContinueTrace()` by providing the `sentry-trace` and `baggage` header received from a downstream SDK.
|
||||||
|
|
||||||
|
```go
|
||||||
|
hub := sentry.CurrentHub()
|
||||||
|
sentry.ContinueTrace(hub, r.Header.Get(sentry.SentryTraceHeader), r.Header.Get(sentry.SentryBaggageHeader)),
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use `hub.GetTraceparent()` and `hub.GetBaggage()` to fetch the necessary header values for outgoing HTTP requests.
|
||||||
|
|
||||||
|
```go
|
||||||
|
hub := sentry.GetHubFromContext(ctx)
|
||||||
|
req, _ := http.NewRequest("GET", "http://localhost:3000", nil)
|
||||||
|
req.Header.Add(sentry.SentryTraceHeader, hub.GetTraceparent())
|
||||||
|
req.Header.Add(sentry.SentryBaggageHeader, hub.GetBaggage())
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Initialize `HTTPTransport.limit` if `nil` ([#844](https://github.com/getsentry/sentry-go/pull/844))
|
||||||
|
- Fix `sentry.StartTransaction()` returning a transaction with an outdated context on existing transactions ([#854](https://github.com/getsentry/sentry-go/pull/854))
|
||||||
|
- Treat `Proxy-Authorization` as a sensitive header ([#859](https://github.com/getsentry/sentry-go/pull/859))
|
||||||
|
- Add support for the `http.Hijacker` interface to the `sentrynegroni` package ([#871](https://github.com/getsentry/sentry-go/pull/871))
|
||||||
|
- Go version >= 1.23: Use value from `http.Request.Pattern` for HTTP transaction names when using `sentryhttp` & `sentrynegroni` ([#875](https://github.com/getsentry/sentry-go/pull/875))
|
||||||
|
- Go version >= 1.21: Fix closure functions name grouping ([#877](https://github.com/getsentry/sentry-go/pull/877))
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
|
||||||
|
- Collect `span` origins ([#849](https://github.com/getsentry/sentry-go/pull/849))
|
||||||
|
|
||||||
## 0.28.1
|
## 0.28.1
|
||||||
|
|
||||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.28.1.
|
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.28.1.
|
||||||
|
|
|
||||||
1
vendor/github.com/getsentry/sentry-go/README.md
generated
vendored
1
vendor/github.com/getsentry/sentry-go/README.md
generated
vendored
|
|
@ -77,7 +77,6 @@ checkout the official documentation:
|
||||||
- [fasthttp](https://docs.sentry.io/platforms/go/guides/fasthttp/)
|
- [fasthttp](https://docs.sentry.io/platforms/go/guides/fasthttp/)
|
||||||
- [gin](https://docs.sentry.io/platforms/go/guides/gin/)
|
- [gin](https://docs.sentry.io/platforms/go/guides/gin/)
|
||||||
- [iris](https://docs.sentry.io/platforms/go/guides/iris/)
|
- [iris](https://docs.sentry.io/platforms/go/guides/iris/)
|
||||||
- [martini](https://docs.sentry.io/platforms/go/guides/martini/)
|
|
||||||
- [negroni](https://docs.sentry.io/platforms/go/guides/negroni/)
|
- [negroni](https://docs.sentry.io/platforms/go/guides/negroni/)
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
|
||||||
4
vendor/github.com/getsentry/sentry-go/client.go
generated
vendored
4
vendor/github.com/getsentry/sentry-go/client.go
generated
vendored
|
|
@ -90,7 +90,7 @@ type EventProcessor func(event *Event, hint *EventHint) *Event
|
||||||
// ApplyToEvent changes an event based on external data and/or
|
// ApplyToEvent changes an event based on external data and/or
|
||||||
// an event hint.
|
// an event hint.
|
||||||
type EventModifier interface {
|
type EventModifier interface {
|
||||||
ApplyToEvent(event *Event, hint *EventHint) *Event
|
ApplyToEvent(event *Event, hint *EventHint, client *Client) *Event
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalEventProcessors []EventProcessor
|
var globalEventProcessors []EventProcessor
|
||||||
|
|
@ -685,7 +685,7 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope != nil {
|
if scope != nil {
|
||||||
event = scope.ApplyToEvent(event, hint)
|
event = scope.ApplyToEvent(event, hint, client)
|
||||||
if event == nil {
|
if event == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go
generated
vendored
59
vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go
generated
vendored
|
|
@ -39,8 +39,6 @@ func DynamicSamplingContextFromHeader(header []byte) (DynamicSamplingContext, er
|
||||||
}
|
}
|
||||||
|
|
||||||
func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {
|
func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {
|
||||||
entries := map[string]string{}
|
|
||||||
|
|
||||||
hub := hubFromContext(span.Context())
|
hub := hubFromContext(span.Context())
|
||||||
scope := hub.Scope()
|
scope := hub.Scope()
|
||||||
client := hub.Client()
|
client := hub.Client()
|
||||||
|
|
@ -52,6 +50,8 @@ func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entries := make(map[string]string)
|
||||||
|
|
||||||
if traceID := span.TraceID.String(); traceID != "" {
|
if traceID := span.TraceID.String(); traceID != "" {
|
||||||
entries["trace_id"] = traceID
|
entries["trace_id"] = traceID
|
||||||
}
|
}
|
||||||
|
|
@ -78,20 +78,9 @@ func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if userSegment := scope.user.Segment; userSegment != "" {
|
entries["sampled"] = strconv.FormatBool(span.Sampled.Bool())
|
||||||
entries["user_segment"] = userSegment
|
|
||||||
}
|
|
||||||
|
|
||||||
if span.Sampled.Bool() {
|
return DynamicSamplingContext{Entries: entries, Frozen: true}
|
||||||
entries["sampled"] = "true"
|
|
||||||
} else {
|
|
||||||
entries["sampled"] = "false"
|
|
||||||
}
|
|
||||||
|
|
||||||
return DynamicSamplingContext{
|
|
||||||
Entries: entries,
|
|
||||||
Frozen: true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DynamicSamplingContext) HasEntries() bool {
|
func (d DynamicSamplingContext) HasEntries() bool {
|
||||||
|
|
@ -121,3 +110,43 @@ func (d DynamicSamplingContext) String() string {
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructs a new DynamicSamplingContext using a scope and client. Accessing
|
||||||
|
// fields on the scope are not thread safe, and this function should only be
|
||||||
|
// called within scope methods.
|
||||||
|
func DynamicSamplingContextFromScope(scope *Scope, client *Client) DynamicSamplingContext {
|
||||||
|
entries := map[string]string{}
|
||||||
|
|
||||||
|
if client == nil || scope == nil {
|
||||||
|
return DynamicSamplingContext{
|
||||||
|
Entries: entries,
|
||||||
|
Frozen: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
propagationContext := scope.propagationContext
|
||||||
|
|
||||||
|
if traceID := propagationContext.TraceID.String(); traceID != "" {
|
||||||
|
entries["trace_id"] = traceID
|
||||||
|
}
|
||||||
|
if sampleRate := client.options.TracesSampleRate; sampleRate != 0 {
|
||||||
|
entries["sample_rate"] = strconv.FormatFloat(sampleRate, 'f', -1, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dsn := client.dsn; dsn != nil {
|
||||||
|
if publicKey := dsn.publicKey; publicKey != "" {
|
||||||
|
entries["public_key"] = publicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if release := client.options.Release; release != "" {
|
||||||
|
entries["release"] = release
|
||||||
|
}
|
||||||
|
if environment := client.options.Environment; environment != "" {
|
||||||
|
entries["environment"] = environment
|
||||||
|
}
|
||||||
|
|
||||||
|
return DynamicSamplingContext{
|
||||||
|
Entries: entries,
|
||||||
|
Frozen: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
29
vendor/github.com/getsentry/sentry-go/hub.go
generated
vendored
29
vendor/github.com/getsentry/sentry-go/hub.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package sentry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -365,6 +366,34 @@ func (hub *Hub) Flush(timeout time.Duration) bool {
|
||||||
return client.Flush(timeout)
|
return client.Flush(timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTraceparent returns the current Sentry traceparent string, to be used as a HTTP header value
|
||||||
|
// or HTML meta tag value.
|
||||||
|
// This function is context aware, as in it either returns the traceparent based
|
||||||
|
// on the current span, or the scope's propagation context.
|
||||||
|
func (hub *Hub) GetTraceparent() string {
|
||||||
|
scope := hub.Scope()
|
||||||
|
|
||||||
|
if scope.span != nil {
|
||||||
|
return scope.span.ToSentryTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s-%s", scope.propagationContext.TraceID, scope.propagationContext.SpanID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBaggage returns the current Sentry baggage string, to be used as a HTTP header value
|
||||||
|
// or HTML meta tag value.
|
||||||
|
// This function is context aware, as in it either returns the baggage based
|
||||||
|
// on the current span or the scope's propagation context.
|
||||||
|
func (hub *Hub) GetBaggage() string {
|
||||||
|
scope := hub.Scope()
|
||||||
|
|
||||||
|
if scope.span != nil {
|
||||||
|
return scope.span.ToBaggage()
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope.propagationContext.DynamicSamplingContext.String()
|
||||||
|
}
|
||||||
|
|
||||||
// HasHubOnContext checks whether Hub instance is bound to a given Context struct.
|
// HasHubOnContext checks whether Hub instance is bound to a given Context struct.
|
||||||
func HasHubOnContext(ctx context.Context) bool {
|
func HasHubOnContext(ctx context.Context) bool {
|
||||||
_, ok := ctx.Value(HubContextKey).(*Hub)
|
_, ok := ctx.Value(HubContextKey).(*Hub)
|
||||||
|
|
|
||||||
1
vendor/github.com/getsentry/sentry-go/interfaces.go
generated
vendored
1
vendor/github.com/getsentry/sentry-go/interfaces.go
generated
vendored
|
|
@ -167,6 +167,7 @@ type Request struct {
|
||||||
|
|
||||||
var sensitiveHeaders = map[string]struct{}{
|
var sensitiveHeaders = map[string]struct{}{
|
||||||
"Authorization": {},
|
"Authorization": {},
|
||||||
|
"Proxy-Authorization": {},
|
||||||
"Cookie": {},
|
"Cookie": {},
|
||||||
"X-Forwarded-For": {},
|
"X-Forwarded-For": {},
|
||||||
"X-Real-Ip": {},
|
"X-Real-Ip": {},
|
||||||
|
|
|
||||||
90
vendor/github.com/getsentry/sentry-go/propagation_context.go
generated
vendored
Normal file
90
vendor/github.com/getsentry/sentry-go/propagation_context.go
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
package sentry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PropagationContext struct {
|
||||||
|
TraceID TraceID `json:"trace_id"`
|
||||||
|
SpanID SpanID `json:"span_id"`
|
||||||
|
ParentSpanID SpanID `json:"parent_span_id"`
|
||||||
|
DynamicSamplingContext DynamicSamplingContext `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PropagationContext) MarshalJSON() ([]byte, error) {
|
||||||
|
type propagationContext PropagationContext
|
||||||
|
var parentSpanID string
|
||||||
|
if p.ParentSpanID != zeroSpanID {
|
||||||
|
parentSpanID = p.ParentSpanID.String()
|
||||||
|
}
|
||||||
|
return json.Marshal(struct {
|
||||||
|
*propagationContext
|
||||||
|
ParentSpanID string `json:"parent_span_id,omitempty"`
|
||||||
|
}{
|
||||||
|
propagationContext: (*propagationContext)(&p),
|
||||||
|
ParentSpanID: parentSpanID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PropagationContext) Map() map[string]interface{} {
|
||||||
|
m := map[string]interface{}{
|
||||||
|
"trace_id": p.TraceID,
|
||||||
|
"span_id": p.SpanID,
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.ParentSpanID != zeroSpanID {
|
||||||
|
m["parent_span_id"] = p.ParentSpanID
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPropagationContext() PropagationContext {
|
||||||
|
p := PropagationContext{}
|
||||||
|
|
||||||
|
if _, err := rand.Read(p.TraceID[:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := rand.Read(p.SpanID[:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func PropagationContextFromHeaders(trace, baggage string) (PropagationContext, error) {
|
||||||
|
p := NewPropagationContext()
|
||||||
|
|
||||||
|
if _, err := rand.Read(p.SpanID[:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTrace := false
|
||||||
|
if trace != "" {
|
||||||
|
if tpc, valid := ParseTraceParentContext([]byte(trace)); valid {
|
||||||
|
hasTrace = true
|
||||||
|
p.TraceID = tpc.TraceID
|
||||||
|
p.ParentSpanID = tpc.ParentSpanID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if baggage != "" {
|
||||||
|
dsc, err := DynamicSamplingContextFromHeader([]byte(baggage))
|
||||||
|
if err != nil {
|
||||||
|
return PropagationContext{}, err
|
||||||
|
}
|
||||||
|
p.DynamicSamplingContext = dsc
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case a sentry-trace header is present but there are no sentry-related
|
||||||
|
// values in the baggage, create an empty, frozen DynamicSamplingContext.
|
||||||
|
if hasTrace && !p.DynamicSamplingContext.HasEntries() {
|
||||||
|
p.DynamicSamplingContext = DynamicSamplingContext{
|
||||||
|
Frozen: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
51
vendor/github.com/getsentry/sentry-go/scope.go
generated
vendored
51
vendor/github.com/getsentry/sentry-go/scope.go
generated
vendored
|
|
@ -43,20 +43,22 @@ type Scope struct {
|
||||||
Overflow() bool
|
Overflow() bool
|
||||||
}
|
}
|
||||||
eventProcessors []EventProcessor
|
eventProcessors []EventProcessor
|
||||||
|
|
||||||
|
propagationContext PropagationContext
|
||||||
|
span *Span
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScope creates a new Scope.
|
// NewScope creates a new Scope.
|
||||||
func NewScope() *Scope {
|
func NewScope() *Scope {
|
||||||
scope := Scope{
|
return &Scope{
|
||||||
breadcrumbs: make([]*Breadcrumb, 0),
|
breadcrumbs: make([]*Breadcrumb, 0),
|
||||||
attachments: make([]*Attachment, 0),
|
attachments: make([]*Attachment, 0),
|
||||||
tags: make(map[string]string),
|
tags: make(map[string]string),
|
||||||
contexts: make(map[string]Context),
|
contexts: make(map[string]Context),
|
||||||
extra: make(map[string]interface{}),
|
extra: make(map[string]interface{}),
|
||||||
fingerprint: make([]string, 0),
|
fingerprint: make([]string, 0),
|
||||||
|
propagationContext: NewPropagationContext(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return &scope
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddBreadcrumb adds new breadcrumb to the current scope
|
// AddBreadcrumb adds new breadcrumb to the current scope
|
||||||
|
|
@ -292,6 +294,22 @@ func (scope *Scope) SetLevel(level Level) {
|
||||||
scope.level = level
|
scope.level = level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPropagationContext sets the propagation context for the current scope.
|
||||||
|
func (scope *Scope) SetPropagationContext(propagationContext PropagationContext) {
|
||||||
|
scope.mu.Lock()
|
||||||
|
defer scope.mu.Unlock()
|
||||||
|
|
||||||
|
scope.propagationContext = propagationContext
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSpan sets a span for the current scope.
|
||||||
|
func (scope *Scope) SetSpan(span *Span) {
|
||||||
|
scope.mu.Lock()
|
||||||
|
defer scope.mu.Unlock()
|
||||||
|
|
||||||
|
scope.span = span
|
||||||
|
}
|
||||||
|
|
||||||
// Clone returns a copy of the current scope with all data copied over.
|
// Clone returns a copy of the current scope with all data copied over.
|
||||||
func (scope *Scope) Clone() *Scope {
|
func (scope *Scope) Clone() *Scope {
|
||||||
scope.mu.RLock()
|
scope.mu.RLock()
|
||||||
|
|
@ -318,6 +336,8 @@ func (scope *Scope) Clone() *Scope {
|
||||||
clone.request = scope.request
|
clone.request = scope.request
|
||||||
clone.requestBody = scope.requestBody
|
clone.requestBody = scope.requestBody
|
||||||
clone.eventProcessors = scope.eventProcessors
|
clone.eventProcessors = scope.eventProcessors
|
||||||
|
clone.propagationContext = scope.propagationContext
|
||||||
|
clone.span = scope.span
|
||||||
return clone
|
return clone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,7 +355,7 @@ func (scope *Scope) AddEventProcessor(processor EventProcessor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyToEvent takes the data from the current scope and attaches it to the event.
|
// ApplyToEvent takes the data from the current scope and attaches it to the event.
|
||||||
func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint) *Event {
|
func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint, client *Client) *Event {
|
||||||
scope.mu.RLock()
|
scope.mu.RLock()
|
||||||
defer scope.mu.RUnlock()
|
defer scope.mu.RUnlock()
|
||||||
|
|
||||||
|
|
@ -379,6 +399,29 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint) *Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event.Contexts == nil {
|
||||||
|
event.Contexts = make(map[string]Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if scope.span != nil {
|
||||||
|
if _, ok := event.Contexts["trace"]; !ok {
|
||||||
|
event.Contexts["trace"] = scope.span.traceContext().Map()
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction := scope.span.GetTransaction()
|
||||||
|
if transaction != nil {
|
||||||
|
event.sdkMetaData.dsc = DynamicSamplingContextFromTransaction(transaction)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event.Contexts["trace"] = scope.propagationContext.Map()
|
||||||
|
|
||||||
|
dsc := scope.propagationContext.DynamicSamplingContext
|
||||||
|
if !dsc.HasEntries() && client != nil {
|
||||||
|
dsc = DynamicSamplingContextFromScope(scope, client)
|
||||||
|
}
|
||||||
|
event.sdkMetaData.dsc = dsc
|
||||||
|
}
|
||||||
|
|
||||||
if len(scope.extra) > 0 {
|
if len(scope.extra) > 0 {
|
||||||
if event.Extra == nil {
|
if event.Extra == nil {
|
||||||
event.Extra = make(map[string]interface{}, len(scope.extra))
|
event.Extra = make(map[string]interface{}, len(scope.extra))
|
||||||
|
|
|
||||||
2
vendor/github.com/getsentry/sentry-go/sentry.go
generated
vendored
2
vendor/github.com/getsentry/sentry-go/sentry.go
generated
vendored
|
|
@ -6,7 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// The version of the SDK.
|
// The version of the SDK.
|
||||||
const SDKVersion = "0.28.1"
|
const SDKVersion = "0.29.1"
|
||||||
|
|
||||||
// apiVersion is the minimum version of the Sentry API compatible with the
|
// apiVersion is the minimum version of the Sentry API compatible with the
|
||||||
// sentry-go SDK.
|
// sentry-go SDK.
|
||||||
|
|
|
||||||
3
vendor/github.com/getsentry/sentry-go/stacktrace.go
generated
vendored
3
vendor/github.com/getsentry/sentry-go/stacktrace.go
generated
vendored
|
|
@ -307,6 +307,9 @@ func createFrames(frames []runtime.Frame) []Frame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix issues grouping errors with the new fully qualified function names
|
||||||
|
// introduced from Go 1.21
|
||||||
|
result = cleanupFunctionNamePrefix(result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
7
vendor/github.com/getsentry/sentry-go/stacktrace_below_go1.21.go
generated
vendored
Normal file
7
vendor/github.com/getsentry/sentry-go/stacktrace_below_go1.21.go
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
//go:build !go1.21
|
||||||
|
|
||||||
|
package sentry
|
||||||
|
|
||||||
|
func cleanupFunctionNamePrefix(f []Frame) []Frame {
|
||||||
|
return f
|
||||||
|
}
|
||||||
25
vendor/github.com/getsentry/sentry-go/stacktrace_go1.21.go
generated
vendored
Normal file
25
vendor/github.com/getsentry/sentry-go/stacktrace_go1.21.go
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
//go:build go1.21
|
||||||
|
|
||||||
|
package sentry
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Walk backwards through the results and for the current function name
|
||||||
|
// remove it's parent function's prefix, leaving only it's actual name. This
|
||||||
|
// fixes issues grouping errors with the new fully qualified function names
|
||||||
|
// introduced from Go 1.21.
|
||||||
|
|
||||||
|
func cleanupFunctionNamePrefix(f []Frame) []Frame {
|
||||||
|
for i := len(f) - 1; i > 0; i-- {
|
||||||
|
name := f[i].Function
|
||||||
|
parentName := f[i-1].Function + "."
|
||||||
|
|
||||||
|
if !strings.HasPrefix(name, parentName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
f[i].Function = name[len(parentName):]
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
85
vendor/github.com/getsentry/sentry-go/tracing.go
generated
vendored
85
vendor/github.com/getsentry/sentry-go/tracing.go
generated
vendored
|
|
@ -18,6 +18,20 @@ const (
|
||||||
SentryBaggageHeader = "baggage"
|
SentryBaggageHeader = "baggage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SpanOrigin indicates what created a trace or a span. See: https://develop.sentry.dev/sdk/performance/trace-origin/
|
||||||
|
type SpanOrigin string
|
||||||
|
|
||||||
|
const (
|
||||||
|
SpanOriginManual = "manual"
|
||||||
|
SpanOriginEcho = "auto.http.echo"
|
||||||
|
SpanOriginFastHTTP = "auto.http.fasthttp"
|
||||||
|
SpanOriginFiber = "auto.http.fiber"
|
||||||
|
SpanOriginGin = "auto.http.gin"
|
||||||
|
SpanOriginStdLib = "auto.http.stdlib"
|
||||||
|
SpanOriginIris = "auto.http.iris"
|
||||||
|
SpanOriginNegroni = "auto.http.negroni"
|
||||||
|
)
|
||||||
|
|
||||||
// A Span is the building block of a Sentry transaction. Spans build up a tree
|
// A Span is the building block of a Sentry transaction. Spans build up a tree
|
||||||
// structure of timed operations. The span tree makes up a transaction event
|
// structure of timed operations. The span tree makes up a transaction event
|
||||||
// that is sent to Sentry when the root span is finished.
|
// that is sent to Sentry when the root span is finished.
|
||||||
|
|
@ -37,6 +51,7 @@ type Span struct { //nolint: maligned // prefer readability over optimal memory
|
||||||
Data map[string]interface{} `json:"data,omitempty"`
|
Data map[string]interface{} `json:"data,omitempty"`
|
||||||
Sampled Sampled `json:"-"`
|
Sampled Sampled `json:"-"`
|
||||||
Source TransactionSource `json:"-"`
|
Source TransactionSource `json:"-"`
|
||||||
|
Origin SpanOrigin `json:"origin,omitempty"`
|
||||||
|
|
||||||
// mu protects concurrent writes to map fields
|
// mu protects concurrent writes to map fields
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
@ -113,11 +128,19 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
|
||||||
parent: parent,
|
parent: parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := rand.Read(span.SpanID[:])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
if hasParent {
|
if hasParent {
|
||||||
span.TraceID = parent.TraceID
|
span.TraceID = parent.TraceID
|
||||||
|
span.ParentSpanID = parent.SpanID
|
||||||
|
span.Origin = parent.Origin
|
||||||
} else {
|
} else {
|
||||||
// Only set the Source if this is a transaction
|
// Only set the Source if this is a transaction
|
||||||
span.Source = SourceCustom
|
span.Source = SourceCustom
|
||||||
|
span.Origin = SpanOriginManual
|
||||||
|
|
||||||
// Implementation note:
|
// Implementation note:
|
||||||
//
|
//
|
||||||
|
|
@ -154,13 +177,6 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := rand.Read(span.SpanID[:])
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if hasParent {
|
|
||||||
span.ParentSpanID = parent.SpanID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply options to override defaults.
|
// Apply options to override defaults.
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
|
|
@ -176,11 +192,15 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
|
||||||
|
|
||||||
span.recorder.record(&span)
|
span.recorder.record(&span)
|
||||||
|
|
||||||
|
clientOptions := span.clientOptions()
|
||||||
|
if clientOptions.EnableTracing {
|
||||||
hub := hubFromContext(ctx)
|
hub := hubFromContext(ctx)
|
||||||
|
if !span.IsTransaction() {
|
||||||
// Update scope so that all events include a trace context, allowing
|
// Push a new scope to stack for non transaction span
|
||||||
// Sentry to correlate errors to transactions/spans.
|
hub.PushScope()
|
||||||
hub.Scope().SetContext("trace", span.traceContext().Map())
|
}
|
||||||
|
hub.Scope().SetSpan(&span)
|
||||||
|
}
|
||||||
|
|
||||||
// Start profiling only if it's a sampled root transaction.
|
// Start profiling only if it's a sampled root transaction.
|
||||||
if span.IsTransaction() && span.Sampled.Bool() {
|
if span.IsTransaction() && span.Sampled.Bool() {
|
||||||
|
|
@ -308,17 +328,21 @@ func (s *Span) ToSentryTrace() string {
|
||||||
// Use this function to propagate the DynamicSamplingContext to a downstream SDK,
|
// Use this function to propagate the DynamicSamplingContext to a downstream SDK,
|
||||||
// either as the value of the "baggage" HTTP header, or as an html "baggage" meta tag.
|
// either as the value of the "baggage" HTTP header, or as an html "baggage" meta tag.
|
||||||
func (s *Span) ToBaggage() string {
|
func (s *Span) ToBaggage() string {
|
||||||
if containingTransaction := s.GetTransaction(); containingTransaction != nil {
|
t := s.GetTransaction()
|
||||||
|
if t == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// In case there is currently no frozen DynamicSamplingContext attached to the transaction,
|
// In case there is currently no frozen DynamicSamplingContext attached to the transaction,
|
||||||
// create one from the properties of the transaction.
|
// create one from the properties of the transaction.
|
||||||
if !s.dynamicSamplingContext.IsFrozen() {
|
if !s.dynamicSamplingContext.IsFrozen() {
|
||||||
// This will return a frozen DynamicSamplingContext.
|
// This will return a frozen DynamicSamplingContext.
|
||||||
s.dynamicSamplingContext = DynamicSamplingContextFromTransaction(containingTransaction)
|
if dsc := DynamicSamplingContextFromTransaction(t); dsc.HasEntries() {
|
||||||
|
t.dynamicSamplingContext = dsc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return containingTransaction.dynamicSamplingContext.String()
|
return t.dynamicSamplingContext.String()
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDynamicSamplingContext sets the given dynamic sampling context on the
|
// SetDynamicSamplingContext sets the given dynamic sampling context on the
|
||||||
|
|
@ -335,6 +359,12 @@ func (s *Span) doFinish() {
|
||||||
s.EndTime = monotonicTimeSince(s.StartTime)
|
s.EndTime = monotonicTimeSince(s.StartTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hub := hubFromContext(s.ctx)
|
||||||
|
if !s.IsTransaction() {
|
||||||
|
// Referenced to StartSpan function that pushes current non-transaction span to scope stack
|
||||||
|
defer hub.PopScope()
|
||||||
|
}
|
||||||
|
|
||||||
if !s.Sampled.Bool() {
|
if !s.Sampled.Bool() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -350,7 +380,6 @@ func (s *Span) doFinish() {
|
||||||
// TODO(tracing): add breadcrumbs
|
// TODO(tracing): add breadcrumbs
|
||||||
// (see https://github.com/getsentry/sentry-python/blob/f6f3525f8812f609/sentry_sdk/tracing.py#L372)
|
// (see https://github.com/getsentry/sentry-python/blob/f6f3525f8812f609/sentry_sdk/tracing.py#L372)
|
||||||
|
|
||||||
hub := hubFromContext(s.ctx)
|
|
||||||
hub.CaptureEvent(event)
|
hub.CaptureEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,7 +563,7 @@ func (s *Span) toEvent() *Event {
|
||||||
s.dynamicSamplingContext = DynamicSamplingContextFromTransaction(s)
|
s.dynamicSamplingContext = DynamicSamplingContextFromTransaction(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
contexts := map[string]Context{}
|
contexts := make(map[string]Context, len(s.contexts)+1)
|
||||||
for k, v := range s.contexts {
|
for k, v := range s.contexts {
|
||||||
contexts[k] = cloneContext(v)
|
contexts[k] = cloneContext(v)
|
||||||
}
|
}
|
||||||
|
|
@ -870,6 +899,25 @@ func WithSpanSampled(sampled Sampled) SpanOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSpanOrigin sets the origin of the span.
|
||||||
|
func WithSpanOrigin(origin SpanOrigin) SpanOption {
|
||||||
|
return func(s *Span) {
|
||||||
|
s.Origin = origin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue a trace based on traceparent and bagge values.
|
||||||
|
// If the SDK is configured with tracing enabled,
|
||||||
|
// this function returns populated SpanOption.
|
||||||
|
// In any other cases, it populates the propagation context on the scope.
|
||||||
|
func ContinueTrace(hub *Hub, traceparent, baggage string) SpanOption {
|
||||||
|
scope := hub.Scope()
|
||||||
|
propagationContext, _ := PropagationContextFromHeaders(traceparent, baggage)
|
||||||
|
scope.SetPropagationContext(propagationContext)
|
||||||
|
|
||||||
|
return ContinueFromHeaders(traceparent, baggage)
|
||||||
|
}
|
||||||
|
|
||||||
// ContinueFromRequest returns a span option that updates the span to continue
|
// ContinueFromRequest returns a span option that updates the span to continue
|
||||||
// an existing trace. If it cannot detect an existing trace in the request, the
|
// an existing trace. If it cannot detect an existing trace in the request, the
|
||||||
// span will be left unchanged.
|
// span will be left unchanged.
|
||||||
|
|
@ -939,6 +987,7 @@ func SpanFromContext(ctx context.Context) *Span {
|
||||||
func StartTransaction(ctx context.Context, name string, options ...SpanOption) *Span {
|
func StartTransaction(ctx context.Context, name string, options ...SpanOption) *Span {
|
||||||
currentTransaction, exists := ctx.Value(spanContextKey{}).(*Span)
|
currentTransaction, exists := ctx.Value(spanContextKey{}).(*Span)
|
||||||
if exists {
|
if exists {
|
||||||
|
currentTransaction.ctx = ctx
|
||||||
return currentTransaction
|
return currentTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
vendor/github.com/getsentry/sentry-go/transport.go
generated
vendored
10
vendor/github.com/getsentry/sentry-go/transport.go
generated
vendored
|
|
@ -357,7 +357,6 @@ func NewHTTPTransport() *HTTPTransport {
|
||||||
transport := HTTPTransport{
|
transport := HTTPTransport{
|
||||||
BufferSize: defaultBufferSize,
|
BufferSize: defaultBufferSize,
|
||||||
Timeout: defaultTimeout,
|
Timeout: defaultTimeout,
|
||||||
limits: make(ratelimit.Map),
|
|
||||||
}
|
}
|
||||||
return &transport
|
return &transport
|
||||||
}
|
}
|
||||||
|
|
@ -550,9 +549,14 @@ func (t *HTTPTransport) worker() {
|
||||||
}
|
}
|
||||||
Logger.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
Logger.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
|
if t.limits == nil {
|
||||||
|
t.limits = make(ratelimit.Map)
|
||||||
|
}
|
||||||
t.limits.Merge(ratelimit.FromResponse(response))
|
t.limits.Merge(ratelimit.FromResponse(response))
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
||||||
// Drain body up to a limit and close it, allowing the
|
// Drain body up to a limit and close it, allowing the
|
||||||
// transport to reuse TCP connections.
|
// transport to reuse TCP connections.
|
||||||
_, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes)
|
_, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes)
|
||||||
|
|
@ -690,6 +694,10 @@ func (t *HTTPSyncTransport) SendEventWithContext(ctx context.Context, event *Eve
|
||||||
}
|
}
|
||||||
|
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
|
if t.limits == nil {
|
||||||
|
t.limits = make(ratelimit.Map)
|
||||||
|
}
|
||||||
|
|
||||||
t.limits.Merge(ratelimit.FromResponse(response))
|
t.limits.Merge(ratelimit.FromResponse(response))
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
||||||
|
|
|
||||||
338
vendor/github.com/hashicorp/golang-lru/v2/expirable/expirable_lru.go
generated
vendored
Normal file
338
vendor/github.com/hashicorp/golang-lru/v2/expirable/expirable_lru.go
generated
vendored
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package expirable
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/golang-lru/v2/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EvictCallback is used to get a callback when a cache entry is evicted
|
||||||
|
type EvictCallback[K comparable, V any] func(key K, value V)
|
||||||
|
|
||||||
|
// LRU implements a thread-safe LRU with expirable entries.
|
||||||
|
type LRU[K comparable, V any] struct {
|
||||||
|
size int
|
||||||
|
evictList *internal.LruList[K, V]
|
||||||
|
items map[K]*internal.Entry[K, V]
|
||||||
|
onEvict EvictCallback[K, V]
|
||||||
|
|
||||||
|
// expirable options
|
||||||
|
mu sync.Mutex
|
||||||
|
ttl time.Duration
|
||||||
|
done chan struct{}
|
||||||
|
|
||||||
|
// buckets for expiration
|
||||||
|
buckets []bucket[K, V]
|
||||||
|
// uint8 because it's number between 0 and numBuckets
|
||||||
|
nextCleanupBucket uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// bucket is a container for holding entries to be expired
|
||||||
|
type bucket[K comparable, V any] struct {
|
||||||
|
entries map[K]*internal.Entry[K, V]
|
||||||
|
newestEntry time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// noEvictionTTL - very long ttl to prevent eviction
|
||||||
|
const noEvictionTTL = time.Hour * 24 * 365 * 10
|
||||||
|
|
||||||
|
// because of uint8 usage for nextCleanupBucket, should not exceed 256.
|
||||||
|
// casting it as uint8 explicitly requires type conversions in multiple places
|
||||||
|
const numBuckets = 100
|
||||||
|
|
||||||
|
// NewLRU returns a new thread-safe cache with expirable entries.
|
||||||
|
//
|
||||||
|
// Size parameter set to 0 makes cache of unlimited size, e.g. turns LRU mechanism off.
|
||||||
|
//
|
||||||
|
// Providing 0 TTL turns expiring off.
|
||||||
|
//
|
||||||
|
// Delete expired entries every 1/100th of ttl value. Goroutine which deletes expired entries runs indefinitely.
|
||||||
|
func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V], ttl time.Duration) *LRU[K, V] {
|
||||||
|
if size < 0 {
|
||||||
|
size = 0
|
||||||
|
}
|
||||||
|
if ttl <= 0 {
|
||||||
|
ttl = noEvictionTTL
|
||||||
|
}
|
||||||
|
|
||||||
|
res := LRU[K, V]{
|
||||||
|
ttl: ttl,
|
||||||
|
size: size,
|
||||||
|
evictList: internal.NewList[K, V](),
|
||||||
|
items: make(map[K]*internal.Entry[K, V]),
|
||||||
|
onEvict: onEvict,
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the buckets
|
||||||
|
res.buckets = make([]bucket[K, V], numBuckets)
|
||||||
|
for i := 0; i < numBuckets; i++ {
|
||||||
|
res.buckets[i] = bucket[K, V]{entries: make(map[K]*internal.Entry[K, V])}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable deleteExpired() running in separate goroutine for cache with non-zero TTL
|
||||||
|
//
|
||||||
|
// Important: done channel is never closed, so deleteExpired() goroutine will never exit,
|
||||||
|
// it's decided to add functionality to close it in the version later than v2.
|
||||||
|
if res.ttl != noEvictionTTL {
|
||||||
|
go func(done <-chan struct{}) {
|
||||||
|
ticker := time.NewTicker(res.ttl / numBuckets)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
res.deleteExpired()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(res.done)
|
||||||
|
}
|
||||||
|
return &res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge clears the cache completely.
|
||||||
|
// onEvict is called for each evicted key.
|
||||||
|
func (c *LRU[K, V]) Purge() {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
for k, v := range c.items {
|
||||||
|
if c.onEvict != nil {
|
||||||
|
c.onEvict(k, v.Value)
|
||||||
|
}
|
||||||
|
delete(c.items, k)
|
||||||
|
}
|
||||||
|
for _, b := range c.buckets {
|
||||||
|
for _, ent := range b.entries {
|
||||||
|
delete(b.entries, ent.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.evictList.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||||
|
// Returns false if there was no eviction: the item was already in the cache,
|
||||||
|
// or the size was not exceeded.
|
||||||
|
func (c *LRU[K, V]) Add(key K, value V) (evicted bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
// Check for existing item
|
||||||
|
if ent, ok := c.items[key]; ok {
|
||||||
|
c.evictList.MoveToFront(ent)
|
||||||
|
c.removeFromBucket(ent) // remove the entry from its current bucket as expiresAt is renewed
|
||||||
|
ent.Value = value
|
||||||
|
ent.ExpiresAt = now.Add(c.ttl)
|
||||||
|
c.addToBucket(ent)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new item
|
||||||
|
ent := c.evictList.PushFrontExpirable(key, value, now.Add(c.ttl))
|
||||||
|
c.items[key] = ent
|
||||||
|
c.addToBucket(ent) // adds the entry to the appropriate bucket and sets entry.expireBucket
|
||||||
|
|
||||||
|
evict := c.size > 0 && c.evictList.Length() > c.size
|
||||||
|
// Verify size not exceeded
|
||||||
|
if evict {
|
||||||
|
c.removeOldest()
|
||||||
|
}
|
||||||
|
return evict
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get looks up a key's value from the cache.
|
||||||
|
func (c *LRU[K, V]) Get(key K) (value V, ok bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
var ent *internal.Entry[K, V]
|
||||||
|
if ent, ok = c.items[key]; ok {
|
||||||
|
// Expired item check
|
||||||
|
if time.Now().After(ent.ExpiresAt) {
|
||||||
|
return value, false
|
||||||
|
}
|
||||||
|
c.evictList.MoveToFront(ent)
|
||||||
|
return ent.Value, true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains checks if a key is in the cache, without updating the recent-ness
|
||||||
|
// or deleting it for being stale.
|
||||||
|
func (c *LRU[K, V]) Contains(key K) (ok bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
_, ok = c.items[key]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peek returns the key value (or undefined if not found) without updating
|
||||||
|
// the "recently used"-ness of the key.
|
||||||
|
func (c *LRU[K, V]) Peek(key K) (value V, ok bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
var ent *internal.Entry[K, V]
|
||||||
|
if ent, ok = c.items[key]; ok {
|
||||||
|
// Expired item check
|
||||||
|
if time.Now().After(ent.ExpiresAt) {
|
||||||
|
return value, false
|
||||||
|
}
|
||||||
|
return ent.Value, true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the provided key from the cache, returning if the
|
||||||
|
// key was contained.
|
||||||
|
func (c *LRU[K, V]) Remove(key K) bool {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if ent, ok := c.items[key]; ok {
|
||||||
|
c.removeElement(ent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
|
func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if ent := c.evictList.Back(); ent != nil {
|
||||||
|
c.removeElement(ent)
|
||||||
|
return ent.Key, ent.Value, true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOldest returns the oldest entry
|
||||||
|
func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if ent := c.evictList.Back(); ent != nil {
|
||||||
|
return ent.Key, ent.Value, true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns a slice of the keys in the cache, from oldest to newest.
|
||||||
|
func (c *LRU[K, V]) Keys() []K {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
keys := make([]K, 0, len(c.items))
|
||||||
|
for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() {
|
||||||
|
keys = append(keys, ent.Key)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns a slice of the values in the cache, from oldest to newest.
|
||||||
|
// Expired entries are filtered out.
|
||||||
|
func (c *LRU[K, V]) Values() []V {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
values := make([]V, len(c.items))
|
||||||
|
i := 0
|
||||||
|
now := time.Now()
|
||||||
|
for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() {
|
||||||
|
if now.After(ent.ExpiresAt) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
values[i] = ent.Value
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of items in the cache.
|
||||||
|
func (c *LRU[K, V]) Len() int {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
return c.evictList.Length()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize changes the cache size. Size of 0 means unlimited.
|
||||||
|
func (c *LRU[K, V]) Resize(size int) (evicted int) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if size <= 0 {
|
||||||
|
c.size = 0
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
diff := c.evictList.Length() - size
|
||||||
|
if diff < 0 {
|
||||||
|
diff = 0
|
||||||
|
}
|
||||||
|
for i := 0; i < diff; i++ {
|
||||||
|
c.removeOldest()
|
||||||
|
}
|
||||||
|
c.size = size
|
||||||
|
return diff
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close destroys cleanup goroutine. To clean up the cache, run Purge() before Close().
|
||||||
|
// func (c *LRU[K, V]) Close() {
|
||||||
|
// c.mu.Lock()
|
||||||
|
// defer c.mu.Unlock()
|
||||||
|
// select {
|
||||||
|
// case <-c.done:
|
||||||
|
// return
|
||||||
|
// default:
|
||||||
|
// }
|
||||||
|
// close(c.done)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// removeOldest removes the oldest item from the cache. Has to be called with lock!
|
||||||
|
func (c *LRU[K, V]) removeOldest() {
|
||||||
|
if ent := c.evictList.Back(); ent != nil {
|
||||||
|
c.removeElement(ent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeElement is used to remove a given list element from the cache. Has to be called with lock!
|
||||||
|
func (c *LRU[K, V]) removeElement(e *internal.Entry[K, V]) {
|
||||||
|
c.evictList.Remove(e)
|
||||||
|
delete(c.items, e.Key)
|
||||||
|
c.removeFromBucket(e)
|
||||||
|
if c.onEvict != nil {
|
||||||
|
c.onEvict(e.Key, e.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteExpired deletes expired records from the oldest bucket, waiting for the newest entry
|
||||||
|
// in it to expire first.
|
||||||
|
func (c *LRU[K, V]) deleteExpired() {
|
||||||
|
c.mu.Lock()
|
||||||
|
bucketIdx := c.nextCleanupBucket
|
||||||
|
timeToExpire := time.Until(c.buckets[bucketIdx].newestEntry)
|
||||||
|
// wait for newest entry to expire before cleanup without holding lock
|
||||||
|
if timeToExpire > 0 {
|
||||||
|
c.mu.Unlock()
|
||||||
|
time.Sleep(timeToExpire)
|
||||||
|
c.mu.Lock()
|
||||||
|
}
|
||||||
|
for _, ent := range c.buckets[bucketIdx].entries {
|
||||||
|
c.removeElement(ent)
|
||||||
|
}
|
||||||
|
c.nextCleanupBucket = (c.nextCleanupBucket + 1) % numBuckets
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// addToBucket adds entry to expire bucket so that it will be cleaned up when the time comes. Has to be called with lock!
|
||||||
|
func (c *LRU[K, V]) addToBucket(e *internal.Entry[K, V]) {
|
||||||
|
bucketID := (numBuckets + c.nextCleanupBucket - 1) % numBuckets
|
||||||
|
e.ExpireBucket = bucketID
|
||||||
|
c.buckets[bucketID].entries[e.Key] = e
|
||||||
|
if c.buckets[bucketID].newestEntry.Before(e.ExpiresAt) {
|
||||||
|
c.buckets[bucketID].newestEntry = e.ExpiresAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeFromBucket removes the entry from its corresponding bucket. Has to be called with lock!
|
||||||
|
func (c *LRU[K, V]) removeFromBucket(e *internal.Entry[K, V]) {
|
||||||
|
delete(c.buckets[e.ExpireBucket].entries, e.Key)
|
||||||
|
}
|
||||||
74
vendor/github.com/jhillyerd/enmime/.golangci.yml
generated
vendored
74
vendor/github.com/jhillyerd/enmime/.golangci.yml
generated
vendored
|
|
@ -2,22 +2,74 @@ run:
|
||||||
timeout: 5m
|
timeout: 5m
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
|
- asasalint
|
||||||
- asciicheck
|
- asciicheck
|
||||||
|
- bidichk
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- deadcode
|
- containedctx
|
||||||
|
- contextcheck
|
||||||
|
- decorder
|
||||||
|
# - dupl
|
||||||
|
# - dupword
|
||||||
|
- durationcheck
|
||||||
|
- errchkjson
|
||||||
|
- errname
|
||||||
|
# - errorlint
|
||||||
|
- execinquery
|
||||||
|
# - exhaustive
|
||||||
- exportloopref
|
- exportloopref
|
||||||
- errcheck
|
# - forcetypeassert
|
||||||
|
- ginkgolinter
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
# - gochecknoinits
|
||||||
|
- gochecksumtype
|
||||||
|
- gocritic
|
||||||
|
# - godot
|
||||||
|
# - goerr113
|
||||||
- gofmt
|
- gofmt
|
||||||
|
# - gofumpt
|
||||||
|
- goheader
|
||||||
- goimports
|
- goimports
|
||||||
- gosimple
|
- gomoddirectives
|
||||||
- govet
|
- gomodguard
|
||||||
- ineffassign
|
- goprintffuncname
|
||||||
|
# - gosec
|
||||||
|
- gosmopolitan
|
||||||
|
- grouper
|
||||||
|
- importas
|
||||||
|
- inamedparam
|
||||||
|
- interfacebloat
|
||||||
|
- loggercheck
|
||||||
|
- makezero
|
||||||
|
- mirror
|
||||||
- misspell
|
- misspell
|
||||||
- megacheck
|
- musttag
|
||||||
|
- nilerr
|
||||||
|
# - nilnil
|
||||||
|
# - nlreturn
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- nosprintfhostport
|
||||||
|
- perfsprint
|
||||||
- prealloc
|
- prealloc
|
||||||
|
- predeclared
|
||||||
|
- promlinter
|
||||||
|
- protogetter
|
||||||
|
- reassign
|
||||||
|
# - revive
|
||||||
- rowserrcheck
|
- rowserrcheck
|
||||||
- staticcheck
|
- sloglint
|
||||||
- structcheck
|
- stylecheck
|
||||||
- typecheck
|
- tagalign
|
||||||
- unused
|
- tagliatelle
|
||||||
- varcheck
|
- tenv
|
||||||
|
- testableexamples
|
||||||
|
- testifylint
|
||||||
|
- thelper
|
||||||
|
- tparallel
|
||||||
|
# - unconvert
|
||||||
|
- unparam
|
||||||
|
- usestdlibvars
|
||||||
|
- wastedassign
|
||||||
|
- whitespace
|
||||||
|
- zerologlint
|
||||||
|
|
|
||||||
3
vendor/github.com/jhillyerd/enmime/Makefile
generated
vendored
3
vendor/github.com/jhillyerd/enmime/Makefile
generated
vendored
|
|
@ -27,7 +27,8 @@ simplify:
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@test -z "$(shell gofmt -l . | tee /dev/stderr)" || echo "[WARN] Fix formatting issues with 'make fmt'"
|
@test -z "$(shell gofmt -l . | tee /dev/stderr)" || echo "[WARN] Fix formatting issues with 'make fmt'"
|
||||||
@golint -set_exit_status $(PKGS)
|
@# TODO: lint disabled until `mediatype.MediaTypeParseOptions` renamed to remove repetition.
|
||||||
|
@#@golint -set_exit_status $(PKGS)
|
||||||
@go vet $(PKGS)
|
@go vet $(PKGS)
|
||||||
|
|
||||||
reflex:
|
reflex:
|
||||||
|
|
|
||||||
10
vendor/github.com/jhillyerd/enmime/README.md
generated
vendored
10
vendor/github.com/jhillyerd/enmime/README.md
generated
vendored
|
|
@ -17,9 +17,8 @@ See our [Pkg Docs] for examples and API usage information.
|
||||||
|
|
||||||
## Development Status
|
## Development Status
|
||||||
|
|
||||||
enmime is near production quality: it works but struggles to parse a small
|
enmime is production quality, but there are many buggy MIME encoders in the
|
||||||
percentage of emails. It's possible the API will evolve slightly before the 1.0
|
wild, so you may still encounter messages it cannot parse.
|
||||||
release.
|
|
||||||
|
|
||||||
See [CONTRIBUTING.md] for more information.
|
See [CONTRIBUTING.md] for more information.
|
||||||
|
|
||||||
|
|
@ -32,11 +31,10 @@ enmime is open source software released under the MIT License. The latest
|
||||||
version can be found at https://github.com/jhillyerd/enmime
|
version can be found at https://github.com/jhillyerd/enmime
|
||||||
|
|
||||||
|
|
||||||
[Build Status]: https://travis-ci.org/jhillyerd/enmime
|
|
||||||
[Builder Usage]: https://github.com/jhillyerd/enmime/wiki/Builder-Usage
|
[Builder Usage]: https://github.com/jhillyerd/enmime/wiki/Builder-Usage
|
||||||
[Coverage Status]: https://coveralls.io/github/jhillyerd/enmime
|
[Coverage Status]: https://coveralls.io/github/jhillyerd/enmime
|
||||||
[CONTRIBUTING.md]: https://github.com/jhillyerd/enmime/blob/main/CONTRIBUTING.md
|
[CONTRIBUTING.md]: https://github.com/jhillyerd/enmime/blob/main/CONTRIBUTING.md
|
||||||
[Inbucket]: http://www.inbucket.org/
|
[Inbucket]: https://www.inbucket.org/
|
||||||
[Golang]: http://golang.org/
|
[Golang]: https://go.dev/
|
||||||
[Go Report Card]: https://goreportcard.com/report/github.com/jhillyerd/enmime
|
[Go Report Card]: https://goreportcard.com/report/github.com/jhillyerd/enmime
|
||||||
[Pkg Docs]: https://pkg.go.dev/github.com/jhillyerd/enmime
|
[Pkg Docs]: https://pkg.go.dev/github.com/jhillyerd/enmime
|
||||||
|
|
|
||||||
7
vendor/github.com/jhillyerd/enmime/encode.go
generated
vendored
7
vendor/github.com/jhillyerd/enmime/encode.go
generated
vendored
|
|
@ -50,7 +50,10 @@ func (p *Part) Encode(writer io.Writer) error {
|
||||||
}
|
}
|
||||||
p.Content = p.Content[:n]
|
p.Content = p.Content[:n]
|
||||||
}
|
}
|
||||||
cte := p.setupMIMEHeaders()
|
cte := teRaw
|
||||||
|
if p.parser == nil || !p.parser.rawContent {
|
||||||
|
cte = p.setupMIMEHeaders()
|
||||||
|
}
|
||||||
// Encode this part.
|
// Encode this part.
|
||||||
b := bufio.NewWriter(writer)
|
b := bufio.NewWriter(writer)
|
||||||
if err := p.encodeHeader(b); err != nil {
|
if err := p.encodeHeader(b); err != nil {
|
||||||
|
|
@ -99,9 +102,7 @@ func (p *Part) setupMIMEHeaders() transferEncoding {
|
||||||
|
|
||||||
// If we are encoding a part that previously had content-transfer-encoding set, unset it so
|
// If we are encoding a part that previously had content-transfer-encoding set, unset it so
|
||||||
// the correct encoding detection can be done below.
|
// the correct encoding detection can be done below.
|
||||||
if p.parser != nil && !p.parser.rawContent {
|
|
||||||
p.Header.Del(hnContentEncoding)
|
p.Header.Del(hnContentEncoding)
|
||||||
}
|
|
||||||
|
|
||||||
cte := te7Bit
|
cte := te7Bit
|
||||||
if len(p.Content) > 0 {
|
if len(p.Content) > 0 {
|
||||||
|
|
|
||||||
23
vendor/github.com/jhillyerd/enmime/envelope.go
generated
vendored
23
vendor/github.com/jhillyerd/enmime/envelope.go
generated
vendored
|
|
@ -69,7 +69,7 @@ func (e *Envelope) GetHeaderValues(name string) []string {
|
||||||
// If the header exists already, all existing values are replaced.
|
// If the header exists already, all existing values are replaced.
|
||||||
func (e *Envelope) SetHeader(name string, value []string) error {
|
func (e *Envelope) SetHeader(name string, value []string) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return fmt.Errorf("provide non-empty header name")
|
return errors.New("provide non-empty header name")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
|
|
@ -86,7 +86,7 @@ func (e *Envelope) SetHeader(name string, value []string) error {
|
||||||
// If the header does not exist already, it will be created.
|
// If the header does not exist already, it will be created.
|
||||||
func (e *Envelope) AddHeader(name string, value string) error {
|
func (e *Envelope) AddHeader(name string, value string) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return fmt.Errorf("provide non-empty header name")
|
return errors.New("provide non-empty header name")
|
||||||
}
|
}
|
||||||
|
|
||||||
e.header.Add(name, mime.BEncoding.Encode("utf-8", value))
|
e.header.Add(name, mime.BEncoding.Encode("utf-8", value))
|
||||||
|
|
@ -96,7 +96,7 @@ func (e *Envelope) AddHeader(name string, value string) error {
|
||||||
// DeleteHeader deletes given header.
|
// DeleteHeader deletes given header.
|
||||||
func (e *Envelope) DeleteHeader(name string) error {
|
func (e *Envelope) DeleteHeader(name string) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return fmt.Errorf("provide non-empty header name")
|
return errors.New("provide non-empty header name")
|
||||||
}
|
}
|
||||||
|
|
||||||
e.header.Del(name)
|
e.header.Del(name)
|
||||||
|
|
@ -106,7 +106,7 @@ func (e *Envelope) DeleteHeader(name string) error {
|
||||||
// AddressList returns a mail.Address slice with RFC 2047 encoded names converted to UTF-8
|
// AddressList returns a mail.Address slice with RFC 2047 encoded names converted to UTF-8
|
||||||
func (e *Envelope) AddressList(key string) ([]*mail.Address, error) {
|
func (e *Envelope) AddressList(key string) ([]*mail.Address, error) {
|
||||||
if e.header == nil {
|
if e.header == nil {
|
||||||
return nil, fmt.Errorf("no headers available")
|
return nil, errors.New("no headers available")
|
||||||
}
|
}
|
||||||
if !AddressHeaders[strings.ToLower(key)] {
|
if !AddressHeaders[strings.ToLower(key)] {
|
||||||
return nil, fmt.Errorf("%s is not an address header", key)
|
return nil, fmt.Errorf("%s is not an address header", key)
|
||||||
|
|
@ -191,9 +191,7 @@ func (p Parser) EnvelopeFromPart(root *Part) (*Envelope, error) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Only text, no attachments
|
// Only text, no attachments
|
||||||
if err := parseTextOnlyBody(root, e); err != nil {
|
parseTextOnlyBody(root, e)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,6 +201,8 @@ func (p Parser) EnvelopeFromPart(root *Part) (*Envelope, error) {
|
||||||
e.Root.addWarning(
|
e.Root.addWarning(
|
||||||
ErrorPlainTextFromHTML,
|
ErrorPlainTextFromHTML,
|
||||||
"Message did not contain a text/plain part")
|
"Message did not contain a text/plain part")
|
||||||
|
|
||||||
|
if !p.disableTextConversion {
|
||||||
var err error
|
var err error
|
||||||
if e.Text, err = html2text.FromString(e.HTML); err != nil {
|
if e.Text, err = html2text.FromString(e.HTML); err != nil {
|
||||||
e.Text = "" // Down-conversion shouldn't fail
|
e.Text = "" // Down-conversion shouldn't fail
|
||||||
|
|
@ -210,6 +210,7 @@ func (p Parser) EnvelopeFromPart(root *Part) (*Envelope, error) {
|
||||||
p.addError(ErrorPlainTextFromHTML, "Failed to downconvert HTML: %v", err)
|
p.addError(ErrorPlainTextFromHTML, "Failed to downconvert HTML: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy part errors into Envelope.
|
// Copy part errors into Envelope.
|
||||||
if e.Root != nil {
|
if e.Root != nil {
|
||||||
|
|
@ -225,7 +226,7 @@ func (p Parser) EnvelopeFromPart(root *Part) (*Envelope, error) {
|
||||||
|
|
||||||
// parseTextOnlyBody parses a plain text message in root that has MIME-like headers, but
|
// parseTextOnlyBody parses a plain text message in root that has MIME-like headers, but
|
||||||
// only contains a single part - no boundaries, etc. The result is placed in e.
|
// only contains a single part - no boundaries, etc. The result is placed in e.
|
||||||
func parseTextOnlyBody(root *Part, e *Envelope) error {
|
func parseTextOnlyBody(root *Part, e *Envelope) {
|
||||||
// Determine character set
|
// Determine character set
|
||||||
var charset string
|
var charset string
|
||||||
var isHTML bool
|
var isHTML bool
|
||||||
|
|
@ -255,14 +256,10 @@ func parseTextOnlyBody(root *Part, e *Envelope) error {
|
||||||
root.addWarning(ErrorCharsetConversion, err.Error())
|
root.addWarning(ErrorCharsetConversion, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Converted from charset in HTML
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
e.Text = string(root.Content)
|
e.Text = string(root.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseMultiPartBody parses a multipart message in root. The result is placed in e.
|
// parseMultiPartBody parses a multipart message in root. The result is placed in e.
|
||||||
|
|
@ -278,7 +275,7 @@ func parseMultiPartBody(root *Part, e *Envelope) error {
|
||||||
}
|
}
|
||||||
boundary := params[hpBoundary]
|
boundary := params[hpBoundary]
|
||||||
if boundary == "" {
|
if boundary == "" {
|
||||||
return fmt.Errorf("unable to locate boundary param in Content-Type header")
|
return errors.New("unable to locate boundary param in Content-Type header")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate text body
|
// Locate text body
|
||||||
|
|
|
||||||
4
vendor/github.com/jhillyerd/enmime/internal/coding/headerext.go
generated
vendored
4
vendor/github.com/jhillyerd/enmime/internal/coding/headerext.go
generated
vendored
|
|
@ -61,10 +61,10 @@ func RFC2047Decode(s string) string {
|
||||||
|
|
||||||
// Add quotes as needed.
|
// Add quotes as needed.
|
||||||
if !strings.HasPrefix(value, "\"") {
|
if !strings.HasPrefix(value, "\"") {
|
||||||
value = fmt.Sprintf("\"%s", value)
|
value = `"` + value
|
||||||
}
|
}
|
||||||
if !strings.HasSuffix(value, "\"") {
|
if !strings.HasSuffix(value, "\"") {
|
||||||
value = fmt.Sprintf("%s\"", value)
|
value += `"`
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s=%s", key, value)
|
return fmt.Sprintf("%s=%s", key, value)
|
||||||
|
|
|
||||||
2
vendor/github.com/jhillyerd/enmime/internal/coding/idheader.go
generated
vendored
2
vendor/github.com/jhillyerd/enmime/internal/coding/idheader.go
generated
vendored
|
|
@ -22,5 +22,5 @@ func FromIDHeader(v string) string {
|
||||||
// ToIDHeader encodes a Content-ID or Message-ID header value (RFC 2392) from a utf-8 string.
|
// ToIDHeader encodes a Content-ID or Message-ID header value (RFC 2392) from a utf-8 string.
|
||||||
func ToIDHeader(v string) string {
|
func ToIDHeader(v string) string {
|
||||||
v = url.QueryEscape(v)
|
v = url.QueryEscape(v)
|
||||||
return "<" + strings.Replace(v, "%40", "@", -1) + ">"
|
return "<" + strings.ReplaceAll(v, "%40", "@") + ">"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
vendor/github.com/jhillyerd/enmime/internal/stringutil/find.go
generated
vendored
1
vendor/github.com/jhillyerd/enmime/internal/stringutil/find.go
generated
vendored
|
|
@ -32,7 +32,6 @@ func FindUnquoted(s string, v rune, quote rune) []int {
|
||||||
default:
|
default:
|
||||||
escaped = false
|
escaped = false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(indexes, quotedIndexes...)
|
return append(indexes, quotedIndexes...)
|
||||||
|
|
|
||||||
4
vendor/github.com/jhillyerd/enmime/internal/textproto/reader.go
generated
vendored
4
vendor/github.com/jhillyerd/enmime/internal/textproto/reader.go
generated
vendored
|
|
@ -127,7 +127,7 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
|
||||||
// error is returned from readContinuedLineSlice.
|
// error is returned from readContinuedLineSlice.
|
||||||
func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) {
|
func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) {
|
||||||
if validateFirstLine == nil {
|
if validateFirstLine == nil {
|
||||||
return nil, fmt.Errorf("missing validateFirstLine func")
|
return nil, errors.New("missing validateFirstLine func")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the first line.
|
// Read the first line.
|
||||||
|
|
@ -168,6 +168,8 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([
|
||||||
r.buf = append(r.buf, ' ')
|
r.buf = append(r.buf, ' ')
|
||||||
r.buf = append(r.buf, trim(line)...)
|
r.buf = append(r.buf, trim(line)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//lint:ignore nilerr to maintain go stdlib compatibility.
|
||||||
return r.buf, nil
|
return r.buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1
vendor/github.com/jhillyerd/enmime/mediatype/mediatype.go
generated
vendored
1
vendor/github.com/jhillyerd/enmime/mediatype/mediatype.go
generated
vendored
|
|
@ -30,6 +30,7 @@ const (
|
||||||
utf8 = "utf-8"
|
utf8 = "utf-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MediaTypeParseOptions controls the parsing of content-type and media-type strings.
|
||||||
type MediaTypeParseOptions struct {
|
type MediaTypeParseOptions struct {
|
||||||
StripMediaTypeInvalidCharacters bool
|
StripMediaTypeInvalidCharacters bool
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
vendor/github.com/jhillyerd/enmime/options.go
generated
vendored
24
vendor/github.com/jhillyerd/enmime/options.go
generated
vendored
|
|
@ -88,3 +88,27 @@ func (o stripMediaTypeInvalidCharactersOption) apply(p *Parser) {
|
||||||
func StripMediaTypeInvalidCharacters(stripMediaTypeInvalidCharacters bool) Option {
|
func StripMediaTypeInvalidCharacters(stripMediaTypeInvalidCharacters bool) Option {
|
||||||
return stripMediaTypeInvalidCharactersOption(stripMediaTypeInvalidCharacters)
|
return stripMediaTypeInvalidCharactersOption(stripMediaTypeInvalidCharacters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type disableTextConversionOption bool
|
||||||
|
|
||||||
|
func (o disableTextConversionOption) apply(p *Parser) {
|
||||||
|
p.disableTextConversion = bool(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableTextConversion sets the disableTextConversion option. When true, there will be no
|
||||||
|
// automated down conversion of HTML to text when a plain/text body is missing.
|
||||||
|
func DisableTextConversion(disableTextConversion bool) Option {
|
||||||
|
return disableTextConversionOption(disableTextConversion)
|
||||||
|
}
|
||||||
|
|
||||||
|
type disableCharacterDetectionOption bool
|
||||||
|
|
||||||
|
func (o disableCharacterDetectionOption) apply(p *Parser) {
|
||||||
|
p.disableCharacterDetection = bool(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableCharacterDetection sets the disableCharacterDetection option. When true, the parser will use the
|
||||||
|
// defined character set if it is defined in the message part.
|
||||||
|
func DisableCharacterDetection(disableCharacterDetection bool) Option {
|
||||||
|
return disableCharacterDetectionOption(disableCharacterDetection)
|
||||||
|
}
|
||||||
|
|
|
||||||
2
vendor/github.com/jhillyerd/enmime/parser.go
generated
vendored
2
vendor/github.com/jhillyerd/enmime/parser.go
generated
vendored
|
|
@ -26,6 +26,8 @@ type Parser struct {
|
||||||
rawContent bool
|
rawContent bool
|
||||||
customParseMediaType CustomParseMediaType
|
customParseMediaType CustomParseMediaType
|
||||||
stripMediaTypeInvalidCharacters bool
|
stripMediaTypeInvalidCharacters bool
|
||||||
|
disableTextConversion bool
|
||||||
|
disableCharacterDetection bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultParser is a Parser with default configuration.
|
// defaultParser is a Parser with default configuration.
|
||||||
|
|
|
||||||
3
vendor/github.com/jhillyerd/enmime/part.go
generated
vendored
3
vendor/github.com/jhillyerd/enmime/part.go
generated
vendored
|
|
@ -210,7 +210,8 @@ func (p *Part) convertFromDetectedCharset(r io.Reader, readPartErrorPolicy ReadP
|
||||||
// Restore r.
|
// Restore r.
|
||||||
r = bytes.NewReader(buf)
|
r = bytes.NewReader(buf)
|
||||||
|
|
||||||
if cs == nil || cs.Confidence < minCharsetConfidence || len(bytes.Runes(buf)) < minCharsetRuneLength {
|
if (p.parser.disableCharacterDetection && p.Charset != "") ||
|
||||||
|
(cs == nil || cs.Confidence < minCharsetConfidence || len(bytes.Runes(buf)) < minCharsetRuneLength) {
|
||||||
// Low confidence or not enough characters, use declared character set.
|
// Low confidence or not enough characters, use declared character set.
|
||||||
return p.convertFromStatedCharset(r), nil
|
return p.convertFromStatedCharset(r), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
vendor/github.com/tidwall/gjson/README.md
generated
vendored
22
vendor/github.com/tidwall/gjson/README.md
generated
vendored
|
|
@ -438,15 +438,15 @@ Benchmarks of GJSON alongside [encoding/json](https://golang.org/pkg/encoding/js
|
||||||
and [json-iterator](https://github.com/json-iterator/go)
|
and [json-iterator](https://github.com/json-iterator/go)
|
||||||
|
|
||||||
```
|
```
|
||||||
BenchmarkGJSONGet-16 11644512 311 ns/op 0 B/op 0 allocs/op
|
BenchmarkGJSONGet-10 17893731 202.1 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkGJSONUnmarshalMap-16 1122678 3094 ns/op 1920 B/op 26 allocs/op
|
BenchmarkGJSONUnmarshalMap-10 1663548 2157 ns/op 1920 B/op 26 allocs/op
|
||||||
BenchmarkJSONUnmarshalMap-16 516681 6810 ns/op 2944 B/op 69 allocs/op
|
BenchmarkJSONUnmarshalMap-10 832236 4279 ns/op 2920 B/op 68 allocs/op
|
||||||
BenchmarkJSONUnmarshalStruct-16 697053 5400 ns/op 928 B/op 13 allocs/op
|
BenchmarkJSONUnmarshalStruct-10 1076475 3219 ns/op 920 B/op 12 allocs/op
|
||||||
BenchmarkJSONDecoder-16 330450 10217 ns/op 3845 B/op 160 allocs/op
|
BenchmarkJSONDecoder-10 585729 6126 ns/op 3845 B/op 160 allocs/op
|
||||||
BenchmarkFFJSONLexer-16 1424979 2585 ns/op 880 B/op 8 allocs/op
|
BenchmarkFFJSONLexer-10 2508573 1391 ns/op 880 B/op 8 allocs/op
|
||||||
BenchmarkEasyJSONLexer-16 3000000 729 ns/op 501 B/op 5 allocs/op
|
BenchmarkEasyJSONLexer-10 3000000 537.9 ns/op 501 B/op 5 allocs/op
|
||||||
BenchmarkJSONParserGet-16 3000000 366 ns/op 21 B/op 0 allocs/op
|
BenchmarkJSONParserGet-10 13707510 263.9 ns/op 21 B/op 0 allocs/op
|
||||||
BenchmarkJSONIterator-16 3000000 869 ns/op 693 B/op 14 allocs/op
|
BenchmarkJSONIterator-10 3000000 561.2 ns/op 693 B/op 14 allocs/op
|
||||||
```
|
```
|
||||||
|
|
||||||
JSON document used:
|
JSON document used:
|
||||||
|
|
@ -487,4 +487,6 @@ widget.image.hOffset
|
||||||
widget.text.onMouseUp
|
widget.text.onMouseUp
|
||||||
```
|
```
|
||||||
|
|
||||||
*These benchmarks were run on a MacBook Pro 16" 2.4 GHz Intel Core i9 using Go 1.17 and can be found [here](https://github.com/tidwall/gjson-benchmarks).*
|
**
|
||||||
|
|
||||||
|
*These benchmarks were run on a MacBook Pro M1 Max using Go 1.22 and can be found [here](https://github.com/tidwall/gjson-benchmarks).*
|
||||||
|
|
|
||||||
128
vendor/github.com/tidwall/gjson/gjson.go
generated
vendored
128
vendor/github.com/tidwall/gjson/gjson.go
generated
vendored
|
|
@ -1040,6 +1040,10 @@ func parseObjectPath(path string) (r objectPathResult) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var vchars = [256]byte{
|
||||||
|
'"': 2, '{': 3, '(': 3, '[': 3, '}': 1, ')': 1, ']': 1,
|
||||||
|
}
|
||||||
|
|
||||||
func parseSquash(json string, i int) (int, string) {
|
func parseSquash(json string, i int) (int, string) {
|
||||||
// expects that the lead character is a '[' or '{' or '('
|
// expects that the lead character is a '[' or '{' or '('
|
||||||
// squash the value, ignoring all nested arrays and objects.
|
// squash the value, ignoring all nested arrays and objects.
|
||||||
|
|
@ -1047,17 +1051,111 @@ func parseSquash(json string, i int) (int, string) {
|
||||||
s := i
|
s := i
|
||||||
i++
|
i++
|
||||||
depth := 1
|
depth := 1
|
||||||
for ; i < len(json); i++ {
|
var c byte
|
||||||
if json[i] >= '"' && json[i] <= '}' {
|
for i < len(json) {
|
||||||
switch json[i] {
|
for i < len(json)-8 {
|
||||||
case '"':
|
jslice := json[i : i+8]
|
||||||
|
c = vchars[jslice[0]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 0
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[1]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 1
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[2]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 2
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[3]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 3
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[4]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 4
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[5]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 5
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[6]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 6
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
c = vchars[jslice[7]]
|
||||||
|
if c != 0 {
|
||||||
|
i += 7
|
||||||
|
goto token
|
||||||
|
}
|
||||||
|
i += 8
|
||||||
|
}
|
||||||
|
c = vchars[json[i]]
|
||||||
|
if c == 0 {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
token:
|
||||||
|
if c == 2 {
|
||||||
|
// '"' string
|
||||||
|
i++
|
||||||
|
s2 := i
|
||||||
|
nextquote:
|
||||||
|
for i < len(json)-8 {
|
||||||
|
jslice := json[i : i+8]
|
||||||
|
if jslice[0] == '"' {
|
||||||
|
i += 0
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[1] == '"' {
|
||||||
|
i += 1
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[2] == '"' {
|
||||||
|
i += 2
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[3] == '"' {
|
||||||
|
i += 3
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[4] == '"' {
|
||||||
|
i += 4
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[5] == '"' {
|
||||||
|
i += 5
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[6] == '"' {
|
||||||
|
i += 6
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
if jslice[7] == '"' {
|
||||||
|
i += 7
|
||||||
|
goto strchkesc
|
||||||
|
}
|
||||||
|
i += 8
|
||||||
|
}
|
||||||
|
goto strchkstd
|
||||||
|
strchkesc:
|
||||||
|
if json[i-1] != '\\' {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
strchkstd:
|
||||||
|
for i < len(json) {
|
||||||
|
if json[i] > '\\' || json[i] != '"' {
|
||||||
i++
|
i++
|
||||||
s2 := i
|
|
||||||
for ; i < len(json); i++ {
|
|
||||||
if json[i] > '\\' {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if json[i] == '"' {
|
|
||||||
// look for an escaped slash
|
// look for an escaped slash
|
||||||
if json[i-1] == '\\' {
|
if json[i-1] == '\\' {
|
||||||
n := 0
|
n := 0
|
||||||
|
|
@ -1068,22 +1166,22 @@ func parseSquash(json string, i int) (int, string) {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
if n%2 == 0 {
|
if n%2 == 0 {
|
||||||
continue
|
i++
|
||||||
|
goto nextquote
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
case '{', '[', '(':
|
// '{', '[', '(', '}', ']', ')'
|
||||||
depth++
|
// open close tokens
|
||||||
case '}', ']', ')':
|
depth += int(c) - 2
|
||||||
depth--
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
i++
|
i++
|
||||||
return i, json[s:i]
|
return i, json[s:i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
i++
|
||||||
}
|
}
|
||||||
return i, json[s:]
|
return i, json[s:]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
vendor/github.com/yuin/goldmark/ast/block.go
generated
vendored
10
vendor/github.com/yuin/goldmark/ast/block.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
||||||
package ast
|
package ast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -47,6 +48,15 @@ func (b *BaseBlock) SetLines(v *textm.Segments) {
|
||||||
b.lines = v
|
b.lines = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Text implements Node.Text.
|
||||||
|
func (b *BaseBlock) Text(source []byte) []byte {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, line := range b.Lines().Sliced(0, b.Lines().Len()) {
|
||||||
|
buf.Write(line.Value(source))
|
||||||
|
}
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
// A Document struct is a root node of Markdown text.
|
// A Document struct is a root node of Markdown text.
|
||||||
type Document struct {
|
type Document struct {
|
||||||
BaseBlock
|
BaseBlock
|
||||||
|
|
|
||||||
4
vendor/github.com/yuin/goldmark/extension/table.go
generated
vendored
4
vendor/github.com/yuin/goldmark/extension/table.go
generated
vendored
|
|
@ -184,11 +184,11 @@ func (b *tableParagraphTransformer) Transform(node *gast.Paragraph, reader text.
|
||||||
func (b *tableParagraphTransformer) parseRow(segment text.Segment,
|
func (b *tableParagraphTransformer) parseRow(segment text.Segment,
|
||||||
alignments []ast.Alignment, isHeader bool, reader text.Reader, pc parser.Context) *ast.TableRow {
|
alignments []ast.Alignment, isHeader bool, reader text.Reader, pc parser.Context) *ast.TableRow {
|
||||||
source := reader.Source()
|
source := reader.Source()
|
||||||
|
segment = segment.TrimLeftSpace(source)
|
||||||
|
segment = segment.TrimRightSpace(source)
|
||||||
line := segment.Value(source)
|
line := segment.Value(source)
|
||||||
pos := 0
|
pos := 0
|
||||||
pos += util.TrimLeftSpaceLength(line)
|
|
||||||
limit := len(line)
|
limit := len(line)
|
||||||
limit -= util.TrimRightSpaceLength(line)
|
|
||||||
row := ast.NewTableRow(alignments)
|
row := ast.NewTableRow(alignments)
|
||||||
if len(line) > 0 && line[pos] == '|' {
|
if len(line) > 0 && line[pos] == '|' {
|
||||||
pos++
|
pos++
|
||||||
|
|
|
||||||
11
vendor/github.com/yuin/goldmark/parser/blockquote.go
generated
vendored
11
vendor/github.com/yuin/goldmark/parser/blockquote.go
generated
vendored
|
|
@ -28,12 +28,13 @@ func (b *blockquoteParser) process(reader text.Reader) bool {
|
||||||
reader.Advance(pos)
|
reader.Advance(pos)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if line[pos] == ' ' || line[pos] == '\t' {
|
|
||||||
pos++
|
|
||||||
}
|
|
||||||
reader.Advance(pos)
|
reader.Advance(pos)
|
||||||
if line[pos-1] == '\t' {
|
if line[pos] == ' ' || line[pos] == '\t' {
|
||||||
reader.SetPadding(2)
|
padding := 0
|
||||||
|
if line[pos] == '\t' {
|
||||||
|
padding = util.TabWidth(reader.LineOffset()) - 1
|
||||||
|
}
|
||||||
|
reader.AdvanceAndSetPadding(1, padding)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
vendor/github.com/yuin/goldmark/parser/list_item.go
generated
vendored
2
vendor/github.com/yuin/goldmark/parser/list_item.go
generated
vendored
|
|
@ -58,7 +58,7 @@ func (b *listItemParser) Continue(node ast.Node, reader text.Reader, pc Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := lastOffset(node.Parent())
|
offset := lastOffset(node.Parent())
|
||||||
isEmpty := node.ChildCount() == 0
|
isEmpty := node.ChildCount() == 0 && pc.Get(emptyListItemWithBlankLines) != nil
|
||||||
indent, _ := util.IndentWidth(line, reader.LineOffset())
|
indent, _ := util.IndentWidth(line, reader.LineOffset())
|
||||||
if (isEmpty || indent < offset) && indent < 4 {
|
if (isEmpty || indent < offset) && indent < 4 {
|
||||||
_, typ := matchesListItem(line, true)
|
_, typ := matchesListItem(line, true)
|
||||||
|
|
|
||||||
8
vendor/github.com/yuin/goldmark/parser/parser.go
generated
vendored
8
vendor/github.com/yuin/goldmark/parser/parser.go
generated
vendored
|
|
@ -878,10 +878,17 @@ func (p *parser) Parse(reader text.Reader, opts ...ParseOption) ast.Node {
|
||||||
blockReader := text.NewBlockReader(reader.Source(), nil)
|
blockReader := text.NewBlockReader(reader.Source(), nil)
|
||||||
p.walkBlock(root, func(node ast.Node) {
|
p.walkBlock(root, func(node ast.Node) {
|
||||||
p.parseBlock(blockReader, node, pc)
|
p.parseBlock(blockReader, node, pc)
|
||||||
|
lines := node.Lines()
|
||||||
|
if lines != nil && lines.Len() != 0 {
|
||||||
|
s := lines.At(lines.Len() - 1)
|
||||||
|
s.EOB = true
|
||||||
|
lines.Set(lines.Len()-1, s)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
for _, at := range p.astTransformers {
|
for _, at := range p.astTransformers {
|
||||||
at.Transform(root, reader, pc)
|
at.Transform(root, reader, pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// root.Dump(reader.Source(), 0)
|
// root.Dump(reader.Source(), 0)
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
@ -1256,4 +1263,5 @@ func (p *parser) parseBlock(block text.BlockReader, parent ast.Node, pc Context)
|
||||||
for _, ip := range p.closeBlockers {
|
for _, ip := range p.closeBlockers {
|
||||||
ip.CloseBlock(parent, block, pc)
|
ip.CloseBlock(parent, block, pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
vendor/github.com/yuin/goldmark/text/segment.go
generated
vendored
18
vendor/github.com/yuin/goldmark/text/segment.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package text
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -18,6 +19,9 @@ type Segment struct {
|
||||||
|
|
||||||
// Padding is a padding length of the segment.
|
// Padding is a padding length of the segment.
|
||||||
Padding int
|
Padding int
|
||||||
|
|
||||||
|
// EOB is true if the segment is end of the block.
|
||||||
|
EOB bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSegment return a new Segment.
|
// NewSegment return a new Segment.
|
||||||
|
|
@ -40,12 +44,18 @@ func NewSegmentPadding(start, stop, n int) Segment {
|
||||||
|
|
||||||
// Value returns a value of the segment.
|
// Value returns a value of the segment.
|
||||||
func (t *Segment) Value(buffer []byte) []byte {
|
func (t *Segment) Value(buffer []byte) []byte {
|
||||||
|
var result []byte
|
||||||
if t.Padding == 0 {
|
if t.Padding == 0 {
|
||||||
return buffer[t.Start:t.Stop]
|
result = buffer[t.Start:t.Stop]
|
||||||
}
|
} else {
|
||||||
result := make([]byte, 0, t.Padding+t.Stop-t.Start+1)
|
result = make([]byte, 0, t.Padding+t.Stop-t.Start+1)
|
||||||
result = append(result, bytes.Repeat(space, t.Padding)...)
|
result = append(result, bytes.Repeat(space, t.Padding)...)
|
||||||
return append(result, buffer[t.Start:t.Stop]...)
|
result = append(result, buffer[t.Start:t.Stop]...)
|
||||||
|
}
|
||||||
|
if t.EOB && len(result) > 0 && result[len(result)-1] != '\n' {
|
||||||
|
result = append(result, '\n')
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns a length of the segment.
|
// Len returns a length of the segment.
|
||||||
|
|
|
||||||
16
vendor/github.com/yuin/goldmark/util/html5entities.go
generated
vendored
16
vendor/github.com/yuin/goldmark/util/html5entities.go
generated
vendored
|
|
@ -1,6 +1,8 @@
|
||||||
//nolint:golint,lll,misspell
|
//nolint:golint,lll,misspell
|
||||||
package util
|
package util
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
// An HTML5Entity struct represents HTML5 entitites.
|
// An HTML5Entity struct represents HTML5 entitites.
|
||||||
type HTML5Entity struct {
|
type HTML5Entity struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
@ -11,11 +13,18 @@ type HTML5Entity struct {
|
||||||
// LookUpHTML5EntityByName returns (an HTML5Entity, true) if an entity named
|
// LookUpHTML5EntityByName returns (an HTML5Entity, true) if an entity named
|
||||||
// given name is found, otherwise (nil, false).
|
// given name is found, otherwise (nil, false).
|
||||||
func LookUpHTML5EntityByName(name string) (*HTML5Entity, bool) {
|
func LookUpHTML5EntityByName(name string) (*HTML5Entity, bool) {
|
||||||
v, ok := html5entities[name]
|
v, ok := html5entities()[name]
|
||||||
return v, ok
|
return v, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
var html5entities = map[string]*HTML5Entity{
|
var html5entitiesOnce sync.Once // TODO: uses sync.OnceValue for future
|
||||||
|
|
||||||
|
var _html5entities map[string]*HTML5Entity
|
||||||
|
|
||||||
|
func html5entities() map[string]*HTML5Entity {
|
||||||
|
html5entitiesOnce.Do(func() {
|
||||||
|
_html5entities =
|
||||||
|
map[string]*HTML5Entity{
|
||||||
"AElig": {Name: "AElig", CodePoints: []int{198}, Characters: []byte{0xc3, 0x86}},
|
"AElig": {Name: "AElig", CodePoints: []int{198}, Characters: []byte{0xc3, 0x86}},
|
||||||
"AMP": {Name: "AMP", CodePoints: []int{38}, Characters: []byte{0x26}},
|
"AMP": {Name: "AMP", CodePoints: []int{38}, Characters: []byte{0x26}},
|
||||||
"Aacute": {Name: "Aacute", CodePoints: []int{193}, Characters: []byte{0xc3, 0x81}},
|
"Aacute": {Name: "Aacute", CodePoints: []int{193}, Characters: []byte{0xc3, 0x81}},
|
||||||
|
|
@ -2141,3 +2150,6 @@ var html5entities = map[string]*HTML5Entity{
|
||||||
"zwj": {Name: "zwj", CodePoints: []int{8205}, Characters: []byte{0xe2, 0x80, 0x8d}},
|
"zwj": {Name: "zwj", CodePoints: []int{8205}, Characters: []byte{0xe2, 0x80, 0x8d}},
|
||||||
"zwnj": {Name: "zwnj", CodePoints: []int{8204}, Characters: []byte{0xe2, 0x80, 0x8c}},
|
"zwnj": {Name: "zwnj", CodePoints: []int{8204}, Characters: []byte{0xe2, 0x80, 0x8c}},
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
return _html5entities
|
||||||
|
}
|
||||||
|
|
|
||||||
6
vendor/github.com/yuin/goldmark/util/util.go
generated
vendored
6
vendor/github.com/yuin/goldmark/util/util.go
generated
vendored
|
|
@ -166,7 +166,13 @@ func IndentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, pad
|
||||||
w := 0
|
w := 0
|
||||||
i := 0
|
i := 0
|
||||||
l := len(bs)
|
l := len(bs)
|
||||||
|
p := paddingv
|
||||||
for ; i < l; i++ {
|
for ; i < l; i++ {
|
||||||
|
if p > 0 {
|
||||||
|
p--
|
||||||
|
w++
|
||||||
|
continue
|
||||||
|
}
|
||||||
if bs[i] == '\t' && w < width {
|
if bs[i] == '\t' && w < width {
|
||||||
w += TabWidth(currentPos + w)
|
w += TabWidth(currentPos + w)
|
||||||
} else if bs[i] == ' ' && w < width {
|
} else if bs[i] == ' ' && w < width {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build !appengine && !js
|
//go:build !appengine && !js && !go1.21
|
||||||
// +build !appengine,!js
|
// +build !appengine,!js,!go1.21
|
||||||
|
|
||||||
package util
|
package util
|
||||||
|
|
||||||
18
vendor/github.com/yuin/goldmark/util/util_unsafe_go121.go
generated
vendored
Normal file
18
vendor/github.com/yuin/goldmark/util/util_unsafe_go121.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
//go:build !appengine && !js && go1.21
|
||||||
|
// +build !appengine,!js,go1.21
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BytesToReadOnlyString returns a string converted from given bytes.
|
||||||
|
func BytesToReadOnlyString(b []byte) string {
|
||||||
|
return unsafe.String(unsafe.SliceData(b), len(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToReadOnlyBytes returns bytes converted from given string.
|
||||||
|
func StringToReadOnlyBytes(s string) []byte {
|
||||||
|
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||||
|
}
|
||||||
4
vendor/go.mau.fi/util/dbutil/upgrades.go
vendored
4
vendor/go.mau.fi/util/dbutil/upgrades.go
vendored
|
|
@ -33,6 +33,10 @@ var ErrForeignTables = errors.New("the database contains foreign tables")
|
||||||
var ErrNotOwned = errors.New("the database is owned by")
|
var ErrNotOwned = errors.New("the database is owned by")
|
||||||
var ErrUnsupportedDialect = errors.New("unsupported database dialect")
|
var ErrUnsupportedDialect = errors.New("unsupported database dialect")
|
||||||
|
|
||||||
|
func DangerousInternalUpgradeVersionTable(ctx context.Context, db *Database) error {
|
||||||
|
return db.upgradeVersionTable(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Database) upgradeVersionTable(ctx context.Context) error {
|
func (db *Database) upgradeVersionTable(ctx context.Context) error {
|
||||||
if compatColumnExists, err := db.ColumnExists(ctx, db.VersionTable, "compat"); err != nil {
|
if compatColumnExists, err := db.ColumnExists(ctx, db.VersionTable, "compat"); err != nil {
|
||||||
return fmt.Errorf("failed to check if version table is up to date: %w", err)
|
return fmt.Errorf("failed to check if version table is up to date: %w", err)
|
||||||
|
|
|
||||||
26
vendor/go.mau.fi/util/exhttp/cors.go
vendored
Normal file
26
vendor/go.mau.fi/util/exhttp/cors.go
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package exhttp
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func AddCORSHeaders(w http.ResponseWriter) {
|
||||||
|
// Recommended CORS headers can be found in https://spec.matrix.org/v1.3/client-server-api/#web-browser-clients
|
||||||
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization")
|
||||||
|
w.Header().Set("Content-Security-Policy", "sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';")
|
||||||
|
// Allow browsers to cache above for 1 day
|
||||||
|
w.Header().Set("Access-Control-Max-Age", "86400")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CORSMiddleware adds CORS headers to the response and handles OPTIONS
|
||||||
|
// requests by returning 200 OK immediately.
|
||||||
|
func CORSMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
AddCORSHeaders(w)
|
||||||
|
if r.Method == http.MethodOptions {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
58
vendor/go.mau.fi/util/exhttp/handleerrors.go
vendored
Normal file
58
vendor/go.mau.fi/util/exhttp/handleerrors.go
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package exhttp
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type ErrorBodyGenerators struct {
|
||||||
|
NotFound func() []byte
|
||||||
|
MethodNotAllowed func() []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleErrors(next http.Handler, gen ErrorBodyGenerators) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
next.ServeHTTP(&bodyOverrider{
|
||||||
|
ResponseWriter: w,
|
||||||
|
statusNotFoundBodyGenerator: gen.NotFound,
|
||||||
|
statusMethodNotAllowedBodyGenerator: gen.MethodNotAllowed,
|
||||||
|
}, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type bodyOverrider struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
|
||||||
|
code int
|
||||||
|
override bool
|
||||||
|
|
||||||
|
statusNotFoundBodyGenerator func() []byte
|
||||||
|
statusMethodNotAllowedBodyGenerator func() []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ http.ResponseWriter = (*bodyOverrider)(nil)
|
||||||
|
|
||||||
|
func (b *bodyOverrider) WriteHeader(code int) {
|
||||||
|
if b.Header().Get("Content-Type") == "text/plain; charset=utf-8" {
|
||||||
|
b.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
b.override = true
|
||||||
|
}
|
||||||
|
|
||||||
|
b.code = code
|
||||||
|
b.ResponseWriter.WriteHeader(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bodyOverrider) Write(body []byte) (int, error) {
|
||||||
|
if b.override {
|
||||||
|
switch b.code {
|
||||||
|
case http.StatusNotFound:
|
||||||
|
if b.statusNotFoundBodyGenerator != nil {
|
||||||
|
body = b.statusNotFoundBodyGenerator()
|
||||||
|
}
|
||||||
|
case http.StatusMethodNotAllowed:
|
||||||
|
if b.statusMethodNotAllowedBodyGenerator != nil {
|
||||||
|
body = b.statusMethodNotAllowedBodyGenerator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.ResponseWriter.Write(body)
|
||||||
|
}
|
||||||
27
vendor/go.mau.fi/util/exhttp/json.go
vendored
Normal file
27
vendor/go.mau.fi/util/exhttp/json.go
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
package exhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WriteJSONResponse(w http.ResponseWriter, httpStatusCode int, jsonData any) {
|
||||||
|
AddCORSHeaders(w)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(httpStatusCode)
|
||||||
|
_ = json.NewEncoder(w).Encode(jsonData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteJSONData(w http.ResponseWriter, httpStatusCode int, data []byte) {
|
||||||
|
AddCORSHeaders(w)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(httpStatusCode)
|
||||||
|
_, _ = w.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteEmptyJSONResponse(w http.ResponseWriter, httpStatusCode int) {
|
||||||
|
AddCORSHeaders(w)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(httpStatusCode)
|
||||||
|
_, _ = w.Write([]byte("{}"))
|
||||||
|
}
|
||||||
31
vendor/go.mau.fi/util/exslices/cast.go
vendored
Normal file
31
vendor/go.mau.fi/util/exslices/cast.go
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2024 Tulir Asokan
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package exslices
|
||||||
|
|
||||||
|
func CastFunc[To, From any](source []From, conv func(From) To) []To {
|
||||||
|
result := make([]To, len(source))
|
||||||
|
for i, v := range source {
|
||||||
|
result[i] = conv(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func CastToString[To, From ~string](source []From) []To {
|
||||||
|
result := make([]To, len(source))
|
||||||
|
for i, v := range source {
|
||||||
|
result[i] = To(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func CastToAny[From any](source []From) []any {
|
||||||
|
result := make([]any, len(source))
|
||||||
|
for i, v := range source {
|
||||||
|
result[i] = v
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
28
vendor/go.mau.fi/util/exslices/chunk.go
vendored
Normal file
28
vendor/go.mau.fi/util/exslices/chunk.go
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) 2024 Tulir Asokan
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package exslices
|
||||||
|
|
||||||
|
// Chunk splits a slice into chunks of the given size.
|
||||||
|
//
|
||||||
|
// From https://github.com/golang/go/issues/53987#issuecomment-1224367139
|
||||||
|
//
|
||||||
|
// TODO remove this after slices.Chunk can be used (it'll probably be added in Go 1.23, so it can be used after 1.22 is EOL)
|
||||||
|
func Chunk[T any](slice []T, size int) (chunks [][]T) {
|
||||||
|
if size < 1 {
|
||||||
|
panic("chunk size cannot be less than 1")
|
||||||
|
}
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
next := i * size
|
||||||
|
if len(slice[next:]) > size {
|
||||||
|
end := next + size
|
||||||
|
chunks = append(chunks, slice[next:end:end])
|
||||||
|
} else {
|
||||||
|
chunks = append(chunks, slice[i*size:])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
vendor/go.mau.fi/util/exslices/deduplicate.go
vendored
Normal file
23
vendor/go.mau.fi/util/exslices/deduplicate.go
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2024 Tulir Asokan
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package exslices
|
||||||
|
|
||||||
|
// DeduplicateUnsorted removes duplicates from the given slice without requiring that the input slice is sorted.
|
||||||
|
// The order of the output will be the same as the input.
|
||||||
|
//
|
||||||
|
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.Compact].
|
||||||
|
func DeduplicateUnsorted[T comparable](s []T) []T {
|
||||||
|
seen := make(map[T]struct{}, len(s))
|
||||||
|
result := make([]T, 0, len(s))
|
||||||
|
for _, item := range s {
|
||||||
|
if _, ok := seen[item]; !ok {
|
||||||
|
seen[item] = struct{}{}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
63
vendor/go.mau.fi/util/exslices/diff.go
vendored
Normal file
63
vendor/go.mau.fi/util/exslices/diff.go
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright (c) 2023 Tulir Asokan
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package exslices
|
||||||
|
|
||||||
|
// SortedDiff returns the difference between two already-sorted slices, with the help of the given comparison function.
|
||||||
|
// The output will be in the same order as the input, which means it'll be sorted.
|
||||||
|
func SortedDiff[T any](a, b []T, compare func(a, b T) int) (uniqueToA, uniqueToB []T) {
|
||||||
|
uniqueToA = make([]T, 0, len(a))
|
||||||
|
uniqueToB = make([]T, 0, len(b))
|
||||||
|
|
||||||
|
var i, j int
|
||||||
|
for {
|
||||||
|
if j >= len(b) {
|
||||||
|
uniqueToA = append(uniqueToA, a[i:]...)
|
||||||
|
break
|
||||||
|
} else if i >= len(a) {
|
||||||
|
uniqueToB = append(uniqueToB, b[j:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := compare(a[i], b[j])
|
||||||
|
if c < 0 {
|
||||||
|
uniqueToA = append(uniqueToA, a[i])
|
||||||
|
i++
|
||||||
|
} else if c > 0 {
|
||||||
|
uniqueToB = append(uniqueToB, b[j])
|
||||||
|
j++
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff returns the difference between two slices. The slices may contain duplicates and don't need to be sorted.
|
||||||
|
// The output will not be sorted, but is guaranteed to not contain any duplicates.
|
||||||
|
func Diff[T comparable](a, b []T) (uniqueToA, uniqueToB []T) {
|
||||||
|
maxLen := len(a)
|
||||||
|
if len(b) > maxLen {
|
||||||
|
maxLen = len(b)
|
||||||
|
}
|
||||||
|
collector := make(map[T]uint8, maxLen)
|
||||||
|
for _, item := range a {
|
||||||
|
collector[item] |= 0b01
|
||||||
|
}
|
||||||
|
for _, item := range b {
|
||||||
|
collector[item] |= 0b10
|
||||||
|
}
|
||||||
|
uniqueToA = make([]T, 0, maxLen)
|
||||||
|
uniqueToB = make([]T, 0, maxLen)
|
||||||
|
for item, mask := range collector {
|
||||||
|
if mask == 0b01 {
|
||||||
|
uniqueToA = append(uniqueToA, item)
|
||||||
|
} else if mask == 0b10 {
|
||||||
|
uniqueToB = append(uniqueToB, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
53
vendor/go.mau.fi/util/exsync/syncset.go
vendored
53
vendor/go.mau.fi/util/exsync/syncset.go
vendored
|
|
@ -72,6 +72,20 @@ func (s *Set[T]) Has(item T) bool {
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pop removes the given item from the set. The return value is true if the item was in the set, or false otherwise.
|
||||||
|
func (s *Set[T]) Pop(item T) bool {
|
||||||
|
if s == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.l.Lock()
|
||||||
|
_, exists := s.m[item]
|
||||||
|
if exists {
|
||||||
|
delete(s.m, item)
|
||||||
|
}
|
||||||
|
s.l.Unlock()
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
// Remove removes the given item from the set.
|
// Remove removes the given item from the set.
|
||||||
func (s *Set[T]) Remove(item T) {
|
func (s *Set[T]) Remove(item T) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
|
|
@ -81,3 +95,42 @@ func (s *Set[T]) Remove(item T) {
|
||||||
delete(s.m, item)
|
delete(s.m, item)
|
||||||
s.l.Unlock()
|
s.l.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplaceAll replaces this set with the given set. If the given set is nil, the set is cleared.
|
||||||
|
func (s *Set[T]) ReplaceAll(newSet *Set[T]) {
|
||||||
|
if s == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.l.Lock()
|
||||||
|
if newSet == nil {
|
||||||
|
s.m = make(map[T]empty)
|
||||||
|
} else {
|
||||||
|
s.m = newSet.m
|
||||||
|
}
|
||||||
|
s.l.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set[T]) Size() int {
|
||||||
|
if s == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
s.l.RLock()
|
||||||
|
size := len(s.m)
|
||||||
|
s.l.RUnlock()
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set[T]) AsList() []T {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
s.l.RLock()
|
||||||
|
list := make([]T, len(s.m))
|
||||||
|
i := 0
|
||||||
|
for item := range s.m {
|
||||||
|
list[i] = item
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
s.l.RUnlock()
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
|
||||||
100
vendor/go.mau.fi/util/glob/glob.go
vendored
Normal file
100
vendor/go.mau.fi/util/glob/glob.go
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
// Package glob implements very simple glob pattern matching used in various parts of the Matrix spec,
|
||||||
|
// such as push rules and moderation policy lists.
|
||||||
|
//
|
||||||
|
// See https://spec.matrix.org/v1.11/appendices/#glob-style-matching for more info.
|
||||||
|
package glob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Glob interface {
|
||||||
|
Match(string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ Glob = ExactGlob("")
|
||||||
|
_ Glob = PrefixGlob("")
|
||||||
|
_ Glob = SuffixGlob("")
|
||||||
|
_ Glob = ContainsGlob("")
|
||||||
|
_ Glob = (*PrefixAndSuffixGlob)(nil)
|
||||||
|
_ Glob = (*PrefixSuffixAndContainsGlob)(nil)
|
||||||
|
_ Glob = (*RegexGlob)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Compile compiles a glob pattern into an object that can be used to efficiently match strings against the pattern.
|
||||||
|
//
|
||||||
|
// Simple globs will be converted into prefix/suffix/contains checks, while complicated ones will be compiled as regex.
|
||||||
|
func Compile(pattern string) Glob {
|
||||||
|
pattern = Simplify(pattern)
|
||||||
|
g := compileSimple(pattern)
|
||||||
|
if g != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
g, _ = CompileRegex(pattern)
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompileWithImplicitContains is a wrapper for Compile which will replace exact matches with contains matches.
|
||||||
|
// i.e. if the pattern has no wildcards, it will be treated as if it was surrounded in asterisks (`foo` -> `*foo*`).
|
||||||
|
func CompileWithImplicitContains(pattern string) Glob {
|
||||||
|
g := Compile(pattern)
|
||||||
|
if _, isExact := g.(ExactGlob); isExact {
|
||||||
|
return ContainsGlob(pattern)
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompileSimple compiles a glob pattern into one of the non-regex forms.
|
||||||
|
//
|
||||||
|
// If the pattern can't be compiled into a simple form, it returns nil.
|
||||||
|
func CompileSimple(pattern string) Glob {
|
||||||
|
return compileSimple(Simplify(pattern))
|
||||||
|
}
|
||||||
|
|
||||||
|
func compileSimple(pattern string) Glob {
|
||||||
|
if strings.ContainsRune(pattern, '?') {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch strings.Count(pattern, "*") {
|
||||||
|
case 0:
|
||||||
|
return ExactGlob(pattern)
|
||||||
|
case 1:
|
||||||
|
if strings.HasPrefix(pattern, "*") {
|
||||||
|
return SuffixGlob(pattern[1:])
|
||||||
|
} else if strings.HasSuffix(pattern, "*") {
|
||||||
|
return PrefixGlob(pattern[:len(pattern)-1])
|
||||||
|
} else {
|
||||||
|
parts := strings.Split(pattern, "*")
|
||||||
|
return PrefixAndSuffixGlob{
|
||||||
|
Prefix: parts[0],
|
||||||
|
Suffix: parts[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if strings.HasPrefix(pattern, "*") && strings.HasSuffix(pattern, "*") {
|
||||||
|
return ContainsGlob(pattern[1 : len(pattern)-1])
|
||||||
|
}
|
||||||
|
parts := strings.Split(pattern, "*")
|
||||||
|
return PrefixSuffixAndContainsGlob{
|
||||||
|
Prefix: parts[0],
|
||||||
|
Contains: parts[1],
|
||||||
|
Suffix: parts[2],
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sqlCompiler = strings.NewReplacer(
|
||||||
|
`\`, `\\`,
|
||||||
|
`%`, `\%`,
|
||||||
|
`_`, `\_`,
|
||||||
|
`*`, `%`,
|
||||||
|
`?`, `_`,
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToSQL converts a Matrix glob pattern to a SQL LIKE pattern.
|
||||||
|
func ToSQL(pattern string) string {
|
||||||
|
return sqlCompiler.Replace(Simplify(pattern))
|
||||||
|
}
|
||||||
43
vendor/go.mau.fi/util/glob/regex.go
vendored
Normal file
43
vendor/go.mau.fi/util/glob/regex.go
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package glob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RegexGlob struct {
|
||||||
|
regex *regexp.Regexp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rg *RegexGlob) Match(s string) bool {
|
||||||
|
return rg.regex.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CompileRegex(pattern string) (*RegexGlob, error) {
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.WriteRune('^')
|
||||||
|
for _, part := range SplitPattern(pattern) {
|
||||||
|
if strings.ContainsRune(part, '*') || strings.ContainsRune(part, '?') {
|
||||||
|
questions := strings.Count(part, "?")
|
||||||
|
star := strings.ContainsRune(part, '*')
|
||||||
|
if star {
|
||||||
|
if questions > 0 {
|
||||||
|
_, _ = fmt.Fprintf(&buf, ".{%d,}", questions)
|
||||||
|
} else {
|
||||||
|
buf.WriteString(".*")
|
||||||
|
}
|
||||||
|
} else if questions > 0 {
|
||||||
|
_, _ = fmt.Fprintf(&buf, ".{%d}", questions)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf.WriteString(regexp.QuoteMeta(part))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteRune('$')
|
||||||
|
regex, err := regexp.Compile(buf.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &RegexGlob{regex}, nil
|
||||||
|
}
|
||||||
62
vendor/go.mau.fi/util/glob/simple.go
vendored
Normal file
62
vendor/go.mau.fi/util/glob/simple.go
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
package glob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExactGlob is the result of [Compile] when the pattern contains no glob characters.
|
||||||
|
// It uses a simple string comparison to match.
|
||||||
|
type ExactGlob string
|
||||||
|
|
||||||
|
func (eg ExactGlob) Match(s string) bool {
|
||||||
|
return string(eg) == s
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuffixGlob is the result of [Compile] when the pattern only has one `*` at the beginning.
|
||||||
|
// It uses [strings.HasSuffix] to match.
|
||||||
|
type SuffixGlob string
|
||||||
|
|
||||||
|
func (sg SuffixGlob) Match(s string) bool {
|
||||||
|
return strings.HasSuffix(s, string(sg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrefixGlob is the result of [Compile] when the pattern only has one `*` at the end.
|
||||||
|
// It uses [strings.HasPrefix] to match.
|
||||||
|
type PrefixGlob string
|
||||||
|
|
||||||
|
func (pg PrefixGlob) Match(s string) bool {
|
||||||
|
return strings.HasPrefix(s, string(pg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsGlob is the result of [Compile] when the pattern has two `*`s, one at the beginning and one at the end.
|
||||||
|
// It uses [strings.Contains] to match.
|
||||||
|
//
|
||||||
|
// When there are exactly two `*`s, but they're not surrounding the string, the pattern is compiled as a [PrefixSuffixAndContainsGlob] instead.
|
||||||
|
type ContainsGlob string
|
||||||
|
|
||||||
|
func (cg ContainsGlob) Match(s string) bool {
|
||||||
|
return strings.Contains(s, string(cg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrefixAndSuffixGlob is the result of [Compile] when the pattern only has one `*` in the middle.
|
||||||
|
type PrefixAndSuffixGlob struct {
|
||||||
|
Prefix string
|
||||||
|
Suffix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psg PrefixAndSuffixGlob) Match(s string) bool {
|
||||||
|
return strings.HasPrefix(s, psg.Prefix) && strings.HasSuffix(s[len(psg.Prefix):], psg.Suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrefixSuffixAndContainsGlob is the result of [Compile] when the pattern has two `*`s which are not surrounding the rest of the pattern.
|
||||||
|
type PrefixSuffixAndContainsGlob struct {
|
||||||
|
Prefix string
|
||||||
|
Suffix string
|
||||||
|
Contains string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psacg PrefixSuffixAndContainsGlob) Match(s string) bool {
|
||||||
|
return strings.HasPrefix(s, psacg.Prefix) &&
|
||||||
|
strings.HasSuffix(s[len(psacg.Prefix):], psacg.Suffix) &&
|
||||||
|
strings.Contains(s[len(psacg.Prefix):len(s)-len(psacg.Suffix)], psacg.Contains)
|
||||||
|
}
|
||||||
42
vendor/go.mau.fi/util/glob/util.go
vendored
Normal file
42
vendor/go.mau.fi/util/glob/util.go
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
package glob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var redundantStarRegex = regexp.MustCompile(`\*{2,}`)
|
||||||
|
var maybeRedundantQuestionRegex = regexp.MustCompile(`[*?]{2,}`)
|
||||||
|
var wildcardRegex = regexp.MustCompile(`[*?]+`)
|
||||||
|
|
||||||
|
func SplitPattern(pattern string) []string {
|
||||||
|
indexes := wildcardRegex.FindAllStringIndex(pattern, -1)
|
||||||
|
if len(indexes) == 0 {
|
||||||
|
return []string{pattern}
|
||||||
|
}
|
||||||
|
parts := make([]string, 0, len(indexes)+1)
|
||||||
|
start := 0
|
||||||
|
for _, part := range indexes {
|
||||||
|
end := part[0]
|
||||||
|
if end > start {
|
||||||
|
parts = append(parts, pattern[start:end])
|
||||||
|
}
|
||||||
|
parts = append(parts, pattern[part[0]:part[1]])
|
||||||
|
start = part[1]
|
||||||
|
}
|
||||||
|
if start < len(pattern) {
|
||||||
|
parts = append(parts, pattern[start:])
|
||||||
|
}
|
||||||
|
return parts
|
||||||
|
}
|
||||||
|
|
||||||
|
func Simplify(pattern string) string {
|
||||||
|
pattern = redundantStarRegex.ReplaceAllString(pattern, "*")
|
||||||
|
pattern = maybeRedundantQuestionRegex.ReplaceAllStringFunc(pattern, func(s string) string {
|
||||||
|
if !strings.ContainsRune(s, '*') {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return strings.Repeat("?", strings.Count(s, "?")) + "*"
|
||||||
|
})
|
||||||
|
return pattern
|
||||||
|
}
|
||||||
17
vendor/go.mau.fi/util/ptr/ptr.go
vendored
17
vendor/go.mau.fi/util/ptr/ptr.go
vendored
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
package ptr
|
package ptr
|
||||||
|
|
||||||
|
// Clone creates a shallow copy of the given pointer.
|
||||||
func Clone[T any](val *T) *T {
|
func Clone[T any](val *T) *T {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -14,10 +15,26 @@ func Clone[T any](val *T) *T {
|
||||||
return &valCopy
|
return &valCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ptr returns a pointer to the given value.
|
||||||
func Ptr[T any](val T) *T {
|
func Ptr[T any](val T) *T {
|
||||||
return &val
|
return &val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NonZero returns a pointer to the given comparable value, unless the value is the type's zero value.
|
||||||
|
func NonZero[T comparable](val T) *T {
|
||||||
|
var zero T
|
||||||
|
return NonDefault(val, zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NonDefault returns a pointer to the first parameter, unless it is equal to the second parameter.
|
||||||
|
func NonDefault[T comparable](val, def T) *T {
|
||||||
|
if val == def {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Val returns the value of the given pointer, or the zero value of the type if the pointer is nil.
|
||||||
func Val[T any](ptr *T) (val T) {
|
func Val[T any](ptr *T) (val T) {
|
||||||
if ptr != nil {
|
if ptr != nil {
|
||||||
val = *ptr
|
val = *ptr
|
||||||
|
|
|
||||||
2972
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
2972
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
5089
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
5089
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
1601
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
generated
vendored
1601
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
131
vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s
generated
vendored
131
vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s
generated
vendored
|
|
@ -1,108 +1,93 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
// Code generated by command: go run sum_amd64_asm.go -out ../sum_amd64.s -pkg poly1305. DO NOT EDIT.
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build gc && !purego
|
//go:build gc && !purego
|
||||||
|
|
||||||
#include "textflag.h"
|
// func update(state *macState, msg []byte)
|
||||||
|
|
||||||
#define POLY1305_ADD(msg, h0, h1, h2) \
|
|
||||||
ADDQ 0(msg), h0; \
|
|
||||||
ADCQ 8(msg), h1; \
|
|
||||||
ADCQ $1, h2; \
|
|
||||||
LEAQ 16(msg), msg
|
|
||||||
|
|
||||||
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
|
|
||||||
MOVQ r0, AX; \
|
|
||||||
MULQ h0; \
|
|
||||||
MOVQ AX, t0; \
|
|
||||||
MOVQ DX, t1; \
|
|
||||||
MOVQ r0, AX; \
|
|
||||||
MULQ h1; \
|
|
||||||
ADDQ AX, t1; \
|
|
||||||
ADCQ $0, DX; \
|
|
||||||
MOVQ r0, t2; \
|
|
||||||
IMULQ h2, t2; \
|
|
||||||
ADDQ DX, t2; \
|
|
||||||
\
|
|
||||||
MOVQ r1, AX; \
|
|
||||||
MULQ h0; \
|
|
||||||
ADDQ AX, t1; \
|
|
||||||
ADCQ $0, DX; \
|
|
||||||
MOVQ DX, h0; \
|
|
||||||
MOVQ r1, t3; \
|
|
||||||
IMULQ h2, t3; \
|
|
||||||
MOVQ r1, AX; \
|
|
||||||
MULQ h1; \
|
|
||||||
ADDQ AX, t2; \
|
|
||||||
ADCQ DX, t3; \
|
|
||||||
ADDQ h0, t2; \
|
|
||||||
ADCQ $0, t3; \
|
|
||||||
\
|
|
||||||
MOVQ t0, h0; \
|
|
||||||
MOVQ t1, h1; \
|
|
||||||
MOVQ t2, h2; \
|
|
||||||
ANDQ $3, h2; \
|
|
||||||
MOVQ t2, t0; \
|
|
||||||
ANDQ $0xFFFFFFFFFFFFFFFC, t0; \
|
|
||||||
ADDQ t0, h0; \
|
|
||||||
ADCQ t3, h1; \
|
|
||||||
ADCQ $0, h2; \
|
|
||||||
SHRQ $2, t3, t2; \
|
|
||||||
SHRQ $2, t3; \
|
|
||||||
ADDQ t2, h0; \
|
|
||||||
ADCQ t3, h1; \
|
|
||||||
ADCQ $0, h2
|
|
||||||
|
|
||||||
// func update(state *[7]uint64, msg []byte)
|
|
||||||
TEXT ·update(SB), $0-32
|
TEXT ·update(SB), $0-32
|
||||||
MOVQ state+0(FP), DI
|
MOVQ state+0(FP), DI
|
||||||
MOVQ msg_base+8(FP), SI
|
MOVQ msg_base+8(FP), SI
|
||||||
MOVQ msg_len+16(FP), R15
|
MOVQ msg_len+16(FP), R15
|
||||||
|
MOVQ (DI), R8
|
||||||
MOVQ 0(DI), R8 // h0
|
MOVQ 8(DI), R9
|
||||||
MOVQ 8(DI), R9 // h1
|
MOVQ 16(DI), R10
|
||||||
MOVQ 16(DI), R10 // h2
|
MOVQ 24(DI), R11
|
||||||
MOVQ 24(DI), R11 // r0
|
MOVQ 32(DI), R12
|
||||||
MOVQ 32(DI), R12 // r1
|
CMPQ R15, $0x10
|
||||||
|
|
||||||
CMPQ R15, $16
|
|
||||||
JB bytes_between_0_and_15
|
JB bytes_between_0_and_15
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
POLY1305_ADD(SI, R8, R9, R10)
|
ADDQ (SI), R8
|
||||||
|
ADCQ 8(SI), R9
|
||||||
|
ADCQ $0x01, R10
|
||||||
|
LEAQ 16(SI), SI
|
||||||
|
|
||||||
multiply:
|
multiply:
|
||||||
POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
|
MOVQ R11, AX
|
||||||
SUBQ $16, R15
|
MULQ R8
|
||||||
CMPQ R15, $16
|
MOVQ AX, BX
|
||||||
|
MOVQ DX, CX
|
||||||
|
MOVQ R11, AX
|
||||||
|
MULQ R9
|
||||||
|
ADDQ AX, CX
|
||||||
|
ADCQ $0x00, DX
|
||||||
|
MOVQ R11, R13
|
||||||
|
IMULQ R10, R13
|
||||||
|
ADDQ DX, R13
|
||||||
|
MOVQ R12, AX
|
||||||
|
MULQ R8
|
||||||
|
ADDQ AX, CX
|
||||||
|
ADCQ $0x00, DX
|
||||||
|
MOVQ DX, R8
|
||||||
|
MOVQ R12, R14
|
||||||
|
IMULQ R10, R14
|
||||||
|
MOVQ R12, AX
|
||||||
|
MULQ R9
|
||||||
|
ADDQ AX, R13
|
||||||
|
ADCQ DX, R14
|
||||||
|
ADDQ R8, R13
|
||||||
|
ADCQ $0x00, R14
|
||||||
|
MOVQ BX, R8
|
||||||
|
MOVQ CX, R9
|
||||||
|
MOVQ R13, R10
|
||||||
|
ANDQ $0x03, R10
|
||||||
|
MOVQ R13, BX
|
||||||
|
ANDQ $-4, BX
|
||||||
|
ADDQ BX, R8
|
||||||
|
ADCQ R14, R9
|
||||||
|
ADCQ $0x00, R10
|
||||||
|
SHRQ $0x02, R14, R13
|
||||||
|
SHRQ $0x02, R14
|
||||||
|
ADDQ R13, R8
|
||||||
|
ADCQ R14, R9
|
||||||
|
ADCQ $0x00, R10
|
||||||
|
SUBQ $0x10, R15
|
||||||
|
CMPQ R15, $0x10
|
||||||
JAE loop
|
JAE loop
|
||||||
|
|
||||||
bytes_between_0_and_15:
|
bytes_between_0_and_15:
|
||||||
TESTQ R15, R15
|
TESTQ R15, R15
|
||||||
JZ done
|
JZ done
|
||||||
MOVQ $1, BX
|
MOVQ $0x00000001, BX
|
||||||
XORQ CX, CX
|
XORQ CX, CX
|
||||||
XORQ R13, R13
|
XORQ R13, R13
|
||||||
ADDQ R15, SI
|
ADDQ R15, SI
|
||||||
|
|
||||||
flush_buffer:
|
flush_buffer:
|
||||||
SHLQ $8, BX, CX
|
SHLQ $0x08, BX, CX
|
||||||
SHLQ $8, BX
|
SHLQ $0x08, BX
|
||||||
MOVB -1(SI), R13
|
MOVB -1(SI), R13
|
||||||
XORQ R13, BX
|
XORQ R13, BX
|
||||||
DECQ SI
|
DECQ SI
|
||||||
DECQ R15
|
DECQ R15
|
||||||
JNZ flush_buffer
|
JNZ flush_buffer
|
||||||
|
|
||||||
ADDQ BX, R8
|
ADDQ BX, R8
|
||||||
ADCQ CX, R9
|
ADCQ CX, R9
|
||||||
ADCQ $0, R10
|
ADCQ $0x00, R10
|
||||||
MOVQ $16, R15
|
MOVQ $0x00000010, R15
|
||||||
JMP multiply
|
JMP multiply
|
||||||
|
|
||||||
done:
|
done:
|
||||||
MOVQ R8, 0(DI)
|
MOVQ R8, (DI)
|
||||||
MOVQ R9, 8(DI)
|
MOVQ R9, 8(DI)
|
||||||
MOVQ R10, 16(DI)
|
MOVQ R10, 16(DI)
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
4
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
|
|
@ -510,8 +510,8 @@ userAuthLoop:
|
||||||
if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
|
if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
authErrs = append(authErrs, discMsg)
|
||||||
return nil, discMsg
|
return nil, &ServerAuthError{Errors: authErrs}
|
||||||
}
|
}
|
||||||
|
|
||||||
var userAuthReq userAuthRequestMsg
|
var userAuthReq userAuthRequestMsg
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue