-
Notifications
You must be signed in to change notification settings - Fork 81
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
Implemented rpc server method GetRawTransaction #135
Changes from 6 commits
41e27d7
79f41f9
a837151
c280890
30d0a4a
6540cf8
ba3393e
36b69e4
df11e05
42590dc
38528c5
9b91af1
04a25fe
5bff6c4
974e986
087ea47
4b4822a
94ac1d3
5b9f828
da3f83f
a9d07e8
a8328ff
18b6b35
b576289
61b8e96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,8 @@ import ( | |
"os" | ||
"time" | ||
|
||
"github.com/CityOfZion/neo-go/pkg/core/transaction" | ||
"github.com/CityOfZion/neo-go/pkg/util" | ||
"github.com/go-yaml/yaml" | ||
"github.com/pkg/errors" | ||
) | ||
|
@@ -27,6 +29,9 @@ var ( | |
// BuildTime the time and date the current version of the node built, | ||
// set at build time. | ||
BuildTime string | ||
|
||
// ConfigDefault is the Config which has been initialized in the Load method. | ||
ConfigDefault *Config | ||
) | ||
|
||
type ( | ||
|
@@ -49,10 +54,10 @@ type ( | |
|
||
// SystemFee fees related to system. | ||
SystemFee struct { | ||
EnrollmentTransaction int64 `yaml:"EnrollmentTransaction"` | ||
IssueTransaction int64 `yaml:"IssueTransaction"` | ||
PublishTransaction int64 `yaml:"PublishTransaction"` | ||
RegisterTransaction int64 `yaml:"RegisterTransaction"` | ||
EnrollmentTransaction int `yaml:"EnrollmentTransaction"` | ||
IssueTransaction int `yaml:"IssueTransaction"` | ||
PublishTransaction int `yaml:"PublishTransaction"` | ||
RegisterTransaction int `yaml:"RegisterTransaction"` | ||
} | ||
|
||
// ApplicationConfiguration config specific to the node. | ||
|
@@ -116,5 +121,26 @@ func Load(path string, netMode NetMode) (Config, error) { | |
return Config{}, errors.Wrap(err, "Problem unmarshaling config json data") | ||
} | ||
|
||
setConfigDefault(&config) | ||
|
||
return config, nil | ||
} | ||
|
||
func setConfigDefault(cfg *Config) { | ||
ConfigDefault = cfg | ||
} | ||
|
||
func (s SystemFee) TryGetValue(txType transaction.TXType) util.Fixed8 { | ||
switch txType { | ||
case transaction.EnrollmentType: | ||
return util.NewFixed8(s.EnrollmentTransaction) | ||
case transaction.IssueType: | ||
return util.NewFixed8(s.IssueTransaction) | ||
case transaction.PublishType: | ||
return util.NewFixed8(s.PublishTransaction) | ||
case transaction.RegisterType: | ||
return util.NewFixed8(s.RegisterTransaction) | ||
default: | ||
return util.NewFixed8(0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we must fix // NewFixed8 return a new Fixed8 type multiplied by decimals.
func NewFixed8(val int64) Fixed8 {
return Fixed8(decimals * val)
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or mb to: // NewFixed8 return a new Fixed8 type multiplied by decimals.
func NewFixed8(val float64) Fixed8 {
return Fixed8(int64(decimals * val))
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see there |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,8 @@ var ( | |
genAmount = []int{8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
decrementInterval = 2000000 | ||
persistInterval = 1 * time.Second | ||
|
||
BlockchainDefault *Blockchain | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it can't be exported There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean it can't be exported? I Do need to register a blockchain as a default one in order to use it in the func References(t *transaction.Transaction) map[util.Uint256]*transaction.Output {
references := make(map[util.Uint256]*transaction.Output)
for prevHash, inputs := range t.GroupInputsByPrevHash() {
if BlockchainDefault == nil {
panic("no default blockchain available! please register one.")
} else if tx, _, err := BlockchainDefault.GetTransaction(prevHash); err != nil {
tx = nil
} else if tx != nil {
for _, in := range inputs {
references[in.PrevHash] = tx.Outputs[in.PrevIndex]
}
} else {
references = nil
}
}
return references
} At least within the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. data race in runtime... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's a bad practice, to set globalVariable.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for the link! |
||
) | ||
|
||
// Blockchain represents the blockchain. | ||
|
@@ -75,10 +77,11 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration) (*Blockcha | |
return nil, err | ||
} | ||
|
||
RegisterBlockchain(bc) | ||
return bc, nil | ||
} | ||
|
||
// GetBlockchainLevelDB returns blockchain based on configuration | ||
// NewBlockchainLevelDB returns LevelDB blockchain based on configuration | ||
func NewBlockchainLevelDB(cfg config.Config) (*Blockchain, error) { | ||
store, err := storage.NewLevelDBStore( | ||
cfg.ApplicationConfiguration.DataDirectoryPath, | ||
|
@@ -148,7 +151,7 @@ func (bc *Blockchain) init() error { | |
headers := make([]*Header, 0) | ||
|
||
for hash != targetHash { | ||
header, err := bc.getHeader(hash) | ||
header, err := bc.GetHeader(hash) | ||
if err != nil { | ||
return fmt.Errorf("could not get header %s: %s", hash, err) | ||
} | ||
|
@@ -179,6 +182,11 @@ func (bc *Blockchain) run() { | |
} | ||
} | ||
|
||
// RegisterBlockchain registers a blockchain | ||
func RegisterBlockchain(b *Blockchain) { | ||
BlockchainDefault = b | ||
} | ||
|
||
// AddBlock processes the given block and will add it to the cache so it | ||
// can be persisted. | ||
func (bc *Blockchain) AddBlock(block *Block) error { | ||
|
@@ -483,7 +491,7 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) { | |
return block, nil | ||
} | ||
|
||
func (bc *Blockchain) getHeader(hash util.Uint256) (*Header, error) { | ||
func (bc *Blockchain) GetHeader(hash util.Uint256) (*Header, error) { | ||
b, err := bc.Get(storage.AppendPrefix(storage.DataBlock, hash.BytesReverse())) | ||
if err != nil { | ||
return nil, err | ||
|
@@ -504,7 +512,7 @@ func (bc *Blockchain) HasTransaction(hash util.Uint256) bool { | |
// HasBlock return true if the blockchain contains the given | ||
// block hash. | ||
func (bc *Blockchain) HasBlock(hash util.Uint256) bool { | ||
if header, err := bc.getHeader(hash); err == nil { | ||
if header, err := bc.GetHeader(hash); err == nil { | ||
return header.Index <= bc.BlockHeight() | ||
} | ||
return false | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,15 +77,15 @@ func TestGetHeader(t *testing.T) { | |
assert.Nil(t, err) | ||
|
||
hash := block.Hash() | ||
header, err := bc.getHeader(hash) | ||
header, err := bc.GetHeader(hash) | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. require.NoError(t, err) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
t.Fatal(err) | ||
} | ||
assert.Equal(t, block.Header(), header) | ||
|
||
block = newBlock(2) | ||
hash = block.Hash() | ||
_, err = bc.getHeader(block.Hash()) | ||
_, err = bc.GetHeader(block.Hash()) | ||
assert.NotNil(t, err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. replace with |
||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package core | ||
|
||
import ( | ||
"github.com/CityOfZion/neo-go/config" | ||
"github.com/CityOfZion/neo-go/pkg/core/transaction" | ||
"github.com/CityOfZion/neo-go/pkg/util" | ||
) | ||
|
||
// References returns a map with input prevHash as key (util.Uint256) | ||
// and transaction output as value from a transaction t. | ||
// @TODO: unfortunately we couldn't attach this method to the Transaction struct in the | ||
// transaction package because of a import cycle problem. Perhaps we should think to re-design | ||
// the code base to avoid this situation. | ||
func References(t *transaction.Transaction) map[util.Uint256]*transaction.Output { | ||
references := make(map[util.Uint256]*transaction.Output) | ||
|
||
for prevHash, inputs := range t.GroupInputsByPrevHash() { | ||
if BlockchainDefault == nil { | ||
panic("no default blockchain available! please register one.") | ||
} else if tx, _, err := BlockchainDefault.GetTransaction(prevHash); err != nil { | ||
tx = nil | ||
} else if tx != nil { | ||
for _, in := range inputs { | ||
references[in.PrevHash] = tx.Outputs[in.PrevIndex] | ||
} | ||
} else { | ||
references = nil | ||
} | ||
} | ||
return references | ||
} | ||
|
||
// FeePerByte returns network fee divided by the size of the transaction | ||
func FeePerByte(t *transaction.Transaction) util.Fixed8 { | ||
return NetworkFee(t).Div(t.Size()) | ||
} | ||
|
||
// NetworkFee returns network fee | ||
func NetworkFee(t *transaction.Transaction) util.Fixed8 { | ||
inputAmount := util.NewFixed8(0) | ||
for _, txOutput := range References(t) { | ||
if txOutput.AssetID == utilityTokenTX().Hash() { | ||
inputAmount.Add(txOutput.Amount) | ||
} | ||
} | ||
|
||
outputAmount := util.NewFixed8(0) | ||
for _, txOutput := range t.Outputs { | ||
if txOutput.AssetID == utilityTokenTX().Hash() { | ||
outputAmount.Add(txOutput.Amount) | ||
} | ||
} | ||
|
||
return inputAmount.Sub(outputAmount).Sub(SystemFee(t)) | ||
} | ||
|
||
// SystemFee returns system fee | ||
func SystemFee(t *transaction.Transaction) util.Fixed8 { | ||
return config.ConfigDefault.ProtocolConfiguration.SystemFee.TryGetValue(t.Type) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package core | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/CityOfZion/neo-go/config" | ||
"github.com/CityOfZion/neo-go/pkg/core/transaction" | ||
"github.com/CityOfZion/neo-go/pkg/util" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestSize(t *testing.T) { | ||
txID := "f999c36145a41306c846ea80290416143e8e856559818065be3f4e143c60e43a" | ||
tx := getTestTransaction(txID, t) | ||
fmt.Println(tx.Bytes()) | ||
assert.Equal(t, 283, tx.Size()) | ||
assert.Equal(t, 22, util.GetVarSize(tx.Attributes)) | ||
assert.Equal(t, 35, util.GetVarSize(tx.Inputs)) | ||
assert.Equal(t, 121, util.GetVarSize(tx.Outputs)) | ||
assert.Equal(t, 103, util.GetVarSize(tx.Scripts)) | ||
} | ||
|
||
func getTestBlockchain(t *testing.T) *Blockchain { | ||
net := config.ModeUnitTestNet | ||
configPath := "../../config" | ||
cfg, err := config.Load(configPath, net) | ||
if err != nil { | ||
t.Fatal("could not create levelDB chain", err) | ||
} | ||
|
||
// adjust datadirectory to point to the correct folder | ||
cfg.ApplicationConfiguration.DataDirectoryPath = "../rpc/chains/unit_testnet" | ||
chain, err := NewBlockchainLevelDB(cfg) | ||
if err != nil { | ||
t.Fatal("could not create levelDB chain", err) | ||
} | ||
|
||
return chain | ||
} | ||
|
||
func getTestTransaction(txID string, t *testing.T) *transaction.Transaction { | ||
chain := getTestBlockchain(t) | ||
|
||
txHash, err := util.Uint256DecodeString(txID) | ||
if err != nil { | ||
t.Fatalf("could not decode string %s to Uint256: err =%s", txID, err) | ||
} | ||
|
||
tx, _, err := chain.GetTransaction(txHash) | ||
if err != nil { | ||
t.Fatalf("Could not get transaction with hash=%s: err=%s", txHash, err) | ||
} | ||
return tx | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,3 +47,57 @@ const ( | |
Remark14 AttrUsage = 0xfe | ||
Remark15 AttrUsage = 0xff | ||
) | ||
|
||
// String implements the stringer interface. | ||
func (attr AttrUsage) String() string { | ||
attrLookup := map[AttrUsage]string{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mb we can move that to global? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
ContractHash: "ContractHash", | ||
ECDH02: "ECDH02", | ||
ECDH03: "ECDH03", | ||
Script: "Script", | ||
Vote: "Vote", | ||
CertURL: "CertURL", | ||
DescriptionURL: "DescriptionURL", | ||
Description: "Description", | ||
|
||
Hash1: "Hash1", | ||
Hash2: "Hash2", | ||
Hash3: "Hash3", | ||
Hash4: "Hash4", | ||
Hash5: "Hash5", | ||
Hash6: "Hash6", | ||
Hash7: "Hash7", | ||
Hash8: "Hash8", | ||
Hash9: "Hash9", | ||
Hash10: "Hash10", | ||
Hash11: "Hash11", | ||
Hash12: "Hash12", | ||
Hash13: "Hash13", | ||
Hash14: "Hash14", | ||
Hash15: "Hash15", | ||
|
||
Remark: "Remark", | ||
Remark1: "Remark1", | ||
Remark2: "Remark2", | ||
Remark3: "Remark3", | ||
Remark4: "Remark4", | ||
Remark5: "Remark5", | ||
Remark6: "Remark6", | ||
Remark7: "Remark7", | ||
Remark8: "Remark8", | ||
Remark9: "Remark9", | ||
Remark10: "Remark10", | ||
Remark11: "Remark11", | ||
Remark12: "Remark12", | ||
Remark13: "Remark13", | ||
Remark14: "Remark14", | ||
Remark15: "Remark15", | ||
} | ||
|
||
v, ok := attrLookup[attr] | ||
if !ok { | ||
return "Unkown Attribute" | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if v, ok := attrLookup[attr]; ok {
return v
}
return "Unkown Attribute" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
return v | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,11 @@ package transaction | |
|
||
import ( | ||
"encoding/binary" | ||
"encoding/hex" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"unsafe" | ||
|
||
"github.com/CityOfZion/neo-go/pkg/util" | ||
) | ||
|
@@ -77,3 +80,33 @@ func (attr *Attribute) EncodeBinary(w io.Writer) error { | |
} | ||
return fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Usage) | ||
} | ||
|
||
// Size returns the size in number bytes of the Attribute | ||
func (attr *Attribute) Size() int { | ||
var b byte | ||
if attr.Usage == ContractHash || attr.Usage == ECDH02 || attr.Usage == ECDH03 || attr.Usage == Vote || (attr.Usage >= Hash1 && attr.Usage <= Hash15) { | ||
return int(unsafe.Sizeof(attr.Usage)) + 32 | ||
} else if attr.Usage == Script { | ||
return int(unsafe.Sizeof(attr.Usage)) + 20 | ||
} else if attr.Usage == DescriptionURL { | ||
return int(unsafe.Sizeof(attr.Usage)) + int(unsafe.Sizeof(b)) + len(attr.Data) | ||
} else { | ||
return int(unsafe.Sizeof(attr.Usage)) + util.GetVarSize(attr.Data) | ||
} | ||
} | ||
|
||
// MarshalJSON implements the json Marschaller interface | ||
func (attr *Attribute) MarshalJSON() ([]byte, error) { | ||
j, err := json.Marshal( | ||
struct { | ||
Usage string `json:"usage"` | ||
Data string `json:"data"` | ||
}{ | ||
attr.Usage.String(), | ||
hex.EncodeToString(attr.Data), | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mb simplify that: return json.Marshal(map[string]string{
"usage": attr.Usage.String(),
"data": hex.EncodeToString(attr.Data),
}) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don’t think that we really need a structure for that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if err != nil { | ||
return nil, err | ||
} | ||
return j, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it must be int64
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or.. mb float64
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the C# implementation is int64
Why do you suggest
float64
?Shall I change everything so that the
NewFixed8
method accept int64?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dauTT yep,
long
/int64
for new.. but...and
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, I think I understood what you mean.