Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add code of sidetree core go #11

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ run:
tests: true
build-tags: [""]
skip-dirs:
- pkg/crypto/primitive/bbs12381g2pub/internal/kilic/bls12-381
- method/sidetreelongform/sidetree-core/docutil

output:
format: colored-line-number
Expand Down
29 changes: 29 additions & 0 deletions doc/json/canonicalizer/canonicalizer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package canonicalizer

import (
"encoding/json"

"github.com/trustbloc/did-go/doc/json/canonicalizer/internal/jsoncanonicalizer"
)

// MarshalCanonical is using JCS RFC canonicalization.
func MarshalCanonical(value interface{}) ([]byte, error) {
valueBytes, ok := value.([]byte)

if !ok {
var err error

valueBytes, err = json.Marshal(value)
if err != nil {
return nil, err
}
}

return jsoncanonicalizer.Transform(valueBytes)
}
43 changes: 43 additions & 0 deletions doc/json/canonicalizer/canonicalizer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package canonicalizer

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestMarshalCanonical(t *testing.T) {
t.Run("success", func(t *testing.T) {
test := struct {
Beta string `json:"beta"`
Alpha string `json:"alpha"`
}{
Beta: "beta",
Alpha: "alpha",
}

result, err := MarshalCanonical(test)
require.NoError(t, err)
require.Equal(t, string(result), `{"alpha":"alpha","beta":"beta"}`)
})

t.Run("success - accepts bytes", func(t *testing.T) {
result, err := MarshalCanonical([]byte(`{"beta":"beta","alpha":"alpha"}`))
require.NoError(t, err)
require.Equal(t, string(result), `{"alpha":"alpha","beta":"beta"}`)
})

t.Run("marshal error", func(t *testing.T) {
var c chan int
result, err := MarshalCanonical(c)
require.Error(t, err)
require.Empty(t, result)
require.Contains(t, err.Error(), "json: unsupported type: chan int")
})
}
4 changes: 4 additions & 0 deletions doc/json/canonicalizer/internal/jsoncanonicalizer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## JSON Cononicalizer

The files in this folder are copied AS-IS from [Cyberphone JSON Canonicalization Go Library](https://github.com/cyberphone/json-canonicalization/tree/master/go/src/webpki.org/jsoncanonicalizer).
The licence details are available at [LICENCE](https://github.com/cyberphone/json-canonicalization/blob/master/LICENSE).
95 changes: 95 additions & 0 deletions doc/json/canonicalizer/internal/jsoncanonicalizer/es6numfmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//
// Copyright 2006-2019 WebPKI.org (http://webpki.org).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// This package converts numbers in IEEE-754 double precision into the
// format specified for JSON in EcmaScript Version 6 and forward.
// The core application for this is canonicalization:
// https://tools.ietf.org/html/draft-rundgren-json-canonicalization-scheme-02

package jsoncanonicalizer

import (
"errors"
"math"
"strconv"
"strings"
)

const invalidPattern uint64 = 0x7ff0000000000000

func NumberToJSON(ieeeF64 float64) (res string, err error) { //nolint:funlen,gocyclo,golint
ieeeU64 := math.Float64bits(ieeeF64)

// Special case: NaN and Infinity are invalid in JSON
if (ieeeU64 & invalidPattern) == invalidPattern {
return "null", errors.New("Invalid JSON number: " + strconv.FormatUint(ieeeU64, 16))
}

// Special case: eliminate "-0" as mandated by the ES6-JSON/JCS specifications
if ieeeF64 == 0 { // Right, this line takes both -0 and 0
return "0", nil
}

// Deal with the sign separately
var sign string = ""

if ieeeF64 < 0 {
ieeeF64 = -ieeeF64
sign = "-"
}

// ES6 has a unique "g" format
var format byte = 'e'
if ieeeF64 < 1e+21 && ieeeF64 >= 1e-6 {
format = 'f'
}

// The following should (in "theory") do the trick:
es6Formatted := strconv.FormatFloat(ieeeF64, format, -1, 64)

// Unfortunately Go version 1.11.4 is a bit buggy with respect to
// rounding for -1 precision which is dealt with below.
// https://github.com/golang/go/issues/29491
exponent := strings.IndexByte(es6Formatted, 'e')
//nolint:nestif
if exponent > 0 {
gform := strconv.FormatFloat(ieeeF64, 'g', 17, 64)
if len(gform) == len(es6Formatted) {
// "g" occasionally produces another result which also is the correct one
es6Formatted = gform
}
// Go outputs "1e+09" which must be rewritten as "1e+9"
if es6Formatted[exponent+2] == '0' {
es6Formatted = es6Formatted[:exponent+2] + es6Formatted[exponent+3:]
}
} else if strings.IndexByte(es6Formatted, '.') < 0 && len(es6Formatted) >= 12 {
i := len(es6Formatted)
for es6Formatted[i-1] == '0' {
i--
}
if i != len(es6Formatted) {
fix := strconv.FormatFloat(ieeeF64, 'f', 0, 64)
if fix[i] >= '5' {
// "f" with precision 0 occasionally produces another result which also is
// the correct one although it must be rounded to match the -1 precision
// (which fortunately seems to be correct with respect to trailing zeroes)
es6Formatted = fix[:i-1] + string(fix[i-1]+1) + es6Formatted[i:]
}
}
}

return sign + es6Formatted, nil
}
Loading
Loading