Witness Problem in Construction

Hello,

I have forked Rosetta-Bitcoin and doing the changes what we need for our Blockchain.
Our blockchain doesn’t support Witness/Segwit.

Now mine Construction-service.go looks like:

// ConstructionDerive implements the /construction/derive endpoint.
func (s *ConstructionAPIService) ConstructionDerive(
	ctx context.Context,
	request *types.ConstructionDeriveRequest,
) (*types.ConstructionDeriveResponse, *types.Error) {
	addr, err := btcutil.NewAddressPubKey(
		request.PublicKey.Bytes,
		s.config.Params,
	)
	if err != nil {
		return nil, wrapErr(ErrUnableToDerive, err)
	}

	return &types.ConstructionDeriveResponse{
		AccountIdentifier: &types.AccountIdentifier{
			Address: addr.EncodeAddress(),
		},
	}, nil
}

// estimateSize returns the estimated size of a transaction in vBytes.
func (s *ConstructionAPIService) estimateSize(operations []*types.Operation) float64 {
	size := bitcoin.TransactionOverhead
	for _, operation := range operations {
		switch operation.Type {
		case bitcoin.InputOpType:
			size += bitcoin.InputSize
		case bitcoin.OutputOpType:
			size += bitcoin.OutputOverhead
			addr, err := btcutil.DecodeAddress(operation.Account.Address, s.config.Params)
			if err != nil {
				size += bitcoin.P2PKHScriptPubkeySize
				continue
			}

			script, err := txscript.PayToAddrScript(addr)
			if err != nil {
				size += bitcoin.P2PKHScriptPubkeySize
				continue
			}

			size += len(script)
		}
	}

	return float64(size)
}

// ConstructionPreprocess implements the /construction/preprocess
// endpoint.
func (s *ConstructionAPIService) ConstructionPreprocess(
	ctx context.Context,
	request *types.ConstructionPreprocessRequest,
) (*types.ConstructionPreprocessResponse, *types.Error) {
	descriptions := &parser.Descriptions{
		OperationDescriptions: []*parser.OperationDescription{
			{
				Type: bitcoin.InputOpType,
				Account: &parser.AccountDescription{
					Exists: true,
				},
				Amount: &parser.AmountDescription{
					Exists:   true,
					Sign:     parser.NegativeAmountSign,
					Currency: s.config.Currency,
				},
				CoinAction:   types.CoinSpent,
				AllowRepeats: true,
			},
		},
	}

	matches, err := parser.MatchOperations(descriptions, request.Operations)
	if err != nil {
		return nil, wrapErr(ErrUnclearIntent, err)
	}

	coins := make([]*types.Coin, len(matches[0].Operations))
	for i, input := range matches[0].Operations {
		if input.CoinChange == nil {
			return nil, wrapErr(ErrUnclearIntent, errors.New("CoinChange cannot be nil"))
		}

		coins[i] = &types.Coin{
			CoinIdentifier: input.CoinChange.CoinIdentifier,
			Amount:         input.Amount,
		}
	}

	options, err := types.MarshalMap(&preprocessOptions{
		Coins:         coins,
		EstimatedSize: s.estimateSize(request.Operations),
		FeeMultiplier: request.SuggestedFeeMultiplier,
	})
	if err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
	}

	return &types.ConstructionPreprocessResponse{
		Options: options,
	}, nil
}

// ConstructionMetadata implements the /construction/metadata endpoint.
func (s *ConstructionAPIService) ConstructionMetadata(
	ctx context.Context,
	request *types.ConstructionMetadataRequest,
) (*types.ConstructionMetadataResponse, *types.Error) {
	if s.config.Mode != configuration.Online {
		return nil, wrapErr(ErrUnavailableOffline, nil)
	}

	var options preprocessOptions
	if err := types.UnmarshalMap(request.Options, &options); err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
	}

	// Determine feePerKB and ensure it is not below the minimum fee
	// relay rate.
	feePerKB := float64(0.001)

	// Calculated the estimated fee in Satoshis
	satoshisPerB := (feePerKB * float64(bitcoin.SatoshisInBitcoin)) / bytesInKb
	estimatedFee := satoshisPerB * options.EstimatedSize
	suggestedFee := &types.Amount{
		Value:    fmt.Sprintf("%d", int64(estimatedFee)),
		Currency: s.config.Currency,
	}

	scripts, err := s.i.GetScriptPubKeys(ctx, options.Coins)
	if err != nil {
		return nil, wrapErr(ErrScriptPubKeysMissing, err)
	}

	metadata, err := types.MarshalMap(&constructionMetadata{ScriptPubKeys: scripts})
	if err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
	}

	return &types.ConstructionMetadataResponse{
		Metadata:     metadata,
		SuggestedFee: []*types.Amount{suggestedFee},
	}, nil
}

// ConstructionPayloads implements the /construction/payloads endpoint.
func (s *ConstructionAPIService) ConstructionPayloads(
	ctx context.Context,
	request *types.ConstructionPayloadsRequest,
) (*types.ConstructionPayloadsResponse, *types.Error) {
	descriptions := &parser.Descriptions{
		OperationDescriptions: []*parser.OperationDescription{
			{
				Type: bitcoin.InputOpType,
				Account: &parser.AccountDescription{
					Exists: true,
				},
				Amount: &parser.AmountDescription{
					Exists:   true,
					Sign:     parser.NegativeAmountSign,
					Currency: s.config.Currency,
				},
				AllowRepeats: true,
				CoinAction:   types.CoinSpent,
			},
			{
				Type: bitcoin.OutputOpType,
				Account: &parser.AccountDescription{
					Exists: true,
				},
				Amount: &parser.AmountDescription{
					Exists:   true,
					Sign:     parser.PositiveAmountSign,
					Currency: s.config.Currency,
				},
				AllowRepeats: true,
			},
		},
		ErrUnmatched: true,
	}

	matches, err := parser.MatchOperations(descriptions, request.Operations)
	if err != nil {
		return nil, wrapErr(ErrUnclearIntent, err)
	}

	tx := wire.NewMsgTx(wire.TxVersion)
	for _, input := range matches[0].Operations {
		if input.CoinChange == nil {
			return nil, wrapErr(ErrUnclearIntent, errors.New("CoinChange cannot be nil"))
		}

		transactionHash, index, err := bitcoin.ParseCoinIdentifier(input.CoinChange.CoinIdentifier)
		if err != nil {
			return nil, wrapErr(ErrInvalidCoin, err)
		}

		tx.AddTxIn(&wire.TxIn{
			PreviousOutPoint: wire.OutPoint{
				Hash:  *transactionHash,
				Index: index,
			},
			SignatureScript: nil,
			Sequence:        wire.MaxTxInSequenceNum,
		})
	}

	for i, output := range matches[1].Operations {
		addr, err := btcutil.DecodeAddress(output.Account.Address, s.config.Params)
		if err != nil {
			return nil, wrapErr(ErrUnableToDecodeAddress, fmt.Errorf(
				"%w unable to decode address %s",
				err,
				output.Account.Address,
			),
			)
		}

		pkScript, err := txscript.PayToAddrScript(addr)
		if err != nil {
			return nil, wrapErr(
				ErrUnableToDecodeAddress,
				fmt.Errorf("%w unable to construct payToAddrScript", err),
			)
		}

		tx.AddTxOut(&wire.TxOut{
			Value:    matches[1].Amounts[i].Int64(),
			PkScript: pkScript,
		})
	}

	// Create Signing Payloads (must be done after entire tx is constructed
	// or hash will not be correct).
	inputAmounts := make([]string, len(tx.TxIn))
	inputAddresses := make([]string, len(tx.TxIn))
	payloads := make([]*types.SigningPayload, len(tx.TxIn))
	var metadata constructionMetadata
	if err := types.UnmarshalMap(request.Metadata, &metadata); err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
	}

	for i := range tx.TxIn {
		address := matches[0].Operations[i].Account.Address
		script, err := hex.DecodeString(metadata.ScriptPubKeys[i].Hex)
		if err != nil {
			return nil, wrapErr(ErrUnableToDecodeScriptPubKey, err)
		}

		class, _, err := bitcoin.ParseSingleAddress(s.config.Params, script)
		if err != nil {
			return nil, wrapErr(
				ErrUnableToDecodeAddress,
				fmt.Errorf("%w unable to parse address for utxo %d", err, i),
			)
		}

		inputAddresses[i] = address
		inputAmounts[i] = matches[0].Amounts[i].String()
		absAmount := new(big.Int).Abs(matches[0].Amounts[i]).Int64()

		switch class {
		case txscript.WitnessV0PubKeyHashTy:
			hash, err := txscript.CalcWitnessSigHash(
				script,
				txscript.NewTxSigHashes(tx),
				txscript.SigHashAll,
				tx,
				i,
				absAmount,
			)
			if err != nil {
				return nil, wrapErr(ErrUnableToCalculateSignatureHash, err)
			}

			payloads[i] = &types.SigningPayload{
				AccountIdentifier: &types.AccountIdentifier{
					Address: address,
				},
				Bytes:         hash,
				SignatureType: types.Ecdsa,
			}
		case txscript.PubKeyHashTy:
			hash, err := txscript.CalcSignatureHash(
				script,
				txscript.SigHashAll,
				tx,
				i,
			)
			if err != nil {
				return nil, wrapErr(ErrUnableToCalculateSignatureHash, err)
			}

			payloads[i] = &types.SigningPayload{
				AccountIdentifier: &types.AccountIdentifier{
					Address: address,
				},
				Bytes:         hash,
				SignatureType: types.Ecdsa,
			}
		default:
			return nil, wrapErr(
				ErrUnsupportedScriptType,
				fmt.Errorf("unupported script type: %s", class),
			)
		}
	}

	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	if err := tx.Serialize(buf); err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
	}

	rawTx, err := json.Marshal(&unsignedTransaction{
		Transaction:    hex.EncodeToString(buf.Bytes()),
		ScriptPubKeys:  metadata.ScriptPubKeys,
		InputAmounts:   inputAmounts,
		InputAddresses: inputAddresses,
	})
	if err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
	}

	return &types.ConstructionPayloadsResponse{
		UnsignedTransaction: hex.EncodeToString(rawTx),
		Payloads:            payloads,
	}, nil
}

func normalizeSignature(signature []byte) []byte {
	sig := btcec.Signature{ // signature is in form of R || S
		R: new(big.Int).SetBytes(signature[:32]),
		S: new(big.Int).SetBytes(signature[32:64]),
	}

	return append(sig.Serialize(), byte(txscript.SigHashAll))
}

// ConstructionCombine implements the /construction/combine
// endpoint.
func (s *ConstructionAPIService) ConstructionCombine(
	ctx context.Context,
	request *types.ConstructionCombineRequest,
) (*types.ConstructionCombineResponse, *types.Error) {
	decodedTx, err := hex.DecodeString(request.UnsignedTransaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w transaction cannot be decoded", err),
		)
	}

	var unsigned unsignedTransaction
	if err := json.Unmarshal(decodedTx, &unsigned); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to unmarshal bitcoin transaction", err),
		)
	}

	decodedCoreTx, err := hex.DecodeString(unsigned.Transaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w transaction cannot be decoded", err),
		)
	}

	var tx wire.MsgTx
	if err := tx.Deserialize(bytes.NewReader(decodedCoreTx)); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to deserialize tx", err),
		)
	}

	for i := range tx.TxIn {
		decodedScript, err := hex.DecodeString(unsigned.ScriptPubKeys[i].Hex)
		if err != nil {
			return nil, wrapErr(ErrUnableToDecodeScriptPubKey, err)
		}

		class, _, err := bitcoin.ParseSingleAddress(s.config.Params, decodedScript)
		if err != nil {
			return nil, wrapErr(
				ErrUnableToDecodeAddress,
				fmt.Errorf("%w unable to parse address for script", err),
			)
		}

		pkData := request.Signatures[i].PublicKey.Bytes
		fullsig := normalizeSignature(request.Signatures[i].Bytes)

		switch class {
		case txscript.WitnessV0PubKeyHashTy:
			tx.TxIn[i].Witness = wire.TxWitness{fullsig, pkData}
		case txscript.PubKeyHashTy:
			tx.TxIn[i].Witness = wire.TxWitness{fullsig, pkData}
		default:
			return nil, wrapErr(
				ErrUnsupportedScriptType,
				fmt.Errorf("unupported script type: %s", class),
			)
		}
	}

	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	if err := tx.Serialize(buf); err != nil {
		return nil, wrapErr(ErrUnableToParseIntermediateResult, fmt.Errorf("%w serialize tx", err))
	}

	rawTx, err := json.Marshal(&signedTransaction{
		Transaction:  hex.EncodeToString(buf.Bytes()),
		InputAmounts: unsigned.InputAmounts,
	})
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to serialize signed tx", err),
		)
	}

	return &types.ConstructionCombineResponse{
		SignedTransaction: hex.EncodeToString(rawTx),
	}, nil
}

// ConstructionHash implements the /construction/hash endpoint.
func (s *ConstructionAPIService) ConstructionHash(
	ctx context.Context,
	request *types.ConstructionHashRequest,
) (*types.TransactionIdentifierResponse, *types.Error) {
	decodedTx, err := hex.DecodeString(request.SignedTransaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w signed transaction cannot be decoded", err),
		)
	}

	var signed signedTransaction
	if err := json.Unmarshal(decodedTx, &signed); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to unmarshal signed bitcoin transaction", err),
		)
	}

	bytesTx, err := hex.DecodeString(signed.Transaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to decode hex transaction", err),
		)
	}

	tx, err := btcutil.NewTxFromBytes(bytesTx)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to parse transaction", err),
		)
	}

	return &types.TransactionIdentifierResponse{
		TransactionIdentifier: &types.TransactionIdentifier{
			Hash: tx.Hash().String(),
		},
	}, nil
}

func (s *ConstructionAPIService) parseUnsignedTransaction(
	request *types.ConstructionParseRequest,
) (*types.ConstructionParseResponse, *types.Error) {
	decodedTx, err := hex.DecodeString(request.Transaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w transaction cannot be decoded", err),
		)
	}

	var unsigned unsignedTransaction
	if err := json.Unmarshal(decodedTx, &unsigned); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to unmarshal bitcoin transaction", err),
		)
	}

	decodedCoreTx, err := hex.DecodeString(unsigned.Transaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w transaction cannot be decoded", err),
		)
	}

	var tx wire.MsgTx
	if err := tx.Deserialize(bytes.NewReader(decodedCoreTx)); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to deserialize tx", err),
		)
	}

	ops := []*types.Operation{}
	for i, input := range tx.TxIn {
		networkIndex := int64(i)
		ops = append(ops, &types.Operation{
			OperationIdentifier: &types.OperationIdentifier{
				Index:        int64(len(ops)),
				NetworkIndex: &networkIndex,
			},
			Type: bitcoin.InputOpType,
			Account: &types.AccountIdentifier{
				Address: unsigned.InputAddresses[i],
			},
			Amount: &types.Amount{
				Value:    unsigned.InputAmounts[i],
				Currency: s.config.Currency,
			},
			CoinChange: &types.CoinChange{
				CoinAction: types.CoinSpent,
				CoinIdentifier: &types.CoinIdentifier{
					Identifier: fmt.Sprintf(
						"%s:%d",
						input.PreviousOutPoint.Hash.String(),
						input.PreviousOutPoint.Index,
					),
				},
			},
		})
	}

	for i, output := range tx.TxOut {
		networkIndex := int64(i)
		_, addr, err := bitcoin.ParseSingleAddress(s.config.Params, output.PkScript)
		if err != nil {
			return nil, wrapErr(
				ErrUnableToDecodeAddress,
				fmt.Errorf("%w unable to parse output address", err),
			)
		}

		ops = append(ops, &types.Operation{
			OperationIdentifier: &types.OperationIdentifier{
				Index:        int64(len(ops)),
				NetworkIndex: &networkIndex,
			},
			Type: bitcoin.OutputOpType,
			Account: &types.AccountIdentifier{
				Address: addr.String(),
			},
			Amount: &types.Amount{
				Value:    strconv.FormatInt(output.Value, 10),
				Currency: s.config.Currency,
			},
		})
	}

	return &types.ConstructionParseResponse{
		Operations:               ops,
		AccountIdentifierSigners: []*types.AccountIdentifier{},
	}, nil
}

func (s *ConstructionAPIService) parseSignedTransaction(
	request *types.ConstructionParseRequest,
) (*types.ConstructionParseResponse, *types.Error) {
	decodedTx, err := hex.DecodeString(request.Transaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w signed transaction cannot be decoded", err),
		)
	}

	var signed signedTransaction
	if err := json.Unmarshal(decodedTx, &signed); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to unmarshal signed bitcoin transaction", err),
		)
	}

	serializedTx, err := hex.DecodeString(signed.Transaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to decode hex transaction", err),
		)
	}

	var tx wire.MsgTx
	if err := tx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to decode msgTx", err),
		)
	}

	ops := []*types.Operation{}
	signers := []*types.AccountIdentifier{}
	for i, input := range tx.TxIn {
		pkScript, err := txscript.ComputePkScript(input.SignatureScript, input.Witness)
		if err != nil {
			return nil, wrapErr(
				ErrUnableToComputePkScript,
				fmt.Errorf("%w: unable to compute pk script", err),
			)
		}

		_, addr, err := bitcoin.ParseSingleAddress(s.config.Params, pkScript.Script())
		if err != nil {
			return nil, wrapErr(
				ErrUnableToDecodeAddress,
				fmt.Errorf("%w unable to decode address", err),
			)
		}

		networkIndex := int64(i)
		signers = append(signers, &types.AccountIdentifier{
			Address: addr.EncodeAddress(),
		})
		ops = append(ops, &types.Operation{
			OperationIdentifier: &types.OperationIdentifier{
				Index:        int64(len(ops)),
				NetworkIndex: &networkIndex,
			},
			Type: bitcoin.InputOpType,
			Account: &types.AccountIdentifier{
				Address: addr.EncodeAddress(),
			},
			Amount: &types.Amount{
				Value:    signed.InputAmounts[i],
				Currency: s.config.Currency,
			},
			CoinChange: &types.CoinChange{
				CoinAction: types.CoinSpent,
				CoinIdentifier: &types.CoinIdentifier{
					Identifier: fmt.Sprintf(
						"%s:%d",
						input.PreviousOutPoint.Hash.String(),
						input.PreviousOutPoint.Index,
					),
				},
			},
		})
	}

	for i, output := range tx.TxOut {
		networkIndex := int64(i)
		_, addr, err := bitcoin.ParseSingleAddress(s.config.Params, output.PkScript)
		if err != nil {
			return nil, wrapErr(
				ErrUnableToDecodeAddress,
				fmt.Errorf("%w unable to parse output address", err),
			)
		}

		ops = append(ops, &types.Operation{
			OperationIdentifier: &types.OperationIdentifier{
				Index:        int64(len(ops)),
				NetworkIndex: &networkIndex,
			},
			Type: bitcoin.OutputOpType,
			Account: &types.AccountIdentifier{
				Address: addr.String(),
			},
			Amount: &types.Amount{
				Value:    strconv.FormatInt(output.Value, 10),
				Currency: s.config.Currency,
			},
		})
	}

	return &types.ConstructionParseResponse{
		Operations:               ops,
		AccountIdentifierSigners: signers,
	}, nil
}

// ConstructionParse implements the /construction/parse endpoint.
func (s *ConstructionAPIService) ConstructionParse(
	ctx context.Context,
	request *types.ConstructionParseRequest,
) (*types.ConstructionParseResponse, *types.Error) {
	if request.Signed {
		return s.parseSignedTransaction(request)
	}

	return s.parseUnsignedTransaction(request)
}

// ConstructionSubmit implements the /construction/submit endpoint.
func (s *ConstructionAPIService) ConstructionSubmit(
	ctx context.Context,
	request *types.ConstructionSubmitRequest,
) (*types.TransactionIdentifierResponse, *types.Error) {
	if s.config.Mode != configuration.Online {
		return nil, wrapErr(ErrUnavailableOffline, nil)
	}

	decodedTx, err := hex.DecodeString(request.SignedTransaction)
	if err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w signed transaction cannot be decoded", err),
		)
	}

	var signed signedTransaction
	if err := json.Unmarshal(decodedTx, &signed); err != nil {
		return nil, wrapErr(
			ErrUnableToParseIntermediateResult,
			fmt.Errorf("%w unable to unmarshal signed bitcoin transaction", err),
		)
	}

	txHash, err := s.client.SendRawTransaction(ctx, signed.Transaction)
	if err != nil {
		return nil, wrapErr(ErrBitcoind, fmt.Errorf("%w unable to submit transaction", err))
	}

	return &types.TransactionIdentifierResponse{
		TransactionIdentifier: &types.TransactionIdentifier{
			Hash: txHash,
		},
	}, nil
}

When i’m running the rosetta-cli test i’m getting:

Command Failed: Account.Address is missing: account identifier is invalid in operation 0 unable to parse operations: /construction/parse: unable to parse signed transaction: unable to create transaction

Workflow of rosetta-cli

2022/05/13 23:46:20 REQUEST /construction/preprocess network_identifier:{"blockchain":"EUNO","network":"Testnet"} intent:[{"operation_identifier":{"index":0},"type":"INPUT","account":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"amount":{"value":"-240000000000","currency":{"symbol":"tEUNO","decimals":8}},"coin_change":{"coin_identifier":{"identifier":"6b26480336d18a8d2f2e9c66662fe17ecd5a4d87a0482b27f3e6e68d5a67fff5:0"},"coin_action":"coin_spent"}},{"operation_identifier":{"index":1},"type":"OUTPUT","account":{"address":"yFZa81DZ5ZoPACQCSQjfgAWz9WeibGyUHJ"},"amount":{"value":"150784319081","currency":{"symbol":"tEUNO","decimals":8}}},{"operation_identifier":{"index":2},"type":"OUTPUT","account":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"amount":{"value":"89215666219","currency":{"symbol":"tEUNO","decimals":8}}}] metadata:null
2022/05/13 23:46:20 Syncing 490148-490154
2022/05/13 23:46:20 RESPONSE /construction/preprocess options:{"coins":[{"amount":{"currency":{"decimals":8,"symbol":"tEUNO"},"value":"-240000000000"},"coin_identifier":{"identifier":"6b26480336d18a8d2f2e9c66662fe17ecd5a4d87a0482b27f3e6e68d5a67fff5:0"}}],"estimated_size":147} required_public_keys:null
2022/05/13 23:46:20 REQUEST /construction/metadata network_identifier:{"blockchain":"EUNO","network":"Testnet"} metadata:{"coins":[{"amount":{"currency":{"decimals":8,"symbol":"tEUNO"},"value":"-240000000000"},"coin_identifier":{"identifier":"6b26480336d18a8d2f2e9c66662fe17ecd5a4d87a0482b27f3e6e68d5a67fff5:0"}}],"estimated_size":147} public_keys:[]
2022/05/13 23:46:20 RESPONSE /construction/metadata metadata:{"script_pub_keys":[{"addresses":["yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"],"asm":"OP_DUP OP_HASH160 e24112be979bd0fbad7a0db9a06525abe88f440b OP_EQUALVERIFY OP_CHECKSIG","hex":"76a914e24112be979bd0fbad7a0db9a06525abe88f440b88ac","reqSigs":1,"type":"pubkeyhash"}]} suggested_fee:[{"value":"14700","currency":{"symbol":"tEUNO","decimals":8}}]
2022/05/13 23:46:20 REQUEST /construction/payloads network_identifier:{"blockchain":"EUNO","network":"Testnet"} intent:[{"operation_identifier":{"index":0},"type":"INPUT","account":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"amount":{"value":"-240000000000","currency":{"symbol":"tEUNO","decimals":8}},"coin_change":{"coin_identifier":{"identifier":"6b26480336d18a8d2f2e9c66662fe17ecd5a4d87a0482b27f3e6e68d5a67fff5:0"},"coin_action":"coin_spent"}},{"operation_identifier":{"index":1},"type":"OUTPUT","account":{"address":"yFZa81DZ5ZoPACQCSQjfgAWz9WeibGyUHJ"},"amount":{"value":"150784319081","currency":{"symbol":"tEUNO","decimals":8}}},{"operation_identifier":{"index":2},"type":"OUTPUT","account":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"amount":{"value":"89215666219","currency":{"symbol":"tEUNO","decimals":8}}}] public_keys:[]
2022/05/13 23:46:20 RESPONSE /construction/payloads unsigned_transaction:"7b227472616e73616374696f6e223a2230313030303030303031663566663637356138646536653666333237326234386130383734643561636437656531326636363636396332653266386438616431333630333438323636623030303030303030303066666666666666663032363931653732316232333030303030303139373661393134636264333433653865643866636565663237616561336362343762653430303037666361616665333838616332623038616263353134303030303030313937366139313465323431313262653937396264306662616437613064623961303635323561626538386634343062383861633030303030303030222c227363726970745075624b657973223a5b7b2261736d223a224f505f445550204f505f484153483136302065323431313262653937396264306662616437613064623961303635323561626538386634343062204f505f455155414c564552494659204f505f434845434b534947222c22686578223a223736613931346532343131326265393739626430666261643761306462396130363532356162653838663434306238386163222c2272657153696773223a312c2274797065223a227075626b657968617368222c22616464726573736573223a5b2279486341587044426742646b6335475a3172634133734333474b59626161326a4439225d7d5d2c22696e7075745f616d6f756e7473223a5b222d323430303030303030303030225d2c22696e7075745f616464726573736573223a5b2279486341587044426742646b6335475a3172634133734333474b59626161326a4439225d7d" payloads:[{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9","hex_bytes":"35d991f5895814e519540995ac3129312cb592bc426fcbdd446d1b572e503353","account_identifier":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"signature_type":"ecdsa"}]
2022/05/13 23:46:20 REQUEST /construction/parse network_identifier:{"blockchain":"EUNO","network":"Testnet"} signed:false transaction:"7b227472616e73616374696f6e223a2230313030303030303031663566663637356138646536653666333237326234386130383734643561636437656531326636363636396332653266386438616431333630333438323636623030303030303030303066666666666666663032363931653732316232333030303030303139373661393134636264333433653865643866636565663237616561336362343762653430303037666361616665333838616332623038616263353134303030303030313937366139313465323431313262653937396264306662616437613064623961303635323561626538386634343062383861633030303030303030222c227363726970745075624b657973223a5b7b2261736d223a224f505f445550204f505f484153483136302065323431313262653937396264306662616437613064623961303635323561626538386634343062204f505f455155414c564552494659204f505f434845434b534947222c22686578223a223736613931346532343131326265393739626430666261643761306462396130363532356162653838663434306238386163222c2272657153696773223a312c2274797065223a227075626b657968617368222c22616464726573736573223a5b2279486341587044426742646b6335475a3172634133734333474b59626161326a4439225d7d5d2c22696e7075745f616d6f756e7473223a5b222d323430303030303030303030225d2c22696e7075745f616464726573736573223a5b2279486341587044426742646b6335475a3172634133734333474b59626161326a4439225d7d"
2022/05/13 23:46:20 RESPONSE /construction/parse operations:[{"operation_identifier":{"index":0,"network_index":0},"type":"INPUT","account":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"amount":{"value":"-240000000000","currency":{"symbol":"tEUNO","decimals":8}},"coin_change":{"coin_identifier":{"identifier":"6b26480336d18a8d2f2e9c66662fe17ecd5a4d87a0482b27f3e6e68d5a67fff5:0"},"coin_action":"coin_spent"}},{"operation_identifier":{"index":1,"network_index":0},"type":"OUTPUT","account":{"address":"yFZa81DZ5ZoPACQCSQjfgAWz9WeibGyUHJ"},"amount":{"value":"150784319081","currency":{"symbol":"tEUNO","decimals":8}}},{"operation_identifier":{"index":2,"network_index":1},"type":"OUTPUT","account":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"amount":{"value":"89215666219","currency":{"symbol":"tEUNO","decimals":8}}}] signers:null metadata:null
2022/05/13 23:46:20 REQUEST /construction/combine network_identifier:{"blockchain":"EUNO","network":"Testnet"} unsigned_transaction:"7b227472616e73616374696f6e223a2230313030303030303031663566663637356138646536653666333237326234386130383734643561636437656531326636363636396332653266386438616431333630333438323636623030303030303030303066666666666666663032363931653732316232333030303030303139373661393134636264333433653865643866636565663237616561336362343762653430303037666361616665333838616332623038616263353134303030303030313937366139313465323431313262653937396264306662616437613064623961303635323561626538386634343062383861633030303030303030222c227363726970745075624b657973223a5b7b2261736d223a224f505f445550204f505f484153483136302065323431313262653937396264306662616437613064623961303635323561626538386634343062204f505f455155414c564552494659204f505f434845434b534947222c22686578223a223736613931346532343131326265393739626430666261643761306462396130363532356162653838663434306238386163222c2272657153696773223a312c2274797065223a227075626b657968617368222c22616464726573736573223a5b2279486341587044426742646b6335475a3172634133734333474b59626161326a4439225d7d5d2c22696e7075745f616d6f756e7473223a5b222d323430303030303030303030225d2c22696e7075745f616464726573736573223a5b2279486341587044426742646b6335475a3172634133734333474b59626161326a4439225d7d" signatures:[{"hex_bytes":"924cca81054ee08330e7701cb3f1fbe71f96fe37629967b353eda990d712b4ec05596ec46e2d2331d1e4e24f7ce8968303bef279a693099be75c5afbe826755e","signing_payload":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9","hex_bytes":"35d991f5895814e519540995ac3129312cb592bc426fcbdd446d1b572e503353","account_identifier":{"address":"yHcAXpDBgBdkc5GZ1rcA3sC3GKYbaa2jD9"},"signature_type":"ecdsa"},"public_key":{"hex_bytes":"02b21d299d9c981e15e381c2d2293d1d78a2e3a1894c47fd388dc2d921a951214d","curve_type":"secp256k1"},"signature_type":"ecdsa"}]
2022/05/13 23:46:20 RESPONSE /construction/combine network_transaction:"7b227472616e73616374696f6e223a223031303030303030303030313031663566663637356138646536653666333237326234386130383734643561636437656531326636363636396332653266386438616431333630333438323636623030303030303030303066666666666666663032363931653732316232333030303030303139373661393134636264333433653865643866636565663237616561336362343762653430303037666361616665333838616332623038616263353134303030303030313937366139313465323431313262653937396264306662616437613064623961303635323561626538386634343062383861633032343833303435303232313030393234636361383130353465653038333330653737303163623366316662653731663936666533373632393936376233353365646139393064373132623465633032323030353539366563343665326432333331643165346532346637636538393638333033626566323739613639333039396265373563356166626538323637353565303132313032623231643239396439633938316531356533383163326432323933643164373861326533613138393463343766643338386463326439323161393531323134643030303030303030222c22696e7075745f616d6f756e7473223a5b222d323430303030303030303030225d7d"
2022/05/13 23:46:20 REQUEST /construction/parse network_identifier:{"blockchain":"EUNO","network":"Testnet"} signed:true transaction:"7b227472616e73616374696f6e223a223031303030303030303030313031663566663637356138646536653666333237326234386130383734643561636437656531326636363636396332653266386438616431333630333438323636623030303030303030303066666666666666663032363931653732316232333030303030303139373661393134636264333433653865643866636565663237616561336362343762653430303037666361616665333838616332623038616263353134303030303030313937366139313465323431313262653937396264306662616437613064623961303635323561626538386634343062383861633032343833303435303232313030393234636361383130353465653038333330653737303163623366316662653731663936666533373632393936376233353365646139393064373132623465633032323030353539366563343665326432333331643165346532346637636538393638333033626566323739613639333039396265373563356166626538323637353565303132313032623231643239396439633938316531356533383163326432323933643164373861326533613138393463343766643338386463326439323161393531323134643030303030303030222c22696e7075745f616d6f756e7473223a5b222d323430303030303030303030225d7d"
2022/05/13 23:46:20 ERROR /construction/parse error:{"err":{},"client_err":null,"retry":false}
2022/05/13 23:46:20 check:construction status server shutting down

Any idea where its going wrong with the convertition?

ENV for rosetta-cli has also been added. (export RECIPIENT=“xxMwLcK2tsC37rGZyDosYAHUeDUQpcff2g”)