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

Enhancement: Deprecating use of langspec #366

Merged
merged 23 commits into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
3 changes: 2 additions & 1 deletion .test-env
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Configs for testing repo download:
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
SDK_TESTING_BRANCH="master"
# TODO revert back to "master" after sdk-testing is merged
SDK_TESTING_BRANCH="deprecate-langspec"
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
SDK_TESTING_HARNESS="test-harness"

VERBOSE_HARNESS=0
Expand Down
6 changes: 3 additions & 3 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func SignBytes(sk ed25519.PrivateKey, bytesToSign []byte) (signature []byte, err
return
}

//VerifyBytes verifies that the signature is valid
// VerifyBytes verifies that the signature is valid
func VerifyBytes(pk ed25519.PublicKey, message, signature []byte) bool {
msgParts := [][]byte{bytesPrefix, message}
toBeVerified := bytes.Join(msgParts, nil)
Expand Down Expand Up @@ -462,7 +462,7 @@ func ComputeGroupID(txgroup []types.Transaction) (gid types.Digest, err error) {
// multsig account). In that case, it should be the address of the delegating
// account.
func VerifyLogicSig(lsig types.LogicSig, singleSigner types.Address) (result bool) {
if err := logic.CheckProgram(lsig.Logic, lsig.Args); err != nil {
if err := logic.SanityCheckProgram(lsig.Logic); err != nil {
return false
}

Expand Down Expand Up @@ -615,7 +615,7 @@ func MakeLogicSig(program []byte, args [][]byte, sk ed25519.PrivateKey, ma Multi
err = errLsigInvalidProgram
return
}
if err = logic.CheckProgram(program, args); err != nil {
if err = logic.SanityCheckProgram(program); err != nil {
return
}

Expand Down
7 changes: 0 additions & 7 deletions crypto/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,6 @@ func TestMakeLogicSigBasic(t *testing.T) {
err = msgpack.Decode(encoded, &lsig1)
require.NoError(t, err)
require.Equal(t, lsig, lsig1)

// check invalid program fails
programMod := make([]byte, len(program))
copy(programMod[:], program)
programMod[0] = 128
lsig, err = MakeLogicSig(programMod, args, sk, pk)
require.Error(t, err)
}

func TestMakeLogicSigSingle(t *testing.T) {
Expand Down
46 changes: 46 additions & 0 deletions logic/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@ package logic
//go:generate ./bundle_langspec_json.sh

import (
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"

"github.com/algorand/go-algorand-sdk/types"
)

// Deprecated
type langSpec struct {
EvalMaxVersion int
LogicSigVersion int
Ops []operation
}

// Deprecated
type operation struct {
Opcode int
Name string
Expand All @@ -29,16 +32,55 @@ type operation struct {
Group []string
}

// Deprecated
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
var spec *langSpec

// Deprecated
var opcodes []operation

// CheckProgram performs basic program validation: instruction count and program cost
// Deprecated: `langspec.json` can no longer correctly to depicting the cost model (as of 2022.08.22),
// also to minimize the work in updating SDKs per AVM release, we are deprecating`langspec.json` across all SDKs.
// The behavior of `CheckProgram` relies on `langspec.json`. Thus, this method is being deprecated.
func CheckProgram(program []byte, args [][]byte) error {
_, _, err := ReadProgram(program, args)
return err
}

func isAsciiPrintableByte(symbol byte) bool {
isBreakLine := symbol == '\n'
isStdPrintable := symbol >= ' ' && symbol <= '~'
return isBreakLine || isStdPrintable
}

func isAsciiPrintable(program []byte) bool {
for _, b := range program {
if !isAsciiPrintableByte(b) {
return false
}
}
return true
}

// SanityCheckProgram performs heuristic program validation:
// check if passed in bytes are Algorand address or is B64 encoded, rather than Teal bytes
func SanityCheckProgram(program []byte) error {
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
if isAsciiPrintable(program) {
if _, err := types.DecodeAddress(string(program)); err == nil {
return fmt.Errorf("requesting program bytes, get Algorand address")
}
if _, err := base64.StdEncoding.DecodeString(string(program)); err == nil {
return fmt.Errorf("program should not be b64 encoded")
}
return fmt.Errorf("program bytes are all ASCII printable characters, not looking like Teal byte code")
}
return nil
}

// ReadProgram is used to validate a program as well as extract found variables
// Deprecated: `langspec.json` can no longer correctly to depicting the cost model (as of 2022.08.22),
// also to minimize the work in updating SDKs per AVM release, we are deprecating`langspec.json` across all SDKs.
// The behavior of `ReadProgram` relies on `langspec.json`. Thus, this method is being deprecated.
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
func ReadProgram(program []byte, args [][]byte) (ints []uint64, byteArrays [][]byte, err error) {
const intcblockOpcode = 32
const bytecblockOpcode = 38
Expand Down Expand Up @@ -138,6 +180,7 @@ func ReadProgram(program []byte, args [][]byte) (ints []uint64, byteArrays [][]b
return
}

// Deprecated
func readIntConstBlock(program []byte, pc int) (size int, ints []uint64, err error) {
size = 1
numInts, bytesUsed := binary.Uvarint(program[pc+size:])
Expand All @@ -163,6 +206,7 @@ func readIntConstBlock(program []byte, pc int) (size int, ints []uint64, err err
return
}

// Deprecated
func readByteConstBlock(program []byte, pc int) (size int, byteArrays [][]byte, err error) {
size = 1
numInts, bytesUsed := binary.Uvarint(program[pc+size:])
Expand Down Expand Up @@ -195,6 +239,7 @@ func readByteConstBlock(program []byte, pc int) (size int, byteArrays [][]byte,
return
}

// Deprecated
func readPushIntOp(program []byte, pc int) (size int, foundInt uint64, err error) {
size = 1
foundInt, bytesUsed := binary.Uvarint(program[pc+size:])
Expand All @@ -207,6 +252,7 @@ func readPushIntOp(program []byte, pc int) (size int, foundInt uint64, err error
return
}

// Deprecated
func readPushByteOp(program []byte, pc int) (size int, byteArray []byte, err error) {
size = 1
itemLen, bytesUsed := binary.Uvarint(program[pc+size:])
Expand Down
37 changes: 36 additions & 1 deletion test/steps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ var txTrace future.DryrunTxnResult
var trace string
var sourceMap logic.SourceMap
var srcMapping map[string]interface{}
var seeminglyProgram []byte
var sanityCheckError error

var assetTestFixture struct {
Creator string
Expand Down Expand Up @@ -387,7 +389,10 @@ func FeatureContext(s *godog.Suite) {
s.Step(`^the resulting source map is the same as the json "([^"]*)"$`, theResultingSourceMapIsTheSameAsTheJson)
s.Step(`^getting the line associated with a pc "([^"]*)" equals "([^"]*)"$`, gettingTheLineAssociatedWithAPcEquals)
s.Step(`^getting the last pc associated with a line "([^"]*)" equals "([^"]*)"$`, gettingTheLastPcAssociatedWithALineEquals)

s.Step(`^a base64 encoded program bytes for heuristic sanity check "([^"]*)"$`, takeB64encodedBytes)
s.Step(`^I start heuristic sanity check over the bytes$`, heuristicCheckOverBytes)
s.Step(`^if there exists an error, the error contains "([^"]*)"$`, checkErrorIfMatching)

s.BeforeScenario(func(interface{}) {
stxObj = types.SignedTxn{}
abiMethods = nil
Expand Down Expand Up @@ -2634,3 +2639,33 @@ func theResultingSourceMapIsTheSameAsTheJson(expectedJsonPath string) error {

return nil
}

func takeB64encodedBytes(b64encodedBytes string) error {
var err error
seeminglyProgram, err = base64.StdEncoding.DecodeString(b64encodedBytes)
if err != nil {
return err
}
return nil
}

func heuristicCheckOverBytes() error {
sanityCheckError = logic.SanityCheckProgram(seeminglyProgram)
if sanityCheckError != nil {
fmt.Printf(sanityCheckError.Error())
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
}
return nil
}

func checkErrorIfMatching(errMsg string) error {
if len(errMsg) == 0 {
if sanityCheckError != nil {
return fmt.Errorf("expected err message to be empty, but sanity check says %w", sanityCheckError)
}
} else {
if sanityCheckError == nil || !strings.Contains(sanityCheckError.Error(), errMsg) {
return fmt.Errorf("expected err to contain %s, but sanity check error not matching: %w", errMsg, sanityCheckError)
}
}
return nil
}
1 change: 1 addition & 0 deletions test/unit.tags
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@unit.indexer.logs
@unit.indexer.rekey
@unit.offline
@unit.program_sanity_check
@unit.rekey
@unit.responses
@unit.responses.231
Expand Down