func TestConstructionDeriveEndpoint(t *testing.T) {
	params := chaincfg.RegNetParams()
	c := newMockChain(t, params)
	pubkey := mustHex("03eb7ae61d440e13823589ce2e3728a02b7f55530d4463aaf8059c7c41ef521e7d")
	v0 := float64(0)
	v1 := float64(1)
	cfg := &ServerConfig{
		ChainParams: params,
		DBType:      dbTypePreconfigured,
		c:           c,
	}
	svr := newTestServer(t, cfg)
	type testCase struct {
		name     string
		req      *rtypes.ConstructionDeriveRequest
		wantErr  error
		wantAddr string
	}
	testCases := []testCase{{
		name: "secp25k1 key for ecdsa algo",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
				"algo":           "ecdsa",
			},
		},
		wantErr:  nil,
		wantAddr: "RsL5dxVrAaEdwHB37sQYe5HA8RoSKVnq8LN",
	}, {
		name: "secp25k1 key for schnorr algo",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
				"algo":           "schnorr",
			},
		},
		wantErr:  nil,
		wantAddr: "RSP8EumNJZ3ucaJPkMPtt1WHMQXTqUeDcqA",
	}, {
		name: "secp25k1 key without algo specified defaults to ecdsa",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
			},
		},
		wantErr:  nil,
		wantAddr: "RsL5dxVrAaEdwHB37sQYe5HA8RoSKVnq8LN",
	}, {
		name: "non v0 script fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v1,
			},
		},
		wantErr: types.ErrUnsupportedAddressVersion,
	}, {
		name: "script_version unspecified fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{},
		},
		wantErr: types.ErrUnspecifiedAddressVersion,
	}, {
		name: "short pubkey fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey[:32],
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
			},
		},
		wantErr: types.ErrInvalidSecp256k1PubKey,
	}, {
		name: "long pubkey fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     append(pubkey, 0x01),
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
			},
		},
		wantErr: types.ErrInvalidSecp256k1PubKey,
	}, {
		name: "invalid pubkey prefix byte fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     append([]byte{0xff}, pubkey[:32]...),
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
			},
		},
		wantErr: types.ErrNotCompressedSecp256k1Key,
	}, {
		name: "unsupported algo fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: rtypes.Secp256k1,
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
				"algo":           "none",
			},
		},
		wantErr: types.ErrUnsupportedAddressAlgo,
	}, {
		name: "unsupported curve type fails",
		req: &rtypes.ConstructionDeriveRequest{
			PublicKey: &rtypes.PublicKey{
				Bytes:     pubkey,
				CurveType: "foo",
			},
			Metadata: map[string]interface{}{
				"script_version": v0,
			},
		},
		wantErr: types.ErrUnsupportedCurveType,
	}}
	test := func(t *testing.T, tc *testCase) {
		t.Parallel()
		res, rerr := svr.ConstructionDerive(context.Background(), tc.req)
		if !types.RosettaErrorIs(rerr, tc.wantErr) {
			t.Fatalf("unexpected error. want=%v got=%v",
				tc.wantErr, rerr)
		}
		if tc.wantErr != nil {
			return
		}
		gotAddr := res.AccountIdentifier.Address
		if gotAddr != tc.wantAddr {
			t.Fatalf("unexpected address. want=%v got=%v", tc.wantAddr,
				gotAddr)
		}
	}
	for _, tc := range testCases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) { test(t, &tc) })
	}
}
TestConsturctionDeriveEndpoint tests the ConstructionDerive() call behaves
as expected.
package backend
import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"strconv"
	"testing"
	"decred.org/dcrros/types"
	rtypes "github.com/coinbase/rosetta-sdk-go/types"
	"github.com/davecgh/go-spew/spew"
	"github.com/decred/dcrd/chaincfg/chainhash"
	"github.com/decred/dcrd/chaincfg/v3"
	"github.com/decred/dcrd/dcrec"
	"github.com/decred/dcrd/dcrec/secp256k1/v3"
	"github.com/decred/dcrd/dcrec/secp256k1/v3/ecdsa"
	"github.com/decred/dcrd/dcrjson/v3"
	"github.com/decred/dcrd/dcrutil/v3"
	"github.com/decred/dcrd/txscript/v3"
	"github.com/decred/dcrd/wire"
	"github.com/stretchr/testify/require"
)