Skip to content

Commit

Permalink
Merge branch 'release/v1.18.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
algojack committed Jul 25, 2022
2 parents fae5b08 + 373fcc8 commit c5290bb
Show file tree
Hide file tree
Showing 14 changed files with 350 additions and 40 deletions.
20 changes: 20 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
changelog:
exclude:
labels:
- Skip-Release-Notes
categories:
- title: Bugfixes
labels:
- Bug-Fix
- title: New Features
labels:
- New Feature
- title: Enhancements
labels:
- Enhancement
- title: Not Yet Enabled
labels:
- Not-Yet-Enabled
- title: Other
labels:
- "*"
24 changes: 24 additions & 0 deletions .github/workflows/pr-type-category.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Check PR category and type
on:
pull_request:
branches:
- develop
types: [opened, synchronize, reopened, labeled, unlabeled, edited]
jobs:
check_label:
runs-on: ubuntu-latest
name: Check PR Category and Type
steps:
- name: Checking for correct number of required github pr labels
uses: mheap/github-action-required-labels@v2
with:
mode: exactly
count: 1
labels: "New Feature, Enhancement, Bug-Fix, Not-Yet-Enabled, Skip-Release-Notes"

- name: "Checking for PR Category in PR title. Should be like '<category>: <pr title>'."
run: |
if [[ ! "${{ github.event.pull_request.title }}" =~ ^.{2,}\:.{2,} ]]; then
echo "## PR Category is missing from PR title. Please add it like '<category>: <pr title>'." >> GITHUB_STEP_SUMMARY
exit 1
fi
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# 1.18.0

## What's Changed

### New Features
* Dev Tools: Source map decoder by @barnjamin in https://github.com/algorand/go-algorand-sdk/pull/335

### Enhancements
* Github-Actions: Adding pr title and label checks by @algojack in https://github.com/algorand/go-algorand-sdk/pull/336

**Full Changelog**: https://github.com/algorand/go-algorand-sdk/compare/v1.17.0...v1.18.0


# 1.17.0

## What's Changed
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ test:

unit:
go test $(TEST_SOURCES_NO_CUCUMBER)
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@unit.offline,@unit.algod,@unit.indexer,@unit.transactions.keyreg,@unit.rekey,@unit.tealsign,@unit.dryrun,@unit.responses,@unit.applications,@unit.transactions,@unit.indexer.rekey,@unit.responses.messagepack,@unit.responses.231,@unit.responses.messagepack.231,@unit.responses.genesis,@unit.feetest,@unit.indexer.logs,@unit.abijson,@unit.abijson.byname,@unit.transactions.payment,@unit.atomic_transaction_composer,@unit.responses.unlimited_assets,@unit.indexer.ledger_refactoring,@unit.algod.ledger_refactoring,@unit.dryrun.trace.application" --test.v .
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@unit.sourcemap,@unit.offline,@unit.algod,@unit.indexer,@unit.transactions.keyreg,@unit.rekey,@unit.tealsign,@unit.dryrun,@unit.responses,@unit.applications,@unit.transactions,@unit.indexer.rekey,@unit.responses.messagepack,@unit.responses.231,@unit.responses.messagepack.231,@unit.responses.genesis,@unit.feetest,@unit.indexer.logs,@unit.abijson,@unit.abijson.byname,@unit.transactions.payment,@unit.atomic_transaction_composer,@unit.responses.unlimited_assets,@unit.indexer.ledger_refactoring,@unit.algod.ledger_refactoring,@unit.dryrun.trace.application" --test.v .

integration:
go test $(TEST_SOURCES_NO_CUCUMBER)
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@algod,@assets,@auction,@kmd,@send,@indexer,@rekey,@send.keyregtxn,@dryrun,@compile,@applications.verified,@indexer.applications,@indexer.231,@abi,@c2c" --test.v .
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@algod,@assets,@auction,@kmd,@send,@indexer,@rekey,@send.keyregtxn,@dryrun,@compile,@applications.verified,@indexer.applications,@indexer.231,@abi,@c2c,@compile.sourcemap" --test.v .

docker-test:
./test/docker/run_docker.sh
Expand Down
4 changes: 2 additions & 2 deletions client/v2/algod/algod.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func (c *Client) getRaw(ctx context.Context, path string, body interface{}, head
// post sends a POST request to the given path with the given request object.
// No query parameters will be sent if request is nil.
// response must be a pointer to an object as post writes the response there.
func (c *Client) post(ctx context.Context, response interface{}, path string, body interface{}, headers []*common.Header) error {
return (*common.Client)(c).Post(ctx, response, path, body, headers)
func (c *Client) post(ctx context.Context, response interface{}, path string, params interface{}, headers []*common.Header, body interface{}) error {
return (*common.Client)(c).Post(ctx, response, path, params, headers, body)
}

// MakeClient is the factory for constructing a ClientV2 for a given endpoint.
Expand Down
3 changes: 1 addition & 2 deletions client/v2/algod/dryrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ func (s *TealDryRun) Do(
ctx context.Context,
headers ...*common.Header,
) (response models.DryrunResponse, err error) {
err = s.c.post(ctx, &response,
"/v2/teal/dryrun", s.rawobj, headers)
err = s.c.post(ctx, &response, "/v2/teal/dryrun", nil, headers, s.rawobj)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/rawTransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (s *SendRawTransaction) Do(ctx context.Context, headers ...*common.Header)
if addContentType {
headers = append(headers, &common.Header{"Content-Type", "application/x-binary"})
}
err = s.c.post(ctx, &response, "/v2/transactions", s.rawtxn, headers)
err = s.c.post(ctx, &response, "/v2/transactions", nil, headers, s.rawtxn)
txid = response.Txid
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/tealCompile.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ func (s *TealCompile) Sourcemap(Sourcemap bool) *TealCompile {

// Do performs the HTTP request
func (s *TealCompile) Do(ctx context.Context, headers ...*common.Header) (response models.CompileResponse, err error) {
err = s.c.post(ctx, &response, "/v2/teal/compile", s.source, headers)
err = s.c.post(ctx, &response, "/v2/teal/compile", s.p, headers, s.source)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/tealDryrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ type TealDryrun struct {

// Do performs the HTTP request
func (s *TealDryrun) Do(ctx context.Context, headers ...*common.Header) (response models.DryrunResponse, err error) {
err = s.c.post(ctx, &response, "/v2/teal/dryrun", msgpack.Encode(&s.request), headers)
err = s.c.post(ctx, &response, "/v2/teal/dryrun", nil, headers, msgpack.Encode(&s.request))
return
}
59 changes: 30 additions & 29 deletions client/v2/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,33 +103,34 @@ func mergeRawQueries(q1, q2 string) string {
}

// submitFormRaw is a helper used for submitting (ex.) GETs and POSTs to the server
func (client *Client) submitFormRaw(ctx context.Context, path string, body interface{}, requestMethod string, encodeJSON bool, headers []*Header) (resp *http.Response, err error) {
func (client *Client) submitFormRaw(ctx context.Context, path string, params interface{}, requestMethod string, encodeJSON bool, headers []*Header, body interface{}) (resp *http.Response, err error) {
queryURL := client.serverURL
queryURL.Path += path

var req *http.Request
var bodyReader io.Reader
if body != nil {
if requestMethod == "POST" && rawRequestPaths[path] {
reqBytes, ok := body.([]byte)
if !ok {
return nil, fmt.Errorf("couldn't decode raw body as bytes")
}
bodyReader = bytes.NewBuffer(reqBytes)
} else {
v, err := query.Values(body)
if err != nil {
return nil, err
}

queryURL.RawQuery = mergeRawQueries(queryURL.RawQuery, v.Encode())
if encodeJSON {
jsonValue := json.Encode(body)
bodyReader = bytes.NewBuffer(jsonValue)
}
var v url.Values

if params != nil {
v, err = query.Values(params)
if err != nil {
return nil, err
}
}

if requestMethod == "POST" && rawRequestPaths[path] {
reqBytes, ok := body.([]byte)
if !ok {
return nil, fmt.Errorf("couldn't decode raw body as bytes")
}
bodyReader = bytes.NewBuffer(reqBytes)
} else if encodeJSON {
jsonValue := json.Encode(params)
bodyReader = bytes.NewBuffer(jsonValue)
}

queryURL.RawQuery = mergeRawQueries(queryURL.RawQuery, v.Encode())

req, err = http.NewRequest(requestMethod, queryURL.String(), bodyReader)
if err != nil {
return nil, err
Expand Down Expand Up @@ -161,8 +162,8 @@ func (client *Client) submitFormRaw(ctx context.Context, path string, body inter
return resp, nil
}

func (client *Client) submitForm(ctx context.Context, response interface{}, path string, body interface{}, requestMethod string, encodeJSON bool, headers []*Header) error {
resp, err := client.submitFormRaw(ctx, path, body, requestMethod, encodeJSON, headers)
func (client *Client) submitForm(ctx context.Context, response interface{}, path string, params interface{}, requestMethod string, encodeJSON bool, headers []*Header, body interface{}) error {
resp, err := client.submitFormRaw(ctx, path, params, requestMethod, encodeJSON, headers, body)
if err != nil {
return err
}
Expand Down Expand Up @@ -192,14 +193,14 @@ func (client *Client) submitForm(ctx context.Context, response interface{}, path
}

// Get performs a GET request to the specific path against the server
func (client *Client) Get(ctx context.Context, response interface{}, path string, body interface{}, headers []*Header) error {
return client.submitForm(ctx, response, path, body, "GET", false /* encodeJSON */, headers)
func (client *Client) Get(ctx context.Context, response interface{}, path string, params interface{}, headers []*Header) error {
return client.submitForm(ctx, response, path, params, "GET", false /* encodeJSON */, headers, nil)
}

// GetRaw performs a GET request to the specific path against the server and returns the raw body bytes.
func (client *Client) GetRaw(ctx context.Context, path string, body interface{}, headers []*Header) (response []byte, err error) {
func (client *Client) GetRaw(ctx context.Context, path string, params interface{}, headers []*Header) (response []byte, err error) {
var resp *http.Response
resp, err = client.submitFormRaw(ctx, path, body, "GET", false /* encodeJSON */, headers)
resp, err = client.submitFormRaw(ctx, path, params, "GET", false /* encodeJSON */, headers, nil)
if err != nil {
return nil, err
}
Expand All @@ -213,8 +214,8 @@ func (client *Client) GetRaw(ctx context.Context, path string, body interface{},
}

// GetRawMsgpack performs a GET request to the specific path against the server and returns the decoded messagepack response.
func (client *Client) GetRawMsgpack(ctx context.Context, response interface{}, path string, body interface{}, headers []*Header) error {
resp, err := client.submitFormRaw(ctx, path, body, "GET", false /* encodeJSON */, headers)
func (client *Client) GetRawMsgpack(ctx context.Context, response interface{}, path string, params interface{}, headers []*Header) error {
resp, err := client.submitFormRaw(ctx, path, params, "GET", false /* encodeJSON */, headers, nil)
if err != nil {
return err
}
Expand All @@ -238,8 +239,8 @@ func (client *Client) GetRawMsgpack(ctx context.Context, response interface{}, p
// Post sends a POST request to the given path with the given body object.
// No query parameters will be sent if body is nil.
// response must be a pointer to an object as post writes the response there.
func (client *Client) Post(ctx context.Context, response interface{}, path string, body interface{}, headers []*Header) error {
return client.submitForm(ctx, response, path, body, "POST", true /* encodeJSON */, headers)
func (client *Client) Post(ctx context.Context, response interface{}, path string, params interface{}, headers []*Header, body interface{}) error {
return client.submitForm(ctx, response, path, params, "POST", true /* encodeJSON */, headers, body)
}

// Helper function for correctly formatting and escaping URL path parameters.
Expand Down
4 changes: 2 additions & 2 deletions client/v2/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ func (c *Client) getRaw(ctx context.Context, path string, body interface{}, head
// post sends a POST request to the given path with the given request object.
// No query parameters will be sent if request is nil.
// response must be a pointer to an object as post writes the response there.
func (c *Client) post(ctx context.Context, response interface{}, path string, body interface{}, headers []*common.Header) error {
return (*common.Client)(c).Post(ctx, response, path, body, headers)
func (c *Client) post(ctx context.Context, response interface{}, path string, params interface{}, headers []*common.Header, body interface{}) error {
return (*common.Client)(c).Post(ctx, response, path, params, headers, body)
}

// MakeClient is the factory for constructing a ClientV2 for a given endpoint.
Expand Down
133 changes: 133 additions & 0 deletions logic/source_map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package logic

import (
"fmt"
"strings"
)

// SourceMap provides a mapping of the source to assembled program
type SourceMap struct {
Version int `json:"version"`
File string `json:"file,omitempty"`
SourceRoot string `json:"sourceRoot,omitempty"`
Sources []string `json:"sources"`
Names []string `json:"names"`
Mappings string `json:"mappings"`
// Decoded mapping results
LineToPc map[int][]int
PcToLine map[int]int
}

func DecodeSourceMap(ism map[string]interface{}) (SourceMap, error) {
sm := SourceMap{}

if v, ok := ism["version"]; ok {
sm.Version = int(v.(float64))
}

if sm.Version != 3 {
return sm, fmt.Errorf("only version 3 is supported")
}

if f, ok := ism["file"]; ok {
sm.File = f.(string)
}

if sr, ok := ism["sourceRoot"]; ok {
sm.SourceRoot = sr.(string)
}

if srcs, ok := ism["sources"]; ok {
srcSlice := srcs.([]interface{})
sm.Sources = make([]string, len(srcSlice))
for idx, s := range srcSlice {
sm.Sources[idx] = s.(string)
}
}

if names, ok := ism["names"]; ok {
nameSlice := names.([]interface{})
sm.Names = make([]string, len(nameSlice))
for idx, n := range nameSlice {
sm.Names[idx] = n.(string)
}
}

if m, ok := ism["mappings"]; ok {
sm.Mappings = m.(string)
}

if sm.Mappings == "" {
return sm, fmt.Errorf("no mappings defined")
}

sm.PcToLine = map[int]int{}
sm.LineToPc = map[int][]int{}

lastLine := 0
for idx, chunk := range strings.Split(sm.Mappings, ";") {
vals := decodeSourceMapLine(chunk)
// If the vals length >= 3 the lineDelta
if len(vals) >= 3 {
lastLine = lastLine + vals[2] // Add the line delta
}

if _, ok := sm.LineToPc[lastLine]; !ok {
sm.LineToPc[lastLine] = []int{}
}

sm.LineToPc[lastLine] = append(sm.LineToPc[lastLine], idx)
sm.PcToLine[idx] = lastLine
}

return sm, nil
}

func (s *SourceMap) GetLineForPc(pc int) (int, bool) {
line, ok := s.PcToLine[pc]
return line, ok
}

func (s *SourceMap) GetPcsForLine(line int) []int {
return s.LineToPc[line]
}

const (
// consts used for vlq encoding/decoding
b64table string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
vlqShiftSize = 5
vlqFlag = 1 << vlqShiftSize
vlqMask = vlqFlag - 1
)

func decodeSourceMapLine(vlq string) []int {

var (
results []int
value, shift int
)

for i := 0; i < len(vlq); i++ {
digit := strings.Index(b64table, string(vlq[i]))

value |= (digit & int(vlqMask)) << shift

if digit&vlqFlag > 0 {
shift += vlqShiftSize
continue
}

if value&1 > 0 {
value = (value >> 1) * -1
} else {
value = value >> 1
}

results = append(results, value)

// Reset
value, shift = 0, 0
}

return results
}
1 change: 1 addition & 0 deletions test/algodclientv2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func AlgodClientV2Context(s *godog.Suite) {
s.Step(`^we make an Account Information call against account "([^"]*)" with exclude "([^"]*)"$`, weMakeAnAccountInformationCallAgainstAccountWithExclude)
s.Step(`^we make an Account Asset Information call against account "([^"]*)" assetID (\d+)$`, weMakeAnAccountAssetInformationCallAgainstAccountAssetID)
s.Step(`^we make an Account Application Information call against account "([^"]*)" applicationID (\d+)$`, weMakeAnAccountApplicationInformationCallAgainstAccountApplicationID)

s.BeforeScenario(func(interface{}) {
globalErrForExamination = nil
})
Expand Down
Loading

0 comments on commit c5290bb

Please sign in to comment.