Move example path outside

pull/117/head
Baohua Yang 2018-01-05 14:02:41 +08:00
parent ae342ef96b
commit 96b581a923
35 changed files with 7753 additions and 0 deletions

View File

@ -0,0 +1,104 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
var A, B string
var Aval, Bval, X int
// Init callback representing the invocation of a chaincode
// This chaincode will manage two accounts A and B and will transfer X units from A to B upon invoke
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
var err error
_, args := stub.GetFunctionAndParameters()
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
/************
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval))
if err != nil {
return nil, err
}
stub.PutState(B, []byte(strconv.Itoa(Bval))
err = stub.PutState(B, []byte(strconv.Itoa(Bval))
if err != nil {
return nil, err
}
************/
return shim.Success(nil)
}
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// Transaction makes payment of X units from A to B
X, err := strconv.Atoi(args[0])
if err != nil {
fmt.Printf("Error convert %s to integer: %s", args[0], err)
return shim.Error(fmt.Sprintf("Error convert %s to integer: %s", args[0], err))
}
Aval = Aval - X
Bval = Bval + X
ts, err2 := stub.GetTxTimestamp()
if err2 != nil {
fmt.Printf("Error getting transaction timestamp: %s", err2)
return shim.Error(fmt.Sprintf("Error getting transaction timestamp: %s", err2))
}
fmt.Printf("Transaction Time: %v,Aval = %d, Bval = %d\n", ts, Aval, Bval)
return shim.Success(nil)
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
return t.invoke(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\"")
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

View File

@ -0,0 +1,199 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/pquerna/ffjson/ffjson"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02 Init")
_, args := stub.GetFunctionAndParameters()
var A, B string // Entities
var Aval, Bval int // Asset holdings
var err error
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
item := map[string]string {"hi":"morning"}
buf, err := ffjson.Marshal(&item)
fmt.Printf("ffjson result=%v\n", buf)
return shim.Success(nil)
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02 Invoke")
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
// Make payment of X units from A to B
return t.invoke(stub, args)
} else if function == "delete" {
// Deletes an entity from its state
return t.delete(stub, args)
} else if function == "query" {
// the old "Query" is now implemtned in invoke
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A, B string // Entities
var Aval, Bval int // Asset holdings
var X int // Transaction value
var err error
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}
A = args[0]
B = args[1]
// Get the state from the ledger
// TODO: will be nice to have a GetAllState call to ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
return shim.Error("Failed to get state")
}
if Avalbytes == nil {
return shim.Error("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes))
Bvalbytes, err := stub.GetState(B)
if err != nil {
return shim.Error("Failed to get state")
}
if Bvalbytes == nil {
return shim.Error("Entity not found")
}
Bval, _ = strconv.Atoi(string(Bvalbytes))
// Perform the execution
X, err = strconv.Atoi(args[2])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
Aval = Aval - X
Bval = Bval + X
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state back to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
A := args[0]
// Delete the key from the state in ledger
err := stub.DelState(A)
if err != nil {
return shim.Error("Failed to delete state")
}
return shim.Success(nil)
}
// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0]
// Get the state from the ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
return shim.Error(jsonResp)
}
if Avalbytes == nil {
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
return shim.Error(jsonResp)
}
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(Avalbytes)
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

View File

@ -0,0 +1,112 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"testing"
"github.com/hyperledger/fabric/core/chaincode/shim"
)
func checkInit(t *testing.T, stub *shim.MockStub, args [][]byte) {
res := stub.MockInit("1", args)
if res.Status != shim.OK {
fmt.Println("Init failed", string(res.Message))
t.FailNow()
}
}
func checkState(t *testing.T, stub *shim.MockStub, name string, value string) {
bytes := stub.State[name]
if bytes == nil {
fmt.Println("State", name, "failed to get value")
t.FailNow()
}
if string(bytes) != value {
fmt.Println("State value", name, "was not", value, "as expected")
t.FailNow()
}
}
func checkQuery(t *testing.T, stub *shim.MockStub, name string, value string) {
res := stub.MockInvoke("1", [][]byte{[]byte("query"), []byte(name)})
if res.Status != shim.OK {
fmt.Println("Query", name, "failed", string(res.Message))
t.FailNow()
}
if res.Payload == nil {
fmt.Println("Query", name, "failed to get value")
t.FailNow()
}
if string(res.Payload) != value {
fmt.Println("Query value", name, "was not", value, "as expected")
t.FailNow()
}
}
func checkInvoke(t *testing.T, stub *shim.MockStub, args [][]byte) {
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
fmt.Println("Invoke", args, "failed", string(res.Message))
t.FailNow()
}
}
func TestExample02_Init(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex02", scc)
// Init A=123 B=234
checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("123"), []byte("B"), []byte("234")})
checkState(t, stub, "A", "123")
checkState(t, stub, "B", "234")
}
func TestExample02_Query(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex02", scc)
// Init A=345 B=456
checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("345"), []byte("B"), []byte("456")})
// Query A
checkQuery(t, stub, "A", "345")
// Query B
checkQuery(t, stub, "B", "456")
}
func TestExample02_Invoke(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex02", scc)
// Init A=567 B=678
checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("567"), []byte("B"), []byte("678")})
// Invoke A->B for 123
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("123")})
checkQuery(t, stub, "A", "444")
checkQuery(t, stub, "B", "801")
// Invoke B->A for 234
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte("B"), []byte("A"), []byte("234")})
checkQuery(t, stub, "A", "678")
checkQuery(t, stub, "B", "567")
checkQuery(t, stub, "A", "678")
checkQuery(t, stub, "B", "567")
}

View File

@ -0,0 +1,100 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This program is an erroneous chaincode program that attempts to put state in query context - query should return error
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
// Init takes a string and int. These are stored as a key/value pair in the state
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
var A string // Entity
var Aval int // Asset holding
var err error
_, args := stub.GetFunctionAndParameters()
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d\n", Aval)
// Write the state to the ledger - this put is legal within Run
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Invoke is a no-op
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "query" {
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"query\"")
}
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entity
var Aval int // Asset holding
var err error
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d\n", Aval)
// Write the state to the ledger - this put is illegal within Run
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
jsonResp := "{\"Error\":\"Cannot put state within chaincode query\"}"
return shim.Error(jsonResp)
}
return shim.Success(nil)
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting chaincode: %s", err)
}
}

View File

@ -0,0 +1,72 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"testing"
"github.com/hyperledger/fabric/core/chaincode/shim"
)
func checkInit(t *testing.T, scc *SimpleChaincode, stub *shim.MockStub, args [][]byte) {
res := stub.MockInit("1", args)
if res.Status != shim.OK {
fmt.Println("Init failed", res.Message)
t.FailNow()
}
}
func checkState(t *testing.T, stub *shim.MockStub, name string, value string) {
bytes := stub.State[name]
if bytes == nil {
fmt.Println("State", name, "failed to get value")
t.FailNow()
}
if string(bytes) != value {
fmt.Println("State value", name, "was not", value, "as expected")
t.FailNow()
}
}
func checkInvoke(t *testing.T, scc *SimpleChaincode, stub *shim.MockStub, args [][]byte) {
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
fmt.Println("Query failed", string(res.Message))
t.FailNow()
}
}
func TestExample03_Init(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex03", scc)
// Init A=123 B=234
checkInit(t, scc, stub, [][]byte{[]byte("init"), []byte("A"), []byte("123")})
checkState(t, stub, "A", "123")
}
func TestExample03_Invoke(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex03", scc)
// Init A=345 B=456
checkInit(t, scc, stub, [][]byte{[]byte("init"), []byte("A"), []byte("345")})
// Invoke "query"
checkInvoke(t, scc, stub, [][]byte{[]byte("query"), []byte("A"), []byte("345")})
}

View File

@ -0,0 +1,174 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// This chaincode is a test for chaincode invoking another chaincode - invokes chaincode_example02
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func toChaincodeArgs(args ...string) [][]byte {
bargs := make([][]byte, len(args))
for i, arg := range args {
bargs[i] = []byte(arg)
}
return bargs
}
// Init takes two arguments, a string and int. These are stored in the key/value pair in the state
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
var event string // Indicates whether event has happened. Initially 0
var eventVal int // State of event
var err error
_, args := stub.GetFunctionAndParameters()
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
// Initialize the chaincode
event = args[0]
eventVal, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for event status")
}
fmt.Printf("eventVal = %d\n", eventVal)
err = stub.PutState(event, []byte(strconv.Itoa(eventVal)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Invoke invokes another chaincode - chaincode_example02, upon receipt of an event and changes event state
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var event string // Event entity
var eventVal int // State of event
var err error
if len(args) != 3 && len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 3 or 4")
}
chainCodeToCall := args[0]
event = args[1]
eventVal, err = strconv.Atoi(args[2])
if err != nil {
return shim.Error("Expected integer value for event state change")
}
channelID := ""
if len(args) == 4 {
channelID = args[3]
}
if eventVal != 1 {
fmt.Printf("Unexpected event. Doing nothing\n")
return shim.Success(nil)
}
f := "invoke"
invokeArgs := toChaincodeArgs(f, "a", "b", "10")
response := stub.InvokeChaincode(chainCodeToCall, invokeArgs, channelID)
if response.Status != shim.OK {
errStr := fmt.Sprintf("Failed to invoke chaincode. Got error: %s", string(response.Payload))
fmt.Printf(errStr)
return shim.Error(errStr)
}
fmt.Printf("Invoke chaincode successful. Got response %s", string(response.Payload))
// Write the event state back to the ledger
err = stub.PutState(event, []byte(strconv.Itoa(eventVal)))
if err != nil {
return shim.Error(err.Error())
}
return response
}
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var event string // Event entity
var err error
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting entity to query")
}
event = args[0]
var jsonResp string
// Get the state from the ledger
eventValbytes, err := stub.GetState(event)
if err != nil {
jsonResp = "{\"Error\":\"Failed to get state for " + event + "\"}"
return shim.Error(jsonResp)
}
if eventValbytes == nil {
jsonResp = "{\"Error\":\"Nil value for " + event + "\"}"
return shim.Error(jsonResp)
}
if len(args) > 3 {
chainCodeToCall := args[1]
queryKey := args[2]
channel := args[3]
f := "query"
invokeArgs := toChaincodeArgs(f, queryKey)
response := stub.InvokeChaincode(chainCodeToCall, invokeArgs, channel)
if response.Status != shim.OK {
errStr := fmt.Sprintf("Failed to invoke chaincode. Got error: %s", err.Error())
fmt.Printf(errStr)
return shim.Error(errStr)
}
jsonResp = string(response.Payload)
} else {
jsonResp = "{\"Name\":\"" + event + "\",\"Amount\":\"" + string(eventValbytes) + "\"}"
}
fmt.Printf("Query Response: %s\n", jsonResp)
return shim.Success([]byte(jsonResp))
}
// Invoke is called by fabric to execute a transaction
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
return t.invoke(stub, args)
} else if function == "query" {
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"query\"")
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

View File

@ -0,0 +1,119 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"testing"
"github.com/hyperledger/fabric/core/chaincode/shim"
ex02 "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
)
// this is the response to any successful Invoke() on chaincode_example04
var eventResponse = "{\"Name\":\"Event\",\"Amount\":\"1\"}"
func checkInit(t *testing.T, stub *shim.MockStub, args [][]byte) {
res := stub.MockInit("1", args)
if res.Status != shim.OK {
fmt.Println("Init failed", string(res.Message))
t.FailNow()
}
}
func checkState(t *testing.T, stub *shim.MockStub, name string, value string) {
bytes := stub.State[name]
if bytes == nil {
fmt.Println("State", name, "failed to get value")
t.FailNow()
}
if string(bytes) != value {
fmt.Println("State value", name, "was not", value, "as expected")
t.FailNow()
}
}
func checkQuery(t *testing.T, stub *shim.MockStub, name string, value string) {
res := stub.MockInvoke("1", [][]byte{[]byte("query"), []byte(name)})
if res.Status != shim.OK {
fmt.Println("Query", name, "failed", string(res.Message))
t.FailNow()
}
if res.Payload == nil {
fmt.Println("Query", name, "failed to get value")
t.FailNow()
}
if string(res.Payload) != value {
fmt.Println("Query value", name, "was not", value, "as expected")
t.FailNow()
}
}
func checkInvoke(t *testing.T, stub *shim.MockStub, args [][]byte) {
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
fmt.Println("Invoke", args, "failed", string(res.Message))
t.FailNow()
}
}
func TestExample04_Init(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex04", scc)
// Init A=123 B=234
checkInit(t, stub, [][]byte{[]byte("init"), []byte("Event"), []byte("123")})
checkState(t, stub, "Event", "123")
}
func TestExample04_Query(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex04", scc)
// Init A=345 B=456
checkInit(t, stub, [][]byte{[]byte("init"), []byte("Event"), []byte("1")})
// Query A
checkQuery(t, stub, "Event", eventResponse)
}
func TestExample04_Invoke(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex04", scc)
chaincodeToInvoke := "ex02"
ccEx2 := new(ex02.SimpleChaincode)
stubEx2 := shim.NewMockStub(chaincodeToInvoke, ccEx2)
checkInit(t, stubEx2, [][]byte{[]byte("init"), []byte("a"), []byte("111"), []byte("b"), []byte("222")})
stub.MockPeerChaincode(chaincodeToInvoke, stubEx2)
// Init A=567 B=678
checkInit(t, stub, [][]byte{[]byte("init"), []byte("Event"), []byte("1")})
// Invoke A->B for 10 via Example04's chaincode
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte(chaincodeToInvoke), []byte("Event"), []byte("1")})
checkQuery(t, stub, "Event", eventResponse)
checkQuery(t, stubEx2, "a", "101")
checkQuery(t, stubEx2, "b", "232")
// Invoke A->B for 10 via Example04's chaincode
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte(chaincodeToInvoke), []byte("Event"), []byte("1")})
checkQuery(t, stub, "Event", eventResponse)
checkQuery(t, stubEx2, "a", "91")
checkQuery(t, stubEx2, "b", "242")
}

View File

@ -0,0 +1,215 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// This chaincode is a test for chaincode querying another chaincode - invokes chaincode_example02 and computes the sum of a and b and stores it as state
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func toChaincodeArgs(args ...string) [][]byte {
bargs := make([][]byte, len(args))
for i, arg := range args {
bargs[i] = []byte(arg)
}
return bargs
}
// Init takes two arguments, a string and int. The string will be a key with
// the int as a value.
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
var sum string // Sum of asset holdings across accounts. Initially 0
var sumVal int // Sum of holdings
var err error
_, args := stub.GetFunctionAndParameters()
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
// Initialize the chaincode
sum = args[0]
sumVal, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for sum")
}
fmt.Printf("sumVal = %d\n", sumVal)
// Write the state to the ledger
err = stub.PutState(sum, []byte(strconv.Itoa(sumVal)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Invoke queries another chaincode and updates its own state
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var sum, channelName string // Sum entity
var Aval, Bval, sumVal int // value of sum entity - to be computed
var err error
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting atleast 2")
}
chaincodeName := args[0] // Expecting name of the chaincode you would like to call, this name would be given during chaincode install time
sum = args[1]
if len(args) > 2 {
channelName = args[2]
} else {
channelName = ""
}
// Query chaincode_example02
f := "query"
queryArgs := toChaincodeArgs(f, "a")
// if chaincode being invoked is on the same channel,
// then channel defaults to the current channel and args[2] can be "".
// If the chaincode being called is on a different channel,
// then you must specify the channel name in args[2]
response := stub.InvokeChaincode(chaincodeName, queryArgs, channelName)
if response.Status != shim.OK {
errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", response.Payload)
fmt.Printf(errStr)
return shim.Error(errStr)
}
Aval, err = strconv.Atoi(string(response.Payload))
if err != nil {
errStr := fmt.Sprintf("Error retrieving state from ledger for queried chaincode: %s", err.Error())
fmt.Printf(errStr)
return shim.Error(errStr)
}
queryArgs = toChaincodeArgs(f, "b")
response = stub.InvokeChaincode(chaincodeName, queryArgs, channelName)
if response.Status != shim.OK {
errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", response.Payload)
fmt.Printf(errStr)
return shim.Error(errStr)
}
Bval, err = strconv.Atoi(string(response.Payload))
if err != nil {
errStr := fmt.Sprintf("Error retrieving state from ledger for queried chaincode: %s", err.Error())
fmt.Printf(errStr)
return shim.Error(errStr)
}
// Compute sum
sumVal = Aval + Bval
// Write sumVal back to the ledger
err = stub.PutState(sum, []byte(strconv.Itoa(sumVal)))
if err != nil {
return shim.Error(err.Error())
}
fmt.Printf("Invoke chaincode successful. Got sum %d\n", sumVal)
return shim.Success([]byte(strconv.Itoa(sumVal)))
}
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var sum, channelName string // Sum entity
var Aval, Bval, sumVal int // value of sum entity - to be computed
var err error
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting atleast 2")
}
chaincodeName := args[0] // Expecting name of the chaincode you would like to call, this name would be given during chaincode install time
sum = args[1]
if len(args) > 2 {
channelName = args[2]
} else {
channelName = ""
}
// Query chaincode_example02
f := "query"
queryArgs := toChaincodeArgs(f, "a")
// if chaincode being invoked is on the same channel,
// then channel defaults to the current channel and args[2] can be "".
// If the chaincode being called is on a different channel,
// then you must specify the channel name in args[2]
response := stub.InvokeChaincode(chaincodeName, queryArgs, channelName)
if response.Status != shim.OK {
errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", response.Payload)
fmt.Printf(errStr)
return shim.Error(errStr)
}
Aval, err = strconv.Atoi(string(response.Payload))
if err != nil {
errStr := fmt.Sprintf("Error retrieving state from ledger for queried chaincode: %s", err.Error())
fmt.Printf(errStr)
return shim.Error(errStr)
}
queryArgs = toChaincodeArgs(f, "b")
response = stub.InvokeChaincode(chaincodeName, queryArgs, channelName)
if response.Status != shim.OK {
errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", response.Payload)
fmt.Printf(errStr)
return shim.Error(errStr)
}
Bval, err = strconv.Atoi(string(response.Payload))
if err != nil {
errStr := fmt.Sprintf("Error retrieving state from ledger for queried chaincode: %s", err.Error())
fmt.Printf(errStr)
return shim.Error(errStr)
}
// Compute sum
sumVal = Aval + Bval
fmt.Printf("Query chaincode successful. Got sum %d\n", sumVal)
jsonResp := "{\"Name\":\"" + sum + "\",\"Value\":\"" + strconv.Itoa(sumVal) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success([]byte(strconv.Itoa(sumVal)))
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
return t.invoke(stub, args)
} else if function == "query" {
return t.query(stub, args)
}
return shim.Success([]byte("Invalid invoke function name. Expecting \"invoke\" \"query\""))
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

View File

@ -0,0 +1,128 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"testing"
"github.com/hyperledger/fabric/core/chaincode/shim"
ex02 "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
)
var chaincodeName = "ex02"
// chaincode_example05 looks like it wanted to return a JSON response to Query()
// it doesn't actually do this though, it just returns the sum value
func jsonResponse(name string, value string) string {
return fmt.Sprintf("jsonResponse = \"{\"Name\":\"%v\",\"Value\":\"%v\"}", name, value)
}
func checkInit(t *testing.T, stub *shim.MockStub, args [][]byte) {
res := stub.MockInit("1", args)
if res.Status != shim.OK {
fmt.Println("Init failed", string(res.Message))
t.FailNow()
}
}
func checkState(t *testing.T, stub *shim.MockStub, name string, expect string) {
bytes := stub.State[name]
if bytes == nil {
fmt.Println("State", name, "failed to get value")
t.FailNow()
}
if string(bytes) != expect {
fmt.Println("State value", name, "was not", expect, "as expected")
t.FailNow()
}
}
func checkQuery(t *testing.T, stub *shim.MockStub, args [][]byte, expect string) {
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
fmt.Println("Query", args, "failed", string(res.Message))
t.FailNow()
}
if res.Payload == nil {
fmt.Println("Query", args, "failed to get result")
t.FailNow()
}
if string(res.Payload) != expect {
fmt.Println("Query result ", string(res.Payload), "was not", expect, "as expected")
t.FailNow()
}
}
func checkInvoke(t *testing.T, stub *shim.MockStub, args [][]byte) {
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
fmt.Println("Invoke", args, "failed", string(res.Message))
t.FailNow()
}
}
func TestExample05_Init(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex05", scc)
// Init A=123 B=234
checkInit(t, stub, [][]byte{[]byte("init"), []byte("sumStoreName"), []byte("432")})
checkState(t, stub, "sumStoreName", "432")
}
func TestExample05_Query(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex05", scc)
ccEx2 := new(ex02.SimpleChaincode)
stubEx2 := shim.NewMockStub(chaincodeName, ccEx2)
checkInit(t, stubEx2, [][]byte{[]byte("init"), []byte("a"), []byte("111"), []byte("b"), []byte("222")})
stub.MockPeerChaincode(chaincodeName, stubEx2)
checkInit(t, stub, [][]byte{[]byte("init"), []byte("sumStoreName"), []byte("0")})
// a + b = 111 + 222 = 333
checkQuery(t, stub, [][]byte{[]byte("query"), []byte(chaincodeName), []byte("sumStoreName"), []byte("")}, "333") // example05 doesn't return JSON?
}
func TestExample05_Invoke(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex05", scc)
ccEx2 := new(ex02.SimpleChaincode)
stubEx2 := shim.NewMockStub(chaincodeName, ccEx2)
checkInit(t, stubEx2, [][]byte{[]byte("init"), []byte("a"), []byte("222"), []byte("b"), []byte("333")})
stub.MockPeerChaincode(chaincodeName, stubEx2)
checkInit(t, stub, [][]byte{[]byte("init"), []byte("sumStoreName"), []byte("0")})
// a + b = 222 + 333 = 555
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte(chaincodeName), []byte("sumStoreName"), []byte("")})
checkQuery(t, stub, [][]byte{[]byte("query"), []byte(chaincodeName), []byte("sumStoreName"), []byte("")}, "555") // example05 doesn't return JSON?
checkQuery(t, stubEx2, [][]byte{[]byte("query"), []byte("a")}, "222")
checkQuery(t, stubEx2, [][]byte{[]byte("query"), []byte("b")}, "333")
// update A-=10 and B+=10
checkInvoke(t, stubEx2, [][]byte{[]byte("invoke"), []byte("a"), []byte("b"), []byte("10")})
// a + b = 212 + 343 = 555
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte(chaincodeName), []byte("sumStoreName"), []byte("")})
checkQuery(t, stub, [][]byte{[]byte("query"), []byte(chaincodeName), []byte("sumStoreName"), []byte("")}, "555") // example05 doesn't return JSON?
checkQuery(t, stubEx2, [][]byte{[]byte("query"), []byte("a")}, "212")
checkQuery(t, stubEx2, [][]byte{[]byte("query"), []byte("b")}, "343")
}

View File

@ -0,0 +1,80 @@
# Using EncCC
To test `EncCC` you need to first generate an AES 256 bit key as a base64
encoded string so that it can be passed as JSON to the peer chaincode
invoke's transient parameter.
Note: Before getting started you must use govendor to add external dependencies. Please issue the following commands inside the "enccc_example" folder:
```
govendor init
govendor add +external
```
Let's generate the encryption and decryption keys. The example will simulate a shared key so the key is used for both encryption and decryption.
```
ENCKEY=`openssl rand 32 -base64` && DECKEY=$ENCKEY
```
At this point, you can invoke the chaincode to encrypt key-value pairs as
follows:
Note: the following assumes the env is initialized and peer has joined channel "my-ch".
```
peer chaincode invoke -n enccc -C my-ch -c '{"Args":["ENCRYPT","key1","value1"]}' --transient "{\"ENCKEY\":\"$ENCKEY\"}"
```
This call will encrypt using a random IV. This may be undesirable for
instance if the chaincode invocation needs to be endorsed by multiple
peers since it would cause the endorsement of conflicting read/write sets.
It is possible to encrypt deterministically by specifying the IV, as
follows: at first the IV must be created
```
IV=`openssl rand 16 -base64`
```
Then, the IV may be specified in the transient field
```
peer chaincode invoke -n enccc -C my-ch -c '{"Args":["ENCRYPT","key2","value2"]}' --transient "{\"ENCKEY\":\"$ENCKEY\",\"IV\":\"$IV\"}"
```
Two such invocations will produce equal KVS writes, which can be endorsed by multiple nodes.
The value can be retrieved back as follows
```
peer chaincode query -n enccc -C my-ch -c '{"Args":["DECRYPT","key1"]}' --transient "{\"DECKEY\":\"$DECKEY\"}"
```
```
peer chaincode query -n enccc -C my-ch -c '{"Args":["DECRYPT","key2"]}' --transient "{\"DECKEY\":\"$DECKEY\"}"
```
Note that in this case we use a chaincode query operation; while the use of the
transient field guarantees that the content will not be written to the ledger,
the chaincode decrypts the message and puts it in the proposal response. An
invocation would persist the result in the ledger for all channel readers to
see whereas a query can be discarded and so the result remains confidential.
To test signing and verifying, you also need to generate an ECDSA key for the appopriate
curve, as follows.
```
On Intel:
SIGKEY=`openssl ecparam -name prime256v1 -genkey | tail -n5 | base64 -w0` && VERKEY=$SIGKEY
On Mac:
SIGKEY=`openssl ecparam -name prime256v1 -genkey | tail -n5 | base64` && VERKEY=$SIGKEY
```
At this point, you can invoke the chaincode to sign and then encrypt key-value
pairs as follows
```
peer chaincode invoke -n enccc -C my-ch -c '{"Args":["ENCRYPTSIGN","key3","value3"]}' --transient "{\"ENCKEY\":\"$ENCKEY\",\"SIGKEY\":\"$SIGKEY\"}"
```
And similarly to retrieve them using a query
```
peer chaincode query -n enccc -C my-ch -c '{"Args":["DECRYPTVERIFY","key3"]}' --transient "{\"DECKEY\":\"$DECKEY\",\"VERKEY\":\"$VERKEY\"}"
```

View File

@ -0,0 +1,223 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"fmt"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/chaincode/shim/ext/entities"
pb "github.com/hyperledger/fabric/protos/peer"
)
const DECKEY = "DECKEY"
const VERKEY = "VERKEY"
const ENCKEY = "ENCKEY"
const SIGKEY = "SIGKEY"
const IV = "IV"
// EncCC example simple Chaincode implementation of a chaincode that uses encryption/signatures
type EncCC struct {
bccspInst bccsp.BCCSP
}
// Init does nothing for this cc
func (t *EncCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
// Encrypter exposes how to write state to the ledger after having
// encrypted it with an AES 256 bit key that has been provided to the chaincode through the
// transient field
func (t *EncCC) Encrypter(stub shim.ChaincodeStubInterface, args []string, encKey, IV []byte) pb.Response {
// create the encrypter entity - we give it an ID, the bccsp instance, the key and (optionally) the IV
ent, err := entities.NewAES256EncrypterEntity("ID", t.bccspInst, encKey, IV)
if err != nil {
return shim.Error(fmt.Sprintf("entities.NewAES256EncrypterEntity failed, err %s", err))
}
if len(args) != 2 {
return shim.Error("Expected 2 parameters to function Encrypter")
}
key := args[0]
cleartextValue := []byte(args[1])
// here, we encrypt cleartextValue and assign it to key
err = encryptAndPutState(stub, ent, key, cleartextValue)
if err != nil {
return shim.Error(fmt.Sprintf("encryptAndPutState failed, err %+v", err))
}
return shim.Success(nil)
}
// Decrypter exposes how to read from the ledger and decrypt using an AES 256
// bit key that has been provided to the chaincode through the transient field.
func (t *EncCC) Decrypter(stub shim.ChaincodeStubInterface, args []string, decKey, IV []byte) pb.Response {
// create the encrypter entity - we give it an ID, the bccsp instance, the key and (optionally) the IV
ent, err := entities.NewAES256EncrypterEntity("ID", t.bccspInst, decKey, IV)
if err != nil {
return shim.Error(fmt.Sprintf("entities.NewAES256EncrypterEntity failed, err %s", err))
}
if len(args) != 1 {
return shim.Error("Expected 1 parameters to function Decrypter")
}
key := args[0]
// here we decrypt the state associated to key
cleartextValue, err := getStateAndDecrypt(stub, ent, key)
if err != nil {
return shim.Error(fmt.Sprintf("getStateAndDecrypt failed, err %+v", err))
}
// here we return the decrypted value as a result
return shim.Success(cleartextValue)
}
// EncrypterSigner exposes how to write state to the ledger after having received keys for
// encrypting (AES 256 bit key) and signing (X9.62/SECG curve over a 256 bit prime field) that has been provided to the chaincode through the
// transient field
func (t *EncCC) EncrypterSigner(stub shim.ChaincodeStubInterface, args []string, encKey, sigKey []byte) pb.Response {
// create the encrypter/signer entity - we give it an ID, the bccsp instance and the keys
ent, err := entities.NewAES256EncrypterECDSASignerEntity("ID", t.bccspInst, encKey, sigKey)
if err != nil {
return shim.Error(fmt.Sprintf("entities.NewAES256EncrypterEntity failed, err %s", err))
}
if len(args) != 2 {
return shim.Error("Expected 2 parameters to function EncrypterSigner")
}
key := args[0]
cleartextValue := []byte(args[1])
// here, we sign cleartextValue, encrypt it and assign it to key
err = signEncryptAndPutState(stub, ent, key, cleartextValue)
if err != nil {
return shim.Error(fmt.Sprintf("signEncryptAndPutState failed, err %+v", err))
}
return shim.Success(nil)
}
// DecrypterVerify exposes how to get state to the ledger after having received keys for
// decrypting (AES 256 bit key) and verifying (X9.62/SECG curve over a 256 bit prime field) that has been provided to the chaincode through the
// transient field
func (t *EncCC) DecrypterVerify(stub shim.ChaincodeStubInterface, args []string, decKey, verKey []byte) pb.Response {
// create the decrypter/verify entity - we give it an ID, the bccsp instance and the keys
ent, err := entities.NewAES256EncrypterECDSASignerEntity("ID", t.bccspInst, decKey, verKey)
if err != nil {
return shim.Error(fmt.Sprintf("entities.NewAES256DecrypterEntity failed, err %s", err))
}
if len(args) != 1 {
return shim.Error("Expected 1 parameters to function DecrypterVerify")
}
key := args[0]
// here we decrypt the state associated to key and verify it
cleartextValue, err := getStateDecryptAndVerify(stub, ent, key)
if err != nil {
return shim.Error(fmt.Sprintf("getStateDecryptAndVerify failed, err %+v", err))
}
// here we return the decrypted and verified value as a result
return shim.Success(cleartextValue)
}
// RangeDecrypter shows how range queries may be satisfied by using the decrypter
// entity directly to decrypt previously encrypted key-value pairs
func (t *EncCC) RangeDecrypter(stub shim.ChaincodeStubInterface, decKey []byte) pb.Response {
// create the encrypter entity - we give it an ID, the bccsp instance and the key
ent, err := entities.NewAES256EncrypterEntity("ID", t.bccspInst, decKey, nil)
if err != nil {
return shim.Error(fmt.Sprintf("entities.NewAES256EncrypterEntity failed, err %s", err))
}
bytes, err := getStateByRangeAndDecrypt(stub, ent, "", "")
if err != nil {
return shim.Error(fmt.Sprintf("getStateByRangeAndDecrypt failed, err %+v", err))
}
return shim.Success(bytes)
}
// Invoke for this chaincode exposes functions to ENCRYPT, DECRYPT transactional
// data. It also supports an example to ENCRYPT and SIGN and DECRYPT and
// VERIFY. The Initialization Vector (IV) can be passed in as a parm to
// ensure peers have deterministic data.
func (t *EncCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// get arguments and transient
f, args := stub.GetFunctionAndParameters()
tMap, err := stub.GetTransient()
if err != nil {
return shim.Error(fmt.Sprintf("Could not retrieve transient, err %s", err))
}
switch f {
case "ENCRYPT":
// make sure there's a key in transient - the assumption is that
// it's associated to the string "ENCKEY"
if _, in := tMap[ENCKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient encryption key %s", ENCKEY))
}
return t.Encrypter(stub, args[0:], tMap[ENCKEY], tMap[IV])
case "DECRYPT":
// make sure there's a key in transient - the assumption is that
// it's associated to the string "DECKEY"
if _, in := tMap[DECKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient decryption key %s", DECKEY))
}
return t.Decrypter(stub, args[0:], tMap[DECKEY], tMap[IV])
case "ENCRYPTSIGN":
// make sure keys are there in the transient map - the assumption is that they
// are associated to the string "ENCKEY" and "SIGKEY"
if _, in := tMap[ENCKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient key %s", ENCKEY))
} else if _, in := tMap[SIGKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient key %s", SIGKEY))
}
return t.EncrypterSigner(stub, args[0:], tMap[ENCKEY], tMap[SIGKEY])
case "DECRYPTVERIFY":
// make sure keys are there in the transient map - the assumption is that they
// are associated to the string "DECKEY" and "VERKEY"
if _, in := tMap[DECKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient key %s", DECKEY))
} else if _, in := tMap[VERKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient key %s", VERKEY))
}
return t.DecrypterVerify(stub, args[0:], tMap[DECKEY], tMap[VERKEY])
case "RANGEQUERY":
// make sure there's a key in transient - the assumption is that
// it's associated to the string "ENCKEY"
if _, in := tMap[DECKEY]; !in {
return shim.Error(fmt.Sprintf("Expected transient key %s", DECKEY))
}
return t.RangeDecrypter(stub, tMap[DECKEY])
default:
return shim.Error(fmt.Sprintf("Unsupported function %s", f))
}
}
func main() {
factory.InitFactories(nil)
err := shim.Start(&EncCC{factory.GetDefault()})
if err != nil {
fmt.Printf("Error starting EncCC chaincode: %s", err)
}
}

View File

@ -0,0 +1,234 @@
package main
import (
"bytes"
"encoding/json"
"testing"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/stretchr/testify/assert"
)
const (
AESKEY1 = "01234567890123456789012345678901"
AESKEY2 = "01234567890123456789012345678902"
ECDSAKEY1 = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIH4Uv66F9kZMdOQxwNegkGm8c3AB3nGPOtxNKi6wb/ZooAoGCCqGSM49
AwEHoUQDQgAEEPE+VLOh+e4NpwIjI/b/fKYHi4weU7r9OTEYPiAJiJBQY6TZnvF5
oRMvwO4MCYxFtpIRO4UxIgcZBj4NCBxKqQ==
-----END EC PRIVATE KEY-----`
ECDSAKEY2 = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIE8Seyc9TXx+yQfnGPuzjkuEfMbkq203IYdfyvMd0r3OoAoGCCqGSM49
AwEHoUQDQgAE4dcGMMroH2LagI/s5i/Bx4t4ggGDoJPNVkKBDBlIaMYjJFYD1obk
JOWqAZxKKsBxBC5Ssu+fS26VPfdNWxDsFQ==
-----END EC PRIVATE KEY-----`
IV1 = "0123456789012345"
)
func TestInit(t *testing.T) {
factory.InitFactories(nil)
scc := new(EncCC)
stub := shim.NewMockStub("enccc", scc)
stub.MockTransactionStart("a")
res := scc.Init(stub)
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
}
// unfortunately we can't tese this cc though invoke since the
// mock shim doesn't support transient. We test failure scenarios
// and the tests below focus on the functionality by invoking
// functions as opposed to cc
func TestInvoke(t *testing.T) {
factory.InitFactories(nil)
scc := &EncCC{factory.GetDefault()}
stub := shim.NewMockStub("enccc", scc)
res := stub.MockInvoke("tx", [][]byte{[]byte("barf")})
assert.NotEqual(t, res.Status, int32(shim.OK))
res = stub.MockInvoke("tx", [][]byte{[]byte("ENC")})
assert.NotEqual(t, res.Status, int32(shim.OK))
res = stub.MockInvoke("tx", [][]byte{[]byte("SIG")})
assert.NotEqual(t, res.Status, int32(shim.OK))
res = stub.MockInvoke("tx", [][]byte{[]byte("RANGE")})
assert.NotEqual(t, res.Status, int32(shim.OK))
}
func TestEnc(t *testing.T) {
factory.InitFactories(nil)
scc := &EncCC{factory.GetDefault()}
stub := shim.NewMockStub("enccc", scc)
// success
stub.MockTransactionStart("a")
res := scc.Encrypter(stub, []string{"key", "value"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
// fail - bad key
stub.MockTransactionStart("a")
res = scc.Encrypter(stub, []string{"key", "value"}, []byte("badkey"), nil)
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - not enough args
stub.MockTransactionStart("a")
res = scc.Encrypter(stub, []string{"key"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// success
stub.MockTransactionStart("a")
res = scc.Decrypter(stub, []string{"key"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
assert.True(t, bytes.Equal(res.Payload, []byte("value")))
// fail - not enough args
stub.MockTransactionStart("a")
res = scc.Decrypter(stub, []string{}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - bad kvs key
stub.MockTransactionStart("a")
res = scc.Decrypter(stub, []string{"badkey"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - bad key
stub.MockTransactionStart("a")
res = scc.Decrypter(stub, []string{"key"}, []byte(AESKEY2), nil)
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
}
func TestSig(t *testing.T) {
factory.InitFactories(nil)
scc := &EncCC{factory.GetDefault()}
stub := shim.NewMockStub("enccc", scc)
// success
stub.MockTransactionStart("a")
res := scc.EncrypterSigner(stub, []string{"key", "value"}, []byte(AESKEY1), []byte(ECDSAKEY1))
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
// fail - bad key
stub.MockTransactionStart("a")
res = scc.EncrypterSigner(stub, []string{"key", "value"}, []byte(AESKEY1), []byte("barf"))
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - bad args
stub.MockTransactionStart("a")
res = scc.EncrypterSigner(stub, []string{"key"}, []byte(AESKEY1), []byte("barf"))
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - bad signing key
stub.MockTransactionStart("a")
res = scc.DecrypterVerify(stub, []string{"key"}, []byte(AESKEY1), []byte(ECDSAKEY2))
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - bad args
stub.MockTransactionStart("a")
res = scc.DecrypterVerify(stub, []string{}, []byte(AESKEY1), []byte(ECDSAKEY1))
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// fail - bad kvs key
stub.MockTransactionStart("a")
res = scc.DecrypterVerify(stub, []string{"badkey"}, []byte(AESKEY1), []byte(ECDSAKEY1))
stub.MockTransactionEnd("a")
assert.NotEqual(t, res.Status, int32(shim.OK))
// success
stub.MockTransactionStart("a")
res = scc.EncrypterSigner(stub, []string{"key", "value"}, []byte(AESKEY1), []byte(ECDSAKEY1))
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
// success
stub.MockTransactionStart("a")
res = scc.DecrypterVerify(stub, []string{"key"}, []byte(AESKEY1), []byte(ECDSAKEY1))
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
assert.True(t, bytes.Equal(res.Payload, []byte("value")))
}
func TestEncCC_RangeDecrypter(t *testing.T) {
factory.InitFactories(nil)
scc := &EncCC{factory.GetDefault()}
stub := shim.NewMockStub("enccc", scc)
stub.MockTransactionStart("a")
res := scc.Encrypter(stub, []string{"key1", "value1"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
stub.MockTransactionStart("a")
res = scc.Encrypter(stub, []string{"key2", "value2"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
stub.MockTransactionStart("a")
res = scc.Encrypter(stub, []string{"key3", "value3"}, []byte(AESKEY1), nil)
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
// failed range query
res = scc.RangeDecrypter(stub, nil)
assert.NotEqual(t, res.Status, int32(shim.OK))
// success range query
stub.MockTransactionStart("a")
res = scc.RangeDecrypter(stub, []byte(AESKEY1))
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
keys := []keyValuePair{}
err := json.Unmarshal(res.Payload, &keys)
assert.NoError(t, err)
assert.Equal(t, keys[0].Key, "key1")
assert.Equal(t, string(keys[0].Value), "value1")
assert.Equal(t, keys[1].Key, "key2")
assert.Equal(t, string(keys[1].Value), "value2")
assert.Equal(t, keys[2].Key, "key3")
assert.Equal(t, string(keys[2].Value), "value3")
_, err = getStateByRangeAndDecrypt(stub, nil, string([]byte{0}), string([]byte{0}))
assert.Error(t, err)
}
func TestDeterministicEncryption(t *testing.T) {
factory.InitFactories(nil)
scc := &EncCC{factory.GetDefault()}
stub := shim.NewMockStub("enccc", scc)
stub.MockTransactionStart("a")
res := scc.Encrypter(stub, []string{"key1", "value1"}, []byte(AESKEY1), []byte(IV1))
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
c1, err := stub.GetState("key1")
assert.NoError(t, err)
assert.NotNil(t, c1)
stub.MockTransactionStart("a")
res = scc.Encrypter(stub, []string{"key1", "value1"}, []byte(AESKEY1), []byte(IV1))
stub.MockTransactionEnd("a")
assert.Equal(t, res.Status, int32(shim.OK))
c2, err := stub.GetState("key1")
assert.NoError(t, err)
assert.NotNil(t, c1)
assert.True(t, bytes.Equal(c1, c2))
}

View File

@ -0,0 +1,147 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"encoding/json"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/chaincode/shim/ext/entities"
"github.com/pkg/errors"
)
// the functions below show some best practices on how
// to use entities to perform cryptographic operations
// over the ledger state
// getStateAndDecrypt retrieves the value associated to key,
// decrypts it with the supplied entity and returns the result
// of the decryption
func getStateAndDecrypt(stub shim.ChaincodeStubInterface, ent entities.Encrypter, key string) ([]byte, error) {
// at first we retrieve the ciphertext from the ledger
ciphertext, err := stub.GetState(key)
if err != nil {
return nil, err
}
// GetState will return a nil slice if the key does not exist.
// Note that the chaincode logic may want to distinguish between
// nil slice (key doesn't exist in state db) and empty slice
// (key found in state db but value is empty). We do not
// distinguish the case here
if len(ciphertext) == 0 {
return nil, errors.New("no ciphertext to decrypt")
}
return ent.Decrypt(ciphertext)
}
// encryptAndPutState encrypts the supplied value using the
// supplied entity and puts it to the ledger associated to
// the supplied KVS key
func encryptAndPutState(stub shim.ChaincodeStubInterface, ent entities.Encrypter, key string, value []byte) error {
// at first we use the supplied entity to encrypt the value
ciphertext, err := ent.Encrypt(value)
if err != nil {
return err
}
return stub.PutState(key, ciphertext)
}
// getStateDecryptAndVerify retrieves the value associated to key,
// decrypts it with the supplied entity, verifies the signature
// over it and returns the result of the decryption in case of
// success
func getStateDecryptAndVerify(stub shim.ChaincodeStubInterface, ent entities.EncrypterSignerEntity, key string) ([]byte, error) {
// here we retrieve and decrypt the state associated to key
val, err := getStateAndDecrypt(stub, ent, key)
if err != nil {
return nil, err
}
// we unmarshal a SignedMessage from the decrypted state
msg := &entities.SignedMessage{}
err = msg.FromBytes(val)
if err != nil {
return nil, err
}
// we verify the signature
ok, err := msg.Verify(ent)
if err != nil {
return nil, err
} else if !ok {
return nil, errors.New("invalid signature")
}
return msg.Payload, nil
}
// signEncryptAndPutState signs the supplied value, encrypts
// the supplied value together with its signature using the
// supplied entity and puts it to the ledger associated to
// the supplied KVS key
func signEncryptAndPutState(stub shim.ChaincodeStubInterface, ent entities.EncrypterSignerEntity, key string, value []byte) error {
// here we create a SignedMessage, set its payload
// to value and the ID of the entity and
// sign it with the entity
msg := &entities.SignedMessage{Payload: value, ID: []byte(ent.ID())}
err := msg.Sign(ent)
if err != nil {
return err
}
// here we serialize the SignedMessage
b, err := msg.ToBytes()
if err != nil {
return err
}
// here we encrypt the serialized version associated to args[0]
return encryptAndPutState(stub, ent, key, b)
}
type keyValuePair struct {
Key string `json:"key"`
Value string `json:"value"`
}
// getStateByRangeAndDecrypt retrieves a range of KVS pairs from the
// ledger and decrypts each value with the supplied entity; it returns
// a json-marshalled slice of keyValuePair
func getStateByRangeAndDecrypt(stub shim.ChaincodeStubInterface, ent entities.Encrypter, startKey, endKey string) ([]byte, error) {
// we call get state by range to go through the entire range
iterator, err := stub.GetStateByRange(startKey, endKey)
if err != nil {
return nil, err
}
defer iterator.Close()
// we decrypt each entry - the assumption is that they have all been encrypted with the same key
keyvalueset := []keyValuePair{}
for iterator.HasNext() {
el, err := iterator.Next()
if err != nil {
return nil, err
}
v, err := ent.Decrypt(el.Value)
if err != nil {
return nil, err
}
keyvalueset = append(keyvalueset, keyValuePair{el.Key, string(v)})
}
bytes, err := json.Marshal(keyvalueset)
if err != nil {
return nil, err
}
return bytes, nil
}

View File

@ -0,0 +1,92 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// EventSender example simple Chaincode implementation
type EventSender struct {
}
// Init function
func (t *EventSender) Init(stub shim.ChaincodeStubInterface) pb.Response {
err := stub.PutState("noevents", []byte("0"))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Invoke function
func (t *EventSender) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
b, err := stub.GetState("noevents")
if err != nil {
return shim.Error("Failed to get state")
}
noevts, _ := strconv.Atoi(string(b))
tosend := "Event " + string(b)
for _, s := range args {
tosend = tosend + "," + s
}
err = stub.PutState("noevents", []byte(strconv.Itoa(noevts+1)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.SetEvent("evtsender", []byte(tosend))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Query function
func (t *EventSender) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
b, err := stub.GetState("noevents")
if err != nil {
return shim.Error("Failed to get state")
}
jsonResp := "{\"NoEvents\":\"" + string(b) + "\"}"
return shim.Success([]byte(jsonResp))
}
func (t *EventSender) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
return t.invoke(stub, args)
} else if function == "query" {
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"query\"")
}
func main() {
err := shim.Start(new(EventSender))
if err != nil {
fmt.Printf("Error starting EventSender chaincode: %s", err)
}
}

View File

@ -0,0 +1,133 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
// Init method of chaincode
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
_, args := stub.GetFunctionAndParameters()
var A, B string // Entities
var Aval, Bval int // Asset holdings
var err error
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte("OK"))
}
// Invoke transaction makes payment of X units from A to B
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
_, args := stub.GetFunctionAndParameters()
var A, B string // Entities
var Aval, Bval int // Asset holdings
var X int // Transaction value
var err error
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}
A = args[0]
B = args[1]
// Get the state from the ledger
// TODO: will be nice to have a GetAllState call to ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
return shim.Error("Failed to get state")
}
if Avalbytes == nil {
return shim.Error("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes))
Bvalbytes, err := stub.GetState(B)
if err != nil {
return shim.Error("Failed to get state")
}
if Bvalbytes == nil {
return shim.Error("Entity not found")
}
Bval, _ = strconv.Atoi(string(Bvalbytes))
// Perform the execution
X, err = strconv.Atoi(args[2])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
Aval = Aval - X
Bval = Bval + X
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state back to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte(fmt.Sprintf("{%d,%d}", Aval, Bval)))
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

View File

@ -0,0 +1,97 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"testing"
"github.com/hyperledger/fabric/core/chaincode/shim"
)
func checkInit(t *testing.T, stub *shim.MockStub, args [][]byte, retval []byte) {
res := stub.MockInit("1", args)
if res.Status != shim.OK {
fmt.Println("Init failed", string(res.Message))
t.FailNow()
}
if retval != nil {
if res.Payload == nil {
fmt.Printf("Init returned nil, expected %s", string(retval))
t.FailNow()
}
if string(res.Payload) != string(retval) {
fmt.Printf("Init returned %s, expected %s", string(res.Payload), string(retval))
t.FailNow()
}
}
}
func checkState(t *testing.T, stub *shim.MockStub, name string, value string) {
bytes := stub.State[name]
if bytes == nil {
fmt.Println("State", name, "failed to get value")
t.FailNow()
}
if string(bytes) != value {
fmt.Println("State value", name, "was not", value, "as expected")
t.FailNow()
}
}
func checkInvoke(t *testing.T, stub *shim.MockStub, args [][]byte, retval []byte) {
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
fmt.Println("Invoke", args, "failed", string(res.Message))
t.FailNow()
}
if retval != nil {
if res.Payload == nil {
fmt.Printf("Invoke returned nil, expected %s", string(retval))
t.FailNow()
}
if string(res.Payload) != string(retval) {
fmt.Printf("Invoke returned %s, expected %s", string(res.Payload), string(retval))
t.FailNow()
}
}
}
func Test_Init(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex02", scc)
// Init A=123 B=234
checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("123"), []byte("B"), []byte("234")}, []byte("OK"))
checkState(t, stub, "A", "123")
checkState(t, stub, "B", "234")
}
func Test_Invoke(t *testing.T) {
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex02", scc)
// Init A=567 B=678
checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("567"), []byte("B"), []byte("678")}, []byte("OK"))
// Invoke A->B for 123
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("123")}, []byte("{444,801}"))
// Invoke B->A for 234
checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte("B"), []byte("A"), []byte("234")}, []byte("{567,678}"))
}

View File

@ -0,0 +1,200 @@
// +build !experimental
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"encoding/json"
"fmt"
"strconv"
"time"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// This chaincode implements a simple map that is stored in the state.
// The following operations are available.
// Invoke operations
// put - requires two arguments, a key and value
// remove - requires a key
// get - requires one argument, a key, and returns a value
// keys - requires no arguments, returns all keys
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
// Init is a no-op
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
// Invoke has two functions
// put - takes two arguments, a key and value, and stores them in the state
// remove - takes one argument, a key, and removes if from the state
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
switch function {
case "put":
if len(args) < 2 {
return shim.Error("put operation must include two arguments: [key, value]")
}
key := args[0]
value := args[1]
if err := stub.PutState(key, []byte(value)); err != nil {
fmt.Printf("Error putting state %s", err)
return shim.Error(fmt.Sprintf("put operation failed. Error updating state: %s", err))
}
indexName := "compositeKeyTest"
compositeKeyTestIndex, err := stub.CreateCompositeKey(indexName, []string{key})
if err != nil {
return shim.Error(err.Error())
}
valueByte := []byte{0x00}
if err := stub.PutState(compositeKeyTestIndex, valueByte); err != nil {
fmt.Printf("Error putting state with compositeKey %s", err)
return shim.Error(fmt.Sprintf("put operation failed. Error updating state with compositeKey: %s", err))
}
return shim.Success(nil)
case "remove":
if len(args) < 1 {
return shim.Error("remove operation must include one argument: [key]")
}
key := args[0]
err := stub.DelState(key)
if err != nil {
return shim.Error(fmt.Sprintf("remove operation failed. Error updating state: %s", err))
}
return shim.Success(nil)
case "get":
if len(args) < 1 {
return shim.Error("get operation must include one argument, a key")
}
key := args[0]
value, err := stub.GetState(key)
if err != nil {
return shim.Error(fmt.Sprintf("get operation failed. Error accessing state: %s", err))
}
jsonVal, err := json.Marshal(string(value))
return shim.Success(jsonVal)
case "keys":
if len(args) < 2 {
return shim.Error("put operation must include two arguments, a key and value")
}
startKey := args[0]
endKey := args[1]
//sleep needed to test peer's timeout behavior when using iterators
stime := 0
if len(args) > 2 {
stime, _ = strconv.Atoi(args[2])
}
keysIter, err := stub.GetStateByRange(startKey, endKey)
if err != nil {
return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
//if sleeptime is specied, take a nap
if stime > 0 {
time.Sleep(time.Duration(stime) * time.Millisecond)
}
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.Key)
}
for key, value := range keys {
fmt.Printf("key %d contains %s\n", key, value)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("keys operation failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
case "query":
query := args[0]
keysIter, err := stub.GetQueryResult(query)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.Key)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
case "history":
key := args[0]
keysIter, err := stub.GetHistoryForKey(key)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.TxId)
}
for key, txID := range keys {
fmt.Printf("key %d contains %s\n", key, txID)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
default:
return shim.Success([]byte("Unsupported operation"))
}
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting chaincode: %s", err)
}
}

View File

@ -0,0 +1,311 @@
// +build experimental
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"encoding/json"
"fmt"
"strconv"
"time"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// This chaincode implements a simple map that is stored in the state.
// The following operations are available.
// Invoke operations
// put - requires two arguments, a key and value
// remove - requires a key
// get - requires one argument, a key, and returns a value
// keys - requires no arguments, returns all keys
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
// Init is a no-op
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
// Invoke has two functions
// put - takes two arguments, a key and value, and stores them in the state
// remove - takes one argument, a key, and removes if from the state
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
switch function {
case "putPrivate":
if len(args) < 3 {
return shim.Error("put operation on private data must include three arguments: [collection, key, value]")
}
collection := args[0]
key := args[1]
value := args[2]
if err := stub.PutPrivateData(collection, key, []byte(value)); err != nil {
fmt.Printf("Error putting private data%s", err)
return shim.Error(fmt.Sprintf("put operation failed. Error updating state: %s", err))
}
return shim.Success(nil)
case "removePrivate":
if len(args) < 2 {
return shim.Error("remove operation on private data must include two arguments: [collection, key]")
}
collection := args[0]
key := args[1]
err := stub.DelPrivateData(collection, key)
if err != nil {
return shim.Error(fmt.Sprintf("remove operation on private data failed. Error updating state: %s", err))
}
return shim.Success(nil)
case "getPrivate":
if len(args) < 2 {
return shim.Error("get operation on private data must include two arguments: [collection, key]")
}
collection := args[0]
key := args[1]
value, err := stub.GetPrivateData(collection, key)
if err != nil {
return shim.Error(fmt.Sprintf("get operation on private data failed. Error accessing state: %s", err))
}
jsonVal, err := json.Marshal(string(value))
return shim.Success(jsonVal)
case "keysPrivate":
if len(args) < 3 {
return shim.Error("range query operation on private data must include three arguments, a collection, key and value")
}
collection := args[0]
startKey := args[1]
endKey := args[2]
//sleep needed to test peer's timeout behavior when using iterators
stime := 0
if len(args) > 3 {
stime, _ = strconv.Atoi(args[3])
}
keysIter, err := stub.GetPrivateDataByRange(collection, startKey, endKey)
if err != nil {
return shim.Error(fmt.Sprintf("keys operation failed on private data. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
//if sleeptime is specied, take a nap
if stime > 0 {
time.Sleep(time.Duration(stime) * time.Millisecond)
}
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("keys operation on private data failed. Error accessing state: %s", err))
}
keys = append(keys, response.Key)
}
for key, value := range keys {
fmt.Printf("key %d contains %s\n", key, value)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("keys operation on private data failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
case "queryPrivate":
collection := args[0]
query := args[1]
keysIter, err := stub.GetPrivateDataQueryResult(collection, query)
if err != nil {
return shim.Error(fmt.Sprintf("query operation on private data failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("query operation on private data failed. Error accessing state: %s", err))
}
keys = append(keys, response.Key)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("query operation on private data failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
case "put":
if len(args) < 2 {
return shim.Error("put operation must include two arguments: [key, value]")
}
key := args[0]
value := args[1]
if err := stub.PutState(key, []byte(value)); err != nil {
fmt.Printf("Error putting state %s", err)
return shim.Error(fmt.Sprintf("put operation failed. Error updating state: %s", err))
}
indexName := "compositeKeyTest"
compositeKeyTestIndex, err := stub.CreateCompositeKey(indexName, []string{key})
if err != nil {
return shim.Error(err.Error())
}
valueByte := []byte{0x00}
if err := stub.PutState(compositeKeyTestIndex, valueByte); err != nil {
fmt.Printf("Error putting state with compositeKey %s", err)
return shim.Error(fmt.Sprintf("put operation failed. Error updating state with compositeKey: %s", err))
}
return shim.Success(nil)
case "remove":
if len(args) < 1 {
return shim.Error("remove operation must include one argument: [key]")
}
key := args[0]
err := stub.DelState(key)
if err != nil {
return shim.Error(fmt.Sprintf("remove operation failed. Error updating state: %s", err))
}
return shim.Success(nil)
case "get":
if len(args) < 1 {
return shim.Error("get operation must include one argument, a key")
}
key := args[0]
value, err := stub.GetState(key)
if err != nil {
return shim.Error(fmt.Sprintf("get operation failed. Error accessing state: %s", err))
}
jsonVal, err := json.Marshal(string(value))
return shim.Success(jsonVal)
case "keys":
if len(args) < 2 {
return shim.Error("put operation must include two arguments, a key and value")
}
startKey := args[0]
endKey := args[1]
//sleep needed to test peer's timeout behavior when using iterators
stime := 0
if len(args) > 2 {
stime, _ = strconv.Atoi(args[2])
}
keysIter, err := stub.GetStateByRange(startKey, endKey)
if err != nil {
return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
//if sleeptime is specied, take a nap
if stime > 0 {
time.Sleep(time.Duration(stime) * time.Millisecond)
}
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.Key)
}
for key, value := range keys {
fmt.Printf("key %d contains %s\n", key, value)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("keys operation failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
case "query":
query := args[0]
keysIter, err := stub.GetQueryResult(query)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.Key)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
case "history":
key := args[0]
keysIter, err := stub.GetHistoryForKey(key)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
defer keysIter.Close()
var keys []string
for keysIter.HasNext() {
response, iterErr := keysIter.Next()
if iterErr != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.TxId)
}
for key, txID := range keys {
fmt.Printf("key %d contains %s\n", key, txID)
}
jsonKeys, err := json.Marshal(keys)
if err != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err))
}
return shim.Success(jsonKeys)
default:
return shim.Success([]byte("Unsupported operation"))
}
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting chaincode: %s", err)
}
}

View File

@ -0,0 +1,627 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
// ====CHAINCODE EXECUTION SAMPLES (CLI) ==================
// ==== Invoke marbles ====
// peer chaincode invoke -C myc1 -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
// peer chaincode invoke -C myc1 -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
// peer chaincode invoke -C myc1 -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
// peer chaincode invoke -C myc1 -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
// peer chaincode invoke -C myc1 -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
// peer chaincode invoke -C myc1 -n marbles -c '{"Args":["delete","marble1"]}'
// ==== Query marbles ====
// peer chaincode query -C myc1 -n marbles -c '{"Args":["readMarble","marble1"]}'
// peer chaincode query -C myc1 -n marbles -c '{"Args":["getMarblesByRange","marble1","marble3"]}'
// peer chaincode query -C myc1 -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'
// Rich Query (Only supported if CouchDB is used as state database):
// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesByOwner","tom"]}'
// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}'
//The following examples demonstrate creating indexes on CouchDB
//Example hostname:port configurations
//
//Docker or vagrant environments:
// http://couchdb:5984/
//
//Inside couchdb docker container
// http://127.0.0.1:5984/
// Index for chaincodeid, docType, owner.
// Note that docType and owner fields must be prefixed with the "data" wrapper
// chaincodeid must be added for all queries
//
// Definition for use with Fauxton interface
// {"index":{"fields":["chaincodeid","data.docType","data.owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}
//
// example curl definition for use with command line
// curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[\"chaincodeid\",\"data.docType\",\"data.owner\"]},\"name\":\"indexOwner\",\"ddoc\":\"indexOwnerDoc\",\"type\":\"json\"}" http://hostname:port/myc1/_index
//
// Index for chaincodeid, docType, owner, size (descending order).
// Note that docType, owner and size fields must be prefixed with the "data" wrapper
// chaincodeid must be added for all queries
//
// Definition for use with Fauxton interface
// {"index":{"fields":[{"data.size":"desc"},{"chaincodeid":"desc"},{"data.docType":"desc"},{"data.owner":"desc"}]},"ddoc":"indexSizeSortDoc", "name":"indexSizeSortDesc","type":"json"}
//
// example curl definition for use with command line
// curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[{\"data.size\":\"desc\"},{\"chaincodeid\":\"desc\"},{\"data.docType\":\"desc\"},{\"data.owner\":\"desc\"}]},\"ddoc\":\"indexSizeSortDoc\", \"name\":\"indexSizeSortDesc\",\"type\":\"json\"}" http://hostname:port/myc1/_index
// Rich Query with index design doc and index name specified (Only supported if CouchDB is used as state database):
// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}'
// Rich Query with index design doc specified only (Only supported if CouchDB is used as state database):
// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"docType\":{\"$eq\":\"marble\"},\"owner\":{\"$eq\":\"tom\"},\"size\":{\"$gt\":0}},\"fields\":[\"docType\",\"owner\",\"size\"],\"sort\":[{\"size\":\"desc\"}],\"use_index\":\"_design/indexSizeSortDoc\"}"]}'
package main
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
type marble struct {
ObjectType string `json:"docType"` //docType is used to distinguish the various types of objects in state database
Name string `json:"name"` //the fieldtags are needed to keep case from bouncing around
Color string `json:"color"`
Size int `json:"size"`
Owner string `json:"owner"`
}
// ===================================================================================
// Main
// ===================================================================================
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
// Init initializes chaincode
// ===========================
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
// Invoke - Our entry point for Invocations
// ========================================
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
fmt.Println("invoke is running " + function)
// Handle different functions
if function == "initMarble" { //create a new marble
return t.initMarble(stub, args)
} else if function == "transferMarble" { //change owner of a specific marble
return t.transferMarble(stub, args)
} else if function == "transferMarblesBasedOnColor" { //transfer all marbles of a certain color
return t.transferMarblesBasedOnColor(stub, args)
} else if function == "delete" { //delete a marble
return t.delete(stub, args)
} else if function == "readMarble" { //read a marble
return t.readMarble(stub, args)
} else if function == "queryMarblesByOwner" { //find marbles for owner X using rich query
return t.queryMarblesByOwner(stub, args)
} else if function == "queryMarbles" { //find marbles based on an ad hoc rich query
return t.queryMarbles(stub, args)
} else if function == "getHistoryForMarble" { //get history of values for a marble
return t.getHistoryForMarble(stub, args)
} else if function == "getMarblesByRange" { //get marbles based on range query
return t.getMarblesByRange(stub, args)
}
fmt.Println("invoke did not find func: " + function) //error
return shim.Error("Received unknown function invocation")
}
// ============================================================
// initMarble - create a new marble, store into chaincode state
// ============================================================
func (t *SimpleChaincode) initMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// 0 1 2 3
// "asdf", "blue", "35", "bob"
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// ==== Input sanitation ====
fmt.Println("- start init marble")
if len(args[0]) <= 0 {
return shim.Error("1st argument must be a non-empty string")
}
if len(args[1]) <= 0 {
return shim.Error("2nd argument must be a non-empty string")
}
if len(args[2]) <= 0 {
return shim.Error("3rd argument must be a non-empty string")
}
if len(args[3]) <= 0 {
return shim.Error("4th argument must be a non-empty string")
}
marbleName := args[0]
color := strings.ToLower(args[1])
owner := strings.ToLower(args[3])
size, err := strconv.Atoi(args[2])
if err != nil {
return shim.Error("3rd argument must be a numeric string")
}
// ==== Check if marble already exists ====
marbleAsBytes, err := stub.GetState(marbleName)
if err != nil {
return shim.Error("Failed to get marble: " + err.Error())
} else if marbleAsBytes != nil {
fmt.Println("This marble already exists: " + marbleName)
return shim.Error("This marble already exists: " + marbleName)
}
// ==== Create marble object and marshal to JSON ====
objectType := "marble"
marble := &marble{objectType, marbleName, color, size, owner}
marbleJSONasBytes, err := json.Marshal(marble)
if err != nil {
return shim.Error(err.Error())
}
//Alternatively, build the marble json string manually if you don't want to use struct marshalling
//marbleJSONasString := `{"docType":"Marble", "name": "` + marbleName + `", "color": "` + color + `", "size": ` + strconv.Itoa(size) + `, "owner": "` + owner + `"}`
//marbleJSONasBytes := []byte(str)
// === Save marble to state ===
err = stub.PutState(marbleName, marbleJSONasBytes)
if err != nil {
return shim.Error(err.Error())
}
// ==== Index the marble to enable color-based range queries, e.g. return all blue marbles ====
// An 'index' is a normal key/value entry in state.
// The key is a composite key, with the elements that you want to range query on listed first.
// In our case, the composite key is based on indexName~color~name.
// This will enable very efficient state range queries based on composite keys matching indexName~color~*
indexName := "color~name"
colorNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{marble.Color, marble.Name})
if err != nil {
return shim.Error(err.Error())
}
// Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the marble.
// Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value
value := []byte{0x00}
stub.PutState(colorNameIndexKey, value)
// ==== Marble saved and indexed. Return success ====
fmt.Println("- end init marble")
return shim.Success(nil)
}
// ===============================================
// readMarble - read a marble from chaincode state
// ===============================================
func (t *SimpleChaincode) readMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var name, jsonResp string
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
}
name = args[0]
valAsbytes, err := stub.GetState(name) //get the marble from chaincode state
if err != nil {
jsonResp = "{\"Error\":\"Failed to get state for " + name + "\"}"
return shim.Error(jsonResp)
} else if valAsbytes == nil {
jsonResp = "{\"Error\":\"Marble does not exist: " + name + "\"}"
return shim.Error(jsonResp)
}
return shim.Success(valAsbytes)
}
// ==================================================
// delete - remove a marble key/value pair from state
// ==================================================
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var jsonResp string
var marbleJSON marble
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
marbleName := args[0]
// to maintain the color~name index, we need to read the marble first and get its color
valAsbytes, err := stub.GetState(marbleName) //get the marble from chaincode state
if err != nil {
jsonResp = "{\"Error\":\"Failed to get state for " + marbleName + "\"}"
return shim.Error(jsonResp)
} else if valAsbytes == nil {
jsonResp = "{\"Error\":\"Marble does not exist: " + marbleName + "\"}"
return shim.Error(jsonResp)
}
err = json.Unmarshal([]byte(valAsbytes), &marbleJSON)
if err != nil {
jsonResp = "{\"Error\":\"Failed to decode JSON of: " + marbleName + "\"}"
return shim.Error(jsonResp)
}
err = stub.DelState(marbleName) //remove the marble from chaincode state
if err != nil {
return shim.Error("Failed to delete state:" + err.Error())
}
// maintain the index
indexName := "color~name"
colorNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{marbleJSON.Color, marbleJSON.Name})
if err != nil {
return shim.Error(err.Error())
}
// Delete index entry to state.
err = stub.DelState(colorNameIndexKey)
if err != nil {
return shim.Error("Failed to delete state:" + err.Error())
}
return shim.Success(nil)
}
// ===========================================================
// transfer a marble by setting a new owner name on the marble
// ===========================================================
func (t *SimpleChaincode) transferMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0 1
// "name", "bob"
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
marbleName := args[0]
newOwner := strings.ToLower(args[1])
fmt.Println("- start transferMarble ", marbleName, newOwner)
marbleAsBytes, err := stub.GetState(marbleName)
if err != nil {
return shim.Error("Failed to get marble:" + err.Error())
} else if marbleAsBytes == nil {
return shim.Error("Marble does not exist")
}
marbleToTransfer := marble{}
err = json.Unmarshal(marbleAsBytes, &marbleToTransfer) //unmarshal it aka JSON.parse()
if err != nil {
return shim.Error(err.Error())
}
marbleToTransfer.Owner = newOwner //change the owner
marbleJSONasBytes, _ := json.Marshal(marbleToTransfer)
err = stub.PutState(marbleName, marbleJSONasBytes) //rewrite the marble
if err != nil {
return shim.Error(err.Error())
}
fmt.Println("- end transferMarble (success)")
return shim.Success(nil)
}
// ===========================================================================================
// getMarblesByRange performs a range query based on the start and end keys provided.
// Read-only function results are not typically submitted to ordering. If the read-only
// results are submitted to ordering, or if the query is used in an update transaction
// and submitted to ordering, then the committing peers will re-execute to guarantee that
// result sets are stable between endorsement time and commit time. The transaction is
// invalidated by the committing peers if the result set has changed between endorsement
// time and commit time.
// Therefore, range queries are a safe option for performing update transactions based on query results.
// ===========================================================================================
func (t *SimpleChaincode) getMarblesByRange(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
startKey := args[0]
endKey := args[1]
resultsIterator, err := stub.GetStateByRange(startKey, endKey)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
// buffer is a JSON array containing QueryResults
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"Key\":")
buffer.WriteString("\"")
buffer.WriteString(queryResponse.Key)
buffer.WriteString("\"")
buffer.WriteString(", \"Record\":")
// Record is a JSON object, so we write as-is
buffer.WriteString(string(queryResponse.Value))
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("- getMarblesByRange queryResult:\n%s\n", buffer.String())
return shim.Success(buffer.Bytes())
}
// ==== Example: GetStateByPartialCompositeKey/RangeQuery =========================================
// transferMarblesBasedOnColor will transfer marbles of a given color to a certain new owner.
// Uses a GetStateByPartialCompositeKey (range query) against color~name 'index'.
// Committing peers will re-execute range queries to guarantee that result sets are stable
// between endorsement time and commit time. The transaction is invalidated by the
// committing peers if the result set has changed between endorsement time and commit time.
// Therefore, range queries are a safe option for performing update transactions based on query results.
// ===========================================================================================
func (t *SimpleChaincode) transferMarblesBasedOnColor(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0 1
// "color", "bob"
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
color := args[0]
newOwner := strings.ToLower(args[1])
fmt.Println("- start transferMarblesBasedOnColor ", color, newOwner)
// Query the color~name index by color
// This will execute a key range query on all keys starting with 'color'
coloredMarbleResultsIterator, err := stub.GetStateByPartialCompositeKey("color~name", []string{color})
if err != nil {
return shim.Error(err.Error())
}
defer coloredMarbleResultsIterator.Close()
// Iterate through result set and for each marble found, transfer to newOwner
var i int
for i = 0; coloredMarbleResultsIterator.HasNext(); i++ {
// Note that we don't get the value (2nd return variable), we'll just get the marble name from the composite key
responseRange, err := coloredMarbleResultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// get the color and name from color~name composite key
objectType, compositeKeyParts, err := stub.SplitCompositeKey(responseRange.Key)
if err != nil {
return shim.Error(err.Error())
}
returnedColor := compositeKeyParts[0]
returnedMarbleName := compositeKeyParts[1]
fmt.Printf("- found a marble from index:%s color:%s name:%s\n", objectType, returnedColor, returnedMarbleName)
// Now call the transfer function for the found marble.
// Re-use the same function that is used to transfer individual marbles
response := t.transferMarble(stub, []string{returnedMarbleName, newOwner})
// if the transfer failed break out of loop and return error
if response.Status != shim.OK {
return shim.Error("Transfer failed: " + response.Message)
}
}
responsePayload := fmt.Sprintf("Transferred %d %s marbles to %s", i, color, newOwner)
fmt.Println("- end transferMarblesBasedOnColor: " + responsePayload)
return shim.Success([]byte(responsePayload))
}
// =======Rich queries =========================================================================
// Two examples of rich queries are provided below (parameterized query and ad hoc query).
// Rich queries pass a query string to the state database.
// Rich queries are only supported by state database implementations
// that support rich query (e.g. CouchDB).
// The query string is in the syntax of the underlying state database.
// With rich queries there is no guarantee that the result set hasn't changed between
// endorsement time and commit time, aka 'phantom reads'.
// Therefore, rich queries should not be used in update transactions, unless the
// application handles the possibility of result set changes between endorsement and commit time.
// Rich queries can be used for point-in-time queries against a peer.
// ============================================================================================
// ===== Example: Parameterized rich query =================================================
// queryMarblesByOwner queries for marbles based on a passed in owner.
// This is an example of a parameterized query where the query logic is baked into the chaincode,
// and accepting a single query parameter (owner).
// Only available on state databases that support rich query (e.g. CouchDB)
// =========================================================================================
func (t *SimpleChaincode) queryMarblesByOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0
// "bob"
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
owner := strings.ToLower(args[0])
queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"marble\",\"owner\":\"%s\"}}", owner)
queryResults, err := getQueryResultForQueryString(stub, queryString)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(queryResults)
}
// ===== Example: Ad hoc rich query ========================================================
// queryMarbles uses a query string to perform a query for marbles.
// Query string matching state database syntax is passed in and executed as is.
// Supports ad hoc queries that can be defined at runtime by the client.
// If this is not desired, follow the queryMarblesForOwner example for parameterized queries.
// Only available on state databases that support rich query (e.g. CouchDB)
// =========================================================================================
func (t *SimpleChaincode) queryMarbles(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0
// "queryString"
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
queryString := args[0]
queryResults, err := getQueryResultForQueryString(stub, queryString)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(queryResults)
}
// =========================================================================================
// getQueryResultForQueryString executes the passed in query string.
// Result set is built and returned as a byte array containing the JSON results.
// =========================================================================================
func getQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) {
fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString)
resultsIterator, err := stub.GetQueryResult(queryString)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
// buffer is a JSON array containing QueryRecords
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return nil, err
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"Key\":")
buffer.WriteString("\"")
buffer.WriteString(queryResponse.Key)
buffer.WriteString("\"")
buffer.WriteString(", \"Record\":")
// Record is a JSON object, so we write as-is
buffer.WriteString(string(queryResponse.Value))
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String())
return buffer.Bytes(), nil
}
func (t *SimpleChaincode) getHistoryForMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
marbleName := args[0]
fmt.Printf("- start getHistoryForMarble: %s\n", marbleName)
resultsIterator, err := stub.GetHistoryForKey(marbleName)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
// buffer is a JSON array containing historic values for the marble
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
response, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"TxId\":")
buffer.WriteString("\"")
buffer.WriteString(response.TxId)
buffer.WriteString("\"")
buffer.WriteString(", \"Value\":")
// if it was a delete operation on given key, then we need to set the
//corresponding value null. Else, we will write the response.Value
//as-is (as the Value itself a JSON marble)
if response.IsDelete {
buffer.WriteString("null")
} else {
buffer.WriteString(string(response.Value))
}
buffer.WriteString(", \"Timestamp\":")
buffer.WriteString("\"")
buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())
buffer.WriteString("\"")
buffer.WriteString(", \"IsDelete\":")
buffer.WriteString("\"")
buffer.WriteString(strconv.FormatBool(response.IsDelete))
buffer.WriteString("\"")
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("- getHistoryForMarble returning:\n%s\n", buffer.String())
return shim.Success(buffer.Bytes())
}

View File

@ -0,0 +1,72 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strings"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// PassthruChaincode passes thru invoke and query to another chaincode where
// called ChaincodeID = function
// called chaincode's function = args[0]
// called chaincode's args = args[1:]
type PassthruChaincode struct {
}
func toChaincodeArgs(args ...string) [][]byte {
bargs := make([][]byte, len(args))
for i, arg := range args {
bargs[i] = []byte(arg)
}
return bargs
}
//Init func will return error if function has string "error" anywhere
func (p *PassthruChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
function, _ := stub.GetFunctionAndParameters()
if strings.Index(function, "error") >= 0 {
return shim.Error(function)
}
return shim.Success([]byte(function))
}
//helper
func (p *PassthruChaincode) iq(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {
if function == "" {
return shim.Error("Chaincode ID not provided")
}
chaincodeID := function
return stub.InvokeChaincode(chaincodeID, toChaincodeArgs(args...), "")
}
// Invoke passes through the invoke call
func (p *PassthruChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
return p.iq(stub, function, args)
}
func main() {
err := shim.Start(new(PassthruChaincode))
if err != nil {
fmt.Printf("Error starting Passthru chaincode: %s", err)
}
}

View File

@ -0,0 +1,124 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
// Sleeper chaincode sleeps and works with one state variable
// Init - 1 param, a sleep time in millisecs
// Invoke - 4 or 3 params, "put" or "get", value to set and sleep time in millisecs
//
// Sleeper can be used to test the "chaincode.executetimeout" property
import (
"fmt"
"strconv"
"time"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SleeperChaincode example simple Chaincode implementation
type SleeperChaincode struct {
}
func (t *SleeperChaincode) sleep(sleepTime string) {
st, _ := strconv.Atoi(sleepTime)
if st >= 0 {
time.Sleep(time.Duration(st) * time.Millisecond)
}
}
// Init initializes chaincode...all it does is sleep a bi
func (t *SleeperChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
args := stub.GetStringArgs()
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
sleepTime := args[0]
t.sleep(sleepTime)
return shim.Success(nil)
}
// Invoke sets key/value and sleeps a bit
func (t *SleeperChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "put" {
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}
// Make payment of X units from A to B
return t.invoke(stub, args)
} else if function == "get" {
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
// the old "Query" is now implemtned in invoke
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"put\" or \"get\"")
}
// Transaction makes payment of X units from A to B
func (t *SleeperChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// set state
key := args[0]
val := args[1]
err := stub.PutState(key, []byte(val))
if err != nil {
return shim.Error(err.Error())
}
sleepTime := args[2]
//sleep for a bit
t.sleep(sleepTime)
return shim.Success([]byte("OK"))
}
// query callback representing the query of a chaincode
func (t *SleeperChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
key := args[0]
// Get the state from the ledger
val, err := stub.GetState(key)
if err != nil {
return shim.Error(err.Error())
}
sleepTime := args[1]
//sleep for a bit
t.sleep(sleepTime)
return shim.Success(val)
}
func main() {
err := shim.Start(new(SleeperChaincode))
if err != nil {
fmt.Printf("Error starting Sleeper chaincode: %s", err)
}
}

View File

@ -0,0 +1,40 @@
# FIXME: someone from the UTXO team will need to verify or rework this
# Copyright London Stock Exchange Group All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
FROM ubuntu:latest
RUN apt-get update && apt-get install pkg-config autoconf libtool -y
RUN cd /tmp && git clone https://github.com/bitcoin/secp256k1.git && cd secp256k1/
WORKDIR /tmp/secp256k1
RUN ./autogen.sh
RUN ./configure --enable-module-recovery
RUN make
RUN ./tests
RUN make install
WORKDIR /tmp
RUN apt-get install libtool libboost1.55-all-dev -y
RUN git clone https://github.com/libbitcoin/libbitcoin-consensus.git
WORKDIR /tmp/libbitcoin-consensus
RUN ./autogen.sh
RUN ./configure
RUN make
RUN make install
# Now SWIG
WORKDIR /tmp
# Need pcre lib for building
RUN apt-get install libpcre3-dev -y
RUN wget http://prdownloads.sourceforge.net/swig/swig-3.0.8.tar.gz && tar xvf swig-3.0.8.tar.gz
WORKDIR /tmp/swig-3.0.8
RUN ./autogen.sh
RUN ./configure
RUN make
RUN make install
# Now add this for SWIG execution requirement to get missing stubs-32.h header file
RUN apt-get install g++-multilib -y
ENV CGO_LDFLAGS="-L/usr/local/lib/ -lbitcoin-consensus -lstdc++"

View File

@ -0,0 +1,79 @@
### UTXO Chaincode
The UTXO example chaincode contains a single invocation function named `execute`. This function accepts BASE64 encoded transactions from the Bitcoin network. This chaincode will parse the transactions and pass the transaction components to the Bitcoin libconsensus C library for script verification.
The purpose of this chaincode is to
1. Demonstrate how the world state can be used to store and process unspent transaction outputs (UTXO).
2. Demonstrate how to include and use a C library from within a chaincode.
A client for exercising this chaincode is avilable at https://github.com/srderson/hyperledger-fabric-utxo-client-java.
The following are instructions for building and deploying the UTXO chaincode in Hypereledger Fabric. All commands should be run with vagrant.
First, build the Docker image for the UTXO chaincode.
```
cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go/utxo/
docker build -t utxo:0.1.0 .
```
Next, modify the `core.yaml` file in the Hyperledger Fabric project to point to the local Docker image that was built in the previous step. In the core.yaml file find `chaincode.golang.Dockerfile` and change it from from `hyperledger/fabric-baseimage` to `utxo:0.1.0`
Start the peer using the following commands
```
peer node start
```
In a second window, deploy the example UTXO chaincode
```
CORE_PEER_ADDRESS=localhost:7051 peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/utxo -c '{"Function":"init", "Args": []}'
```
Wait about 30 seconds for the chaincode to be deployed. Output from the window where the peer is running will indicate that this is successful.
Next, find the `image ID` for the deployed chaincode. Run
```
docker images
```
and look for the image ID of the most recently deployed chaincode. The image ID will likely be similar to
```
dev-jdoe-cbe6be7ed67931b9be2ce31dd833e523702378bef91b29917005f0eaa316b57e268e19696093d48b91076f1134cbf4b06afd78e6afd947133f43cb51bf40b0a4
```
Make a note of this as we'll be using it later.
Stop the running peer.
Build a peer docker image by running the following test. This will allow for easy testing of the chaincode by giving us the ability to reset the database to a clean state.
```
go test github.com/hyperledger/fabric/core/container -run=BuildImage_Peer
```
Using the Docker image that we just built, start a peer within a container in `chaincodedev` mode.
```
docker run -it -p 7051:7051 -p 7053:7053 hyperledger/fabric-peer peer node start --peer-chaincodedev
```
In another window, start UTXO chaincode in a container. The <image ID> refers to the UTXO image ID noted in a prior step.
```
docker run -it <image ID> /bin/bash
```
Build the UTXO chaincode.
```
cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go/utxo/
go build
CORE_PEER_ADDRESS=172.17.0.2:7051 CORE_CHAINCODE_ID_NAME=utxo ./utxo
```
In another window, deploy the chaincode
```
peer chaincode deploy -n utxo -c '{"Function":"init", "Args": []}'
```
The chaincode is now deployed and ready to accept transactions.
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
s

View File

@ -0,0 +1,104 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"encoding/base64"
"errors"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/examples/chaincode/go/utxo/util"
)
// The UTXO example chaincode contains a single invocation function named execute. This function accepts BASE64
// encoded transactions from the Bitcoin network. This chaincode will parse the transactions and pass the transaction
// components to the Bitcoin libconsensus C library for script verification. A table of UTXOs is maintained to ensure
// each transaction is valid.
// Documentation can be found at
// https://github.com/hyperledger/fabric/blob/master/examples/chaincode/go/utxo/README.md
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
// Init does nothing in the UTXO chaincode
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return nil, nil
}
// Invoke callback representing the invocation of a chaincode
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
switch function {
case "execute":
if len(args) < 1 {
return nil, errors.New("execute operation must include single argument, the base64 encoded form of a bitcoin transaction")
}
txDataBase64 := args[0]
txData, err := base64.StdEncoding.DecodeString(txDataBase64)
if err != nil {
return nil, fmt.Errorf("Error decoding TX as base64: %s", err)
}
utxo := util.MakeUTXO(MakeChaincodeStore(stub))
execResult, err := utxo.Execute(txData)
if err != nil {
return nil, fmt.Errorf("Error executing TX: %s", err)
}
fmt.Printf("\nExecResult: Coinbase: %t, SumInputs %d, SumOutputs %d\n\n", execResult.IsCoinbase, execResult.SumPriorOutputs, execResult.SumCurrentOutputs)
if execResult.IsCoinbase == false {
if execResult.SumCurrentOutputs > execResult.SumPriorOutputs {
return nil, fmt.Errorf("sumOfCurrentOutputs > sumOfPriorOutputs: sumOfCurrentOutputs = %d, sumOfPriorOutputs = %d", execResult.SumCurrentOutputs, execResult.SumPriorOutputs)
}
}
return nil, nil
case "getTran":
if len(args) < 1 {
return nil, errors.New("queryBTC operation must include single argument, the TX hash hex")
}
utxo := util.MakeUTXO(MakeChaincodeStore(stub))
tx, err := utxo.Query(args[0])
if err != nil {
return nil, fmt.Errorf("Error querying for transaction: %s", err)
}
if tx == nil {
var data []byte
return data, nil
}
return tx, nil
default:
return nil, errors.New("Unsupported operation")
}
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting chaincode: %s", err)
}
}

View File

@ -0,0 +1,482 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 3.0.8
*
* This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
* changes to this file unless you know what you are doing--modify the SWIG
* interface file instead.
* ----------------------------------------------------------------------------- */
// source: consensus.swg
package consensus
/*
#define intgo swig_intgo
typedef void *swig_voidp;
#include <stdint.h>
typedef int intgo;
typedef unsigned int uintgo;
typedef struct { char *p; intgo n; } _gostring_;
typedef struct { void* array; intgo len; intgo cap; } _goslice_;
typedef long long swig_type_1;
typedef long long swig_type_2;
extern void _wrap_Swig_free_consensus_0731991c73947514(uintptr_t arg1);
extern swig_intgo _wrap_verify_result_eval_false_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_eval_true_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_script_size_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_push_size_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_op_count_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_stack_size_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_sig_count_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_pubkey_count_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_verify_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_equalverify_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_checkmultisigverify_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_checksigverify_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_numequalverify_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_bad_opcode_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_disabled_opcode_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_invalid_stack_operation_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_invalid_altstack_operation_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_unbalanced_conditional_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_sig_hashtype_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_sig_der_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_minimaldata_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_sig_pushonly_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_sig_high_s_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_sig_nulldummy_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_pubkeytype_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_cleanstack_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_discourage_upgradable_nops_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_op_return_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_unknown_error_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_tx_invalid_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_tx_size_invalid_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_tx_input_invalid_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_negative_locktime_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_result_unsatisfied_locktime_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_none_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_p2sh_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_strictenc_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_dersig_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_low_s_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_nulldummy_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_sigpushonly_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_minimaldata_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_discourage_upgradable_nops_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_cleanstack_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_flags_checklocktimeverify_consensus_0731991c73947514(void);
extern swig_intgo _wrap_verify_script_consensus_0731991c73947514(swig_voidp arg1, swig_type_1 arg2, swig_voidp arg3, swig_type_2 arg4, swig_intgo arg5, swig_intgo arg6);
#undef intgo
*/
import "C"
import "unsafe"
import _ "runtime/cgo"
import "sync"
type _ unsafe.Pointer
var Swig_escape_always_false bool
var Swig_escape_val interface{}
type _swig_fnptr *byte
type _swig_memberptr *byte
type _ sync.Mutex
func Swig_free(arg1 uintptr) {
_swig_i_0 := arg1
C._wrap_Swig_free_consensus_0731991c73947514(C.uintptr_t(_swig_i_0))
}
const LIBBITCOIN_CONSENSUS_VERSION string = "2.0.0"
const LIBBITCOIN_CONSENSUS_MAJOR_VERSION int = 2
const LIBBITCOIN_CONSENSUS_MINOR_VERSION int = 0
const LIBBITCOIN_CONSENSUS_PATCH_VERSION int = 0
type LibbitcoinConsensusVerify_result_type int
func _swig_getverify_result_eval_false() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_eval_false_consensus_0731991c73947514())
return swig_r
}
var Verify_result_eval_false LibbitcoinConsensusVerify_result_type = _swig_getverify_result_eval_false()
func _swig_getverify_result_eval_true() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_eval_true_consensus_0731991c73947514())
return swig_r
}
var Verify_result_eval_true LibbitcoinConsensusVerify_result_type = _swig_getverify_result_eval_true()
func _swig_getverify_result_script_size() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_script_size_consensus_0731991c73947514())
return swig_r
}
var Verify_result_script_size LibbitcoinConsensusVerify_result_type = _swig_getverify_result_script_size()
func _swig_getverify_result_push_size() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_push_size_consensus_0731991c73947514())
return swig_r
}
var Verify_result_push_size LibbitcoinConsensusVerify_result_type = _swig_getverify_result_push_size()
func _swig_getverify_result_op_count() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_op_count_consensus_0731991c73947514())
return swig_r
}
var Verify_result_op_count LibbitcoinConsensusVerify_result_type = _swig_getverify_result_op_count()
func _swig_getverify_result_stack_size() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_stack_size_consensus_0731991c73947514())
return swig_r
}
var Verify_result_stack_size LibbitcoinConsensusVerify_result_type = _swig_getverify_result_stack_size()
func _swig_getverify_result_sig_count() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_sig_count_consensus_0731991c73947514())
return swig_r
}
var Verify_result_sig_count LibbitcoinConsensusVerify_result_type = _swig_getverify_result_sig_count()
func _swig_getverify_result_pubkey_count() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_pubkey_count_consensus_0731991c73947514())
return swig_r
}
var Verify_result_pubkey_count LibbitcoinConsensusVerify_result_type = _swig_getverify_result_pubkey_count()
func _swig_getverify_result_verify() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_verify_consensus_0731991c73947514())
return swig_r
}
var Verify_result_verify LibbitcoinConsensusVerify_result_type = _swig_getverify_result_verify()
func _swig_getverify_result_equalverify() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_equalverify_consensus_0731991c73947514())
return swig_r
}
var Verify_result_equalverify LibbitcoinConsensusVerify_result_type = _swig_getverify_result_equalverify()
func _swig_getverify_result_checkmultisigverify() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_checkmultisigverify_consensus_0731991c73947514())
return swig_r
}
var Verify_result_checkmultisigverify LibbitcoinConsensusVerify_result_type = _swig_getverify_result_checkmultisigverify()
func _swig_getverify_result_checksigverify() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_checksigverify_consensus_0731991c73947514())
return swig_r
}
var Verify_result_checksigverify LibbitcoinConsensusVerify_result_type = _swig_getverify_result_checksigverify()
func _swig_getverify_result_numequalverify() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_numequalverify_consensus_0731991c73947514())
return swig_r
}
var Verify_result_numequalverify LibbitcoinConsensusVerify_result_type = _swig_getverify_result_numequalverify()
func _swig_getverify_result_bad_opcode() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_bad_opcode_consensus_0731991c73947514())
return swig_r
}
var Verify_result_bad_opcode LibbitcoinConsensusVerify_result_type = _swig_getverify_result_bad_opcode()
func _swig_getverify_result_disabled_opcode() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_disabled_opcode_consensus_0731991c73947514())
return swig_r
}
var Verify_result_disabled_opcode LibbitcoinConsensusVerify_result_type = _swig_getverify_result_disabled_opcode()
func _swig_getverify_result_invalid_stack_operation() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_invalid_stack_operation_consensus_0731991c73947514())
return swig_r
}
var Verify_result_invalid_stack_operation LibbitcoinConsensusVerify_result_type = _swig_getverify_result_invalid_stack_operation()
func _swig_getverify_result_invalid_altstack_operation() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_invalid_altstack_operation_consensus_0731991c73947514())
return swig_r
}
var Verify_result_invalid_altstack_operation LibbitcoinConsensusVerify_result_type = _swig_getverify_result_invalid_altstack_operation()
func _swig_getverify_result_unbalanced_conditional() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_unbalanced_conditional_consensus_0731991c73947514())
return swig_r
}
var Verify_result_unbalanced_conditional LibbitcoinConsensusVerify_result_type = _swig_getverify_result_unbalanced_conditional()
func _swig_getverify_result_sig_hashtype() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_sig_hashtype_consensus_0731991c73947514())
return swig_r
}
var Verify_result_sig_hashtype LibbitcoinConsensusVerify_result_type = _swig_getverify_result_sig_hashtype()
func _swig_getverify_result_sig_der() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_sig_der_consensus_0731991c73947514())
return swig_r
}
var Verify_result_sig_der LibbitcoinConsensusVerify_result_type = _swig_getverify_result_sig_der()
func _swig_getverify_result_minimaldata() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_minimaldata_consensus_0731991c73947514())
return swig_r
}
var Verify_result_minimaldata LibbitcoinConsensusVerify_result_type = _swig_getverify_result_minimaldata()
func _swig_getverify_result_sig_pushonly() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_sig_pushonly_consensus_0731991c73947514())
return swig_r
}
var Verify_result_sig_pushonly LibbitcoinConsensusVerify_result_type = _swig_getverify_result_sig_pushonly()
func _swig_getverify_result_sig_high_s() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_sig_high_s_consensus_0731991c73947514())
return swig_r
}
var Verify_result_sig_high_s LibbitcoinConsensusVerify_result_type = _swig_getverify_result_sig_high_s()
func _swig_getverify_result_sig_nulldummy() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_sig_nulldummy_consensus_0731991c73947514())
return swig_r
}
var Verify_result_sig_nulldummy LibbitcoinConsensusVerify_result_type = _swig_getverify_result_sig_nulldummy()
func _swig_getverify_result_pubkeytype() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_pubkeytype_consensus_0731991c73947514())
return swig_r
}
var Verify_result_pubkeytype LibbitcoinConsensusVerify_result_type = _swig_getverify_result_pubkeytype()
func _swig_getverify_result_cleanstack() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_cleanstack_consensus_0731991c73947514())
return swig_r
}
var Verify_result_cleanstack LibbitcoinConsensusVerify_result_type = _swig_getverify_result_cleanstack()
func _swig_getverify_result_discourage_upgradable_nops() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_discourage_upgradable_nops_consensus_0731991c73947514())
return swig_r
}
var Verify_result_discourage_upgradable_nops LibbitcoinConsensusVerify_result_type = _swig_getverify_result_discourage_upgradable_nops()
func _swig_getverify_result_op_return() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_op_return_consensus_0731991c73947514())
return swig_r
}
var Verify_result_op_return LibbitcoinConsensusVerify_result_type = _swig_getverify_result_op_return()
func _swig_getverify_result_unknown_error() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_unknown_error_consensus_0731991c73947514())
return swig_r
}
var Verify_result_unknown_error LibbitcoinConsensusVerify_result_type = _swig_getverify_result_unknown_error()
func _swig_getverify_result_tx_invalid() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_tx_invalid_consensus_0731991c73947514())
return swig_r
}
var Verify_result_tx_invalid LibbitcoinConsensusVerify_result_type = _swig_getverify_result_tx_invalid()
func _swig_getverify_result_tx_size_invalid() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_tx_size_invalid_consensus_0731991c73947514())
return swig_r
}
var Verify_result_tx_size_invalid LibbitcoinConsensusVerify_result_type = _swig_getverify_result_tx_size_invalid()
func _swig_getverify_result_tx_input_invalid() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_tx_input_invalid_consensus_0731991c73947514())
return swig_r
}
var Verify_result_tx_input_invalid LibbitcoinConsensusVerify_result_type = _swig_getverify_result_tx_input_invalid()
func _swig_getverify_result_negative_locktime() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_negative_locktime_consensus_0731991c73947514())
return swig_r
}
var Verify_result_negative_locktime LibbitcoinConsensusVerify_result_type = _swig_getverify_result_negative_locktime()
func _swig_getverify_result_unsatisfied_locktime() (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_result_unsatisfied_locktime_consensus_0731991c73947514())
return swig_r
}
var Verify_result_unsatisfied_locktime LibbitcoinConsensusVerify_result_type = _swig_getverify_result_unsatisfied_locktime()
type LibbitcoinConsensusVerify_flags_type int
func _swig_getverify_flags_none() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_none_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_none LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_none()
func _swig_getverify_flags_p2sh() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_p2sh_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_p2sh LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_p2sh()
func _swig_getverify_flags_strictenc() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_strictenc_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_strictenc LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_strictenc()
func _swig_getverify_flags_dersig() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_dersig_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_dersig LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_dersig()
func _swig_getverify_flags_low_s() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_low_s_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_low_s LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_low_s()
func _swig_getverify_flags_nulldummy() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_nulldummy_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_nulldummy LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_nulldummy()
func _swig_getverify_flags_sigpushonly() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_sigpushonly_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_sigpushonly LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_sigpushonly()
func _swig_getverify_flags_minimaldata() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_minimaldata_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_minimaldata LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_minimaldata()
func _swig_getverify_flags_discourage_upgradable_nops() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_discourage_upgradable_nops_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_discourage_upgradable_nops LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_discourage_upgradable_nops()
func _swig_getverify_flags_cleanstack() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_cleanstack_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_cleanstack LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_cleanstack()
func _swig_getverify_flags_checklocktimeverify() (_swig_ret LibbitcoinConsensusVerify_flags_type) {
var swig_r LibbitcoinConsensusVerify_flags_type
swig_r = (LibbitcoinConsensusVerify_flags_type)(C._wrap_verify_flags_checklocktimeverify_consensus_0731991c73947514())
return swig_r
}
var Verify_flags_checklocktimeverify LibbitcoinConsensusVerify_flags_type = _swig_getverify_flags_checklocktimeverify()
func Verify_script(arg1 *byte, arg2 int64, arg3 *byte, arg4 int64, arg5 uint, arg6 uint) (_swig_ret LibbitcoinConsensusVerify_result_type) {
var swig_r LibbitcoinConsensusVerify_result_type
_swig_i_0 := arg1
_swig_i_1 := arg2
_swig_i_2 := arg3
_swig_i_3 := arg4
_swig_i_4 := arg5
_swig_i_5 := arg6
swig_r = (LibbitcoinConsensusVerify_result_type)(C._wrap_verify_script_consensus_0731991c73947514(C.swig_voidp(_swig_i_0), C.swig_type_1(_swig_i_1), C.swig_voidp(_swig_i_2), C.swig_type_2(_swig_i_3), C.swig_intgo(_swig_i_4), C.swig_intgo(_swig_i_5)))
return swig_r
}

View File

@ -0,0 +1,812 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 3.0.8
*
* This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
* changes to this file unless you know what you are doing--modify the SWIG
* interface file instead.
* ----------------------------------------------------------------------------- */
// source: consensus.swg
#define SWIGMODULE consensus
#ifdef __cplusplus
/* SwigValueWrapper is described in swig.swg */
template<typename T> class SwigValueWrapper {
struct SwigMovePointer {
T *ptr;
SwigMovePointer(T *p) : ptr(p) { }
~SwigMovePointer() { delete ptr; }
SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
} pointer;
SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
SwigValueWrapper(const SwigValueWrapper<T>& rhs);
public:
SwigValueWrapper() : pointer(0) { }
SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
operator T&() const { return *pointer.ptr; }
T *operator&() { return pointer.ptr; }
};
template <typename T> T SwigValueInit() {
return T();
}
#endif
/* -----------------------------------------------------------------------------
* This section contains generic SWIG labels for method/variable
* declarations/attributes, and other compiler dependent labels.
* ----------------------------------------------------------------------------- */
/* template workaround for compilers that cannot correctly implement the C++ standard */
#ifndef SWIGTEMPLATEDISAMBIGUATOR
# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
# define SWIGTEMPLATEDISAMBIGUATOR template
# elif defined(__HP_aCC)
/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
# define SWIGTEMPLATEDISAMBIGUATOR template
# else
# define SWIGTEMPLATEDISAMBIGUATOR
# endif
#endif
/* inline attribute */
#ifndef SWIGINLINE
# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
# define SWIGINLINE inline
# else
# define SWIGINLINE
# endif
#endif
/* attribute recognised by some compilers to avoid 'unused' warnings */
#ifndef SWIGUNUSED
# if defined(__GNUC__)
# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
# define SWIGUNUSED __attribute__ ((__unused__))
# else
# define SWIGUNUSED
# endif
# elif defined(__ICC)
# define SWIGUNUSED __attribute__ ((__unused__))
# else
# define SWIGUNUSED
# endif
#endif
#ifndef SWIG_MSC_UNSUPPRESS_4505
# if defined(_MSC_VER)
# pragma warning(disable : 4505) /* unreferenced local function has been removed */
# endif
#endif
#ifndef SWIGUNUSEDPARM
# ifdef __cplusplus
# define SWIGUNUSEDPARM(p)
# else
# define SWIGUNUSEDPARM(p) p SWIGUNUSED
# endif
#endif
/* internal SWIG method */
#ifndef SWIGINTERN
# define SWIGINTERN static SWIGUNUSED
#endif
/* internal inline SWIG method */
#ifndef SWIGINTERNINLINE
# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
#endif
/* exporting methods */
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
# ifndef GCC_HASCLASSVISIBILITY
# define GCC_HASCLASSVISIBILITY
# endif
#endif
#ifndef SWIGEXPORT
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# if defined(STATIC_LINKED)
# define SWIGEXPORT
# else
# define SWIGEXPORT __declspec(dllexport)
# endif
# else
# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
# define SWIGEXPORT __attribute__ ((visibility("default")))
# else
# define SWIGEXPORT
# endif
# endif
#endif
/* calling conventions for Windows */
#ifndef SWIGSTDCALL
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# define SWIGSTDCALL __stdcall
# else
# define SWIGSTDCALL
# endif
#endif
/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
# define _CRT_SECURE_NO_DEPRECATE
#endif
/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
# define _SCL_SECURE_NO_DEPRECATE
#endif
/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
#endif
/* Intel's compiler complains if a variable which was never initialised is
* cast to void, which is a common idiom which we use to indicate that we
* are aware a variable isn't used. So we just silence that warning.
* See: https://github.com/swig/swig/issues/192 for more discussion.
*/
#ifdef __INTEL_COMPILER
# pragma warning disable 592
#endif
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
typedef int intgo;
typedef unsigned int uintgo;
typedef struct { char *p; intgo n; } _gostring_;
typedef struct { void* array; intgo len; intgo cap; } _goslice_;
#define swiggo_size_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
#define swiggo_size_assert(t, n) swiggo_size_assert_eq(sizeof(t), n, swiggo_sizeof_##t##_is_not_##n)
swiggo_size_assert(char, 1)
swiggo_size_assert(short, 2)
swiggo_size_assert(int, 4)
typedef long long swiggo_long_long;
swiggo_size_assert(swiggo_long_long, 8)
swiggo_size_assert(float, 4)
swiggo_size_assert(double, 8)
#ifdef __cplusplus
extern "C" {
#endif
extern void crosscall2(void (*fn)(void *, int), void *, int);
extern char* _cgo_topofstack(void) __attribute__ ((weak));
extern void _cgo_allocate(void *, int);
extern void _cgo_panic(void *, int);
#ifdef __cplusplus
}
#endif
static char *_swig_topofstack() {
if (_cgo_topofstack) {
return _cgo_topofstack();
} else {
return 0;
}
}
static void _swig_gopanic(const char *p) {
struct {
const char *p;
} a;
a.p = p;
crosscall2(_cgo_panic, &a, (int) sizeof a);
}
#define SWIG_contract_assert(expr, msg) \
if (!(expr)) { _swig_gopanic(msg); } else
static void Swig_free(void* p) {
free(p);
}
#include <bitcoin/consensus.hpp>
#ifdef __cplusplus
extern "C" {
#endif
void _wrap_Swig_free_consensus_0731991c73947514(void *_swig_go_0) {
void *arg1 = (void *) 0 ;
arg1 = *(void **)&_swig_go_0;
Swig_free(arg1);
}
intgo _wrap_verify_result_eval_false_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_eval_false;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_eval_true_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_eval_true;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_script_size_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_script_size;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_push_size_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_push_size;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_op_count_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_op_count;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_stack_size_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_stack_size;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_sig_count_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_sig_count;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_pubkey_count_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_pubkey_count;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_verify_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_verify;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_equalverify_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_equalverify;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_checkmultisigverify_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_checkmultisigverify;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_checksigverify_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_checksigverify;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_numequalverify_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_numequalverify;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_bad_opcode_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_bad_opcode;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_disabled_opcode_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_disabled_opcode;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_invalid_stack_operation_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_invalid_stack_operation;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_invalid_altstack_operation_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_invalid_altstack_operation;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_unbalanced_conditional_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_unbalanced_conditional;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_sig_hashtype_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_sig_hashtype;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_sig_der_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_sig_der;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_minimaldata_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_minimaldata;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_sig_pushonly_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_sig_pushonly;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_sig_high_s_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_sig_high_s;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_sig_nulldummy_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_sig_nulldummy;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_pubkeytype_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_pubkeytype;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_cleanstack_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_cleanstack;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_discourage_upgradable_nops_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_discourage_upgradable_nops;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_op_return_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_op_return;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_unknown_error_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_unknown_error;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_tx_invalid_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_tx_invalid;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_tx_size_invalid_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_tx_size_invalid;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_tx_input_invalid_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_tx_input_invalid;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_negative_locktime_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_negative_locktime;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_result_unsatisfied_locktime_consensus_0731991c73947514() {
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_result_unsatisfied_locktime;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_none_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_none;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_p2sh_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_p2sh;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_strictenc_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_strictenc;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_dersig_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_dersig;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_low_s_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_low_s;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_nulldummy_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_nulldummy;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_sigpushonly_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_sigpushonly;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_minimaldata_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_minimaldata;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_discourage_upgradable_nops_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_discourage_upgradable_nops;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_cleanstack_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_cleanstack;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_flags_checklocktimeverify_consensus_0731991c73947514() {
libbitcoin::consensus::verify_flags_type result;
intgo _swig_go_result;
result = libbitcoin::consensus::verify_flags_checklocktimeverify;
_swig_go_result = (intgo)result;
return _swig_go_result;
}
intgo _wrap_verify_script_consensus_0731991c73947514(char *_swig_go_0, long long _swig_go_1, char *_swig_go_2, long long _swig_go_3, intgo _swig_go_4, intgo _swig_go_5) {
unsigned char *arg1 = (unsigned char *) 0 ;
size_t arg2 ;
unsigned char *arg3 = (unsigned char *) 0 ;
size_t arg4 ;
unsigned int arg5 ;
unsigned int arg6 ;
libbitcoin::consensus::verify_result_type result;
intgo _swig_go_result;
arg1 = *(unsigned char **)&_swig_go_0;
arg2 = (size_t)_swig_go_1;
arg3 = *(unsigned char **)&_swig_go_2;
arg4 = (size_t)_swig_go_3;
arg5 = (unsigned int)_swig_go_4;
arg6 = (unsigned int)_swig_go_5;
result = (libbitcoin::consensus::verify_result_type)libbitcoin::consensus::verify_script((unsigned char const *)arg1,arg2,(unsigned char const *)arg3,arg4,arg5,arg6);
_swig_go_result = (intgo)result;
return _swig_go_result;
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,91 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/examples/chaincode/go/utxo/util"
)
// Store struct uses a chaincode stub for state access
type Store struct {
stub shim.ChaincodeStubInterface
}
// MakeChaincodeStore returns a store for storing keys in the state
func MakeChaincodeStore(stub shim.ChaincodeStubInterface) util.Store {
store := &Store{}
store.stub = stub
return store
}
func keyToString(key *util.Key) string {
return key.TxHashAsHex + ":" + string(key.TxIndex)
}
// GetState returns the transaction for a given key
func (s *Store) GetState(key util.Key) (*util.TX_TXOUT, bool, error) {
keyToFetch := keyToString(&key)
data, err := s.stub.GetState(keyToFetch)
if err != nil {
return nil, false, fmt.Errorf("Error getting state from stub: %s", err)
}
if data == nil {
return nil, false, nil
}
// Value found, unmarshal
var value = &util.TX_TXOUT{}
err = proto.Unmarshal(data, value)
if err != nil {
return nil, false, fmt.Errorf("Error unmarshalling value: %s", err)
}
return value, true, nil
}
// DelState deletes the transaction for the given key
func (s *Store) DelState(key util.Key) error {
return s.stub.DelState(keyToString(&key))
}
// PutState stores the given transaction and key
func (s *Store) PutState(key util.Key, value *util.TX_TXOUT) error {
data, err := proto.Marshal(value)
if err != nil {
return fmt.Errorf("Error marshalling value to bytes: %s", err)
}
return s.stub.PutState(keyToString(&key), data)
}
// GetTran returns a transaction for the given hash
func (s *Store) GetTran(key string) ([]byte, bool, error) {
data, err := s.stub.GetState(key)
if err != nil {
return nil, false, fmt.Errorf("Error getting state from stub: %s", err)
}
if data == nil {
return nil, false, nil
}
return data, true, nil
}
// PutTran adds a transaction to the state with the hash as a key
func (s *Store) PutTran(key string, value []byte) error {
return s.stub.PutState(key, value)
}

View File

@ -0,0 +1,908 @@
Block: 0
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////9NBP//AB0BBEVUaGUgVGltZXMgMDMvSmFuLzIwMDkgQ2hhbmNlbGxvciBvbiBicmluayBvZiBzZWNvbmQgYmFpbG91dCBmb3IgYmFua3P/////AQDyBSoBAAAAQ0EEZ4r9sP5VSCcZZ/GmcTC3EFzWqCjgOQmmeWLg6h9h3rZJ9rw/TO84xPNVBOUewRLeXDhN97oLjVeKTHAra/EdX6wAAAAA
Block: 1
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCDnSU0BfwYvUDJTSC//////AQDyBSoBAAAAIyECGury+GOKEpoxVvvn5e9jUiawuv1JX/A6/iyEPX46S1GsAAAAAA==
Block: 2
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDLnSU0BDgYvUDJTSC//////AQDyBSoBAAAAIyEDin9u8cjKDFiKpT+oYBKAd8nmwR5oMPTX7k52Ola3cY+sAAAAAA==
Block: 3
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIbnSU0BUQYvUDJTSC//////AQDyBSoBAAAAIyED9tn/TBKVlEXKVUnIEWg7+ciOY3siLdLgMRFUxMhc9COsAAAAAA==
Block: 4
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKrnSU0BHQYvUDJTSC//////AQDyBSoBAAAAIyECH3LeHP8Xd6lYTzGtxFgEGBTDvDnGYkGsTUMTbXEGrr6sAAAAAA==
Block: 5
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBjoSU0BagYvUDJTSC//////AQDyBSoBAAAAIyEDc+pzmn503u60Qxptd99BlywYXm6D4cMA65ExCWM5g+esAAAAAA==
Block: 6
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDHoSU0BFgYvUDJTSC//////AQDyBSoBAAAAIyEDoO+Q7VYFbhJuvloUwRLwuciQyU/ytKvp5xSIo6qUABasAAAAAA==
Block: 7
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIHoSU0BUAYvUDJTSC//////AQDyBSoBAAAAIyEChbxHksK4djxvfgi4VoytTM664Bd6zgo+7E8+TQRHFE+sAAAAAA==
Block: 8
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKDoSU0BGQYvUDJTSC//////AQDyBSoBAAAAIyECMETlaS4M62G/iAGKu5m89dAGPi8IKk5Fh5oWQHKNtbysAAAAAA==
Block: 9
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBP3oSU0BWwYvUDJTSC//////AQDyBSoBAAAAIyEDnBGEA/SSj8H0oPqm/ML/5R5FShONBOGCB2tmehT/dUasAAAAAA==
Block: 10
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDXpSU0BNgYvUDJTSC//////AQDyBSoBAAAAIyEDjIZh3LP/iadr3RHpVxLAn7AZWAajLl8O1zmwZHVne/+sAAAAAA==
Block: 11
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBH3pSU0BRwYvUDJTSC//////AQDyBSoBAAAAIyEDH96UU8YWwE7gP4Cf+gSH7sk0QMqxrQbuaga2oYw4kpasAAAAAA==
Block: 12
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBELqSU0CwgAGL1AyU0gv/////wEA8gUqAQAAACMhAgIKNC4+LiDFAAd8tDBKMVXae1qYWOoTaazXtuyzwyUErAAAAAA=
Block: 13
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJnqSU0BUgYvUDJTSC//////AQDyBSoBAAAAIyECKjNeYBvHflQBDnsV9ZeC1vcEhbC64+uF3yW6QeOtfIesAAAAAA==
Block: 14
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKHqSU0BBQYvUDJTSC//////AQDyBSoBAAAAIyEDrIfcVRiUMUkBOa7g5pC4wNQedwKRq5DOjaHqqOE732isAAAAAA==
Block: 15
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBK3qSU0BCQYvUDJTSC//////AQDyBSoBAAAAIyECpAwbcwsLplZwrckU2YVwjav4xSSwMl1E7id30QVVbKGsAAAAAA==
Block: 16
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMPqSU0BEgYvUDJTSC//////AQDyBSoBAAAAIyECwfrFEBgeQHRGx3JzWrx2WrgZdbsMPKmxYXSY6SnIhW+sAAAAAA==
Block: 17
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBFHrSU0CiQAGL1AyU0gv/////wEA8gUqAQAAACMhAu9x/ERPDFCLH+Zz9EkGacdLHUNJBNJlrjHPj8qij36nrAAAAAA=
Block: 18
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBH3rSU0BKQYvUDJTSC//////AQDyBSoBAAAAIyEDsbskjzdWg95PsEVNPlF9UYlBUaDX7pRlaPutz07igl2sAAAAAA==
Block: 19
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLDrSU0BLwYvUDJTSC//////AQDyBSoBAAAAIyECAela3YC/7QecmoXpwcVBHvmq9Igg7/pPrp6+po6gOeasAAAAAA==
Block: 20
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLPrSU0BAwYvUDJTSC//////AQDyBSoBAAAAIyECOCTb7SV0yI7jdXiNlWnfDqCyTM/Socpx6ix0Q2fec1usAAAAAA==
Block: 21
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBnsSU0BYwYvUDJTSC//////AQDyBSoBAAAAIyEDOxvsrCrf3LzfkqF6sW2hdDI0STQcvDDKFaguehlJhjSsAAAAAA==
Block: 22
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBBbtSU0C+gAGL1AyU0gv/////wEA8gUqAQAAACMhA7eHkgWUy0f7/M7pFb765ArC4rKVIkRg7uB1rQraTAxUrAAAAAA=
Block: 23
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBE3tSU0BNgYvUDJTSC//////AQDyBSoBAAAAIyECKifvqihaTQSfERtUPc1YLGxxuyHyCyKniRx3yXX7O8OsAAAAAA==
Block: 24
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBGnuSU0CFwEGL1AyU0gv/////wEA8gUqAQAAACMhA8BULZnHhUkkwRuChgNlmiruT0O6R8lNAKmIjwuhr7/zrAAAAAA=
Block: 25
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBP/wSU0CjQIGL1AyU0gv/////wEA8gUqAQAAACMhAxGkBMZd+Vjgbo7VWoLTzgo/gcV4AiFLSVS9x890lFRirAAAAAA=
Block: 26
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDrxSU0BMwYvUDJTSC//////AQDyBSoBAAAAIyECffJ5kZ4Q7JLmSbsjk86Kh21LCmDi2MuN4ESioZnesPKsAAAAAA==
Block: 27
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFnxSU0BGQYvUDJTSC//////AQDyBSoBAAAAIyECcJP3Vfc3TUatwc3raJDpEf2EI3rQ30yLph5MO/sy012sAAAAAA==
Block: 28
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBF7xSU0BAwYvUDJTSC//////AQDyBSoBAAAAIyEDhOZsm1BYwtjpDfh7mAKxflVlaFthoun6idSM7fGafSOsAAAAAA==
Block: 29
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNrxSU0BdwYvUDJTSC//////AQDyBSoBAAAAIyECWXKM/kRtVcixvUPEg9y21vCzgqdLCEQG4Ig8mZMlzKisAAAAAA==
Block: 30
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBIHySU0CowAGL1AyU0gv/////wEA8gUqAQAAACMhAs/LJ+fERSyRleiLOeSxjUX14Ecz5yzVWDF3lx/L0wJTrAAAAAA=
Block: 31
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKrySU0BJwYvUDJTSC//////AQDyBSoBAAAAIyECPU5mVU5PatRnuw8wIibdoUzITkeZQhk67Kpv5ezUjTSsAAAAAA==
Block: 32
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBL/ySU0BEwYvUDJTSC//////AQDyBSoBAAAAIyECtvPaaw1EP0rmDVLOibHEztobgYLCWYhVSXZJArIwpHusAAAAAA==
Block: 33
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM7ySU0BCQYvUDJTSC//////AQDyBSoBAAAAIyEDzFQB490ZDRQ1WMOuhSC4sZ651G9sh2DJ+ZcuWuIflWCsAAAAAA==
Block: 34
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNPySU0BAQYvUDJTSC//////AQDyBSoBAAAAIyECSylQW41EXWOZ31CvExD6+aXabV0TrFSinEwMY9+pj86sAAAAAA==
Block: 35
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBTzSU0BPgYvUDJTSC//////AQDyBSoBAAAAIyECE8p6oDbtxI7jSmW2lNfLn6oxtoLi88KLdQB7BfBeBlusAAAAAA==
Block: 36
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBG3zSU0BVgYvUDJTSC//////AQDyBSoBAAAAIyEChAl8To2kjVb58pc1oWzLfRImNg9q8srVh4VHczZYV12sAAAAAA==
Block: 37
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBH3zSU0BDgYvUDJTSC//////AQDyBSoBAAAAIyEDE5yzxxZ4WFoduT16wym78lpcAw+rP70r2eMnHZ94ScqsAAAAAA==
Block: 38
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBN/0SU0CXwEGL1AyU0gv/////wEA8gUqAQAAACMhAhPWoDG6689omfxxvV8+TJgHb8Id0gkb2k3i0rkvZ/oorAAAAAA=
Block: 39
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBA71SU0BKgYvUDJTSC//////AQDyBSoBAAAAIyEDQIng3kzxC1cm+G0Bnth9Sa7KOHFuCm3z4xLyYCJ7O4+sAAAAAA==
Block: 40
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJD1SU0BfgYvUDJTSC//////AQDyBSoBAAAAIyECoY1wflhE9PVB9dwhSknejApBY/eIE0CvIKObEuf6B+asAAAAAA==
Block: 41
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNL2SU0CPwEGL1AyU0gv/////wEA8gUqAQAAACMhAmcdzpOspNYs6o/TN5CzDiqhx9K96neEhROlO47zm49arAAAAAA=
Block: 42
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOP2SU0BDQYvUDJTSC//////AQDyBSoBAAAAIyEDfO7OWX00d7xOLX5GiwhH9WSnZqMSzmnOLg1oZ86i4cGsAAAAAA==
Block: 43
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBE/3SU0BawYvUDJTSC//////AQDyBSoBAAAAIyEDOsp3p/iuhz87/hjiQaW5MLFTEAMjdHBG9toI78bR6CWsAAAAAA==
Block: 44
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBI/3SU0BPQYvUDJTSC//////AQDyBSoBAAAAIyEDWGIJZypV1ghaNLShPzAtGfr2hY41jb8JAJ8hk9v2NwusAAAAAA==
Block: 45
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBC34SU0CmgAGL1AyU0gv/////wEA8gUqAQAAACMhAp+9ICcmETU29ZlGo4RRY25HXEhmg91nRnSBASYH18B7rAAAAAA=
Block: 46
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBFD6SU0CHQIGL1AyU0gv/////wEA8gUqAQAAACMhA4XwdH0k+Heveh7uQ3phvM9SVCbtT1l9Eq0Y3fPYsjtQrAAAAAA=
Block: 47
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGb6SU0BEgYvUDJTSC//////AQDyBSoBAAAAIyEDZhcjinxBQXVgFLA+iAGp1VZsalDx+gptnX5pzTFgLomsAAAAAA==
Block: 48
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHv6SU0BEQYvUDJTSC//////AQDyBSoBAAAAIyEC1/pOUjVLwQLKHrbmzekcK3mM5m27Pw2DfceQQWGPIAesAAAAAA==
Block: 49
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKD7SU0CIgEGL1AyU0gv/////wEA8gUqAQAAACMhAiDrQHypfIhJFYRfd0eD5sw0sUdED2ddyxZjTYRiTU0OrAAAAAA=
Block: 50
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNn7SU0BNgYvUDJTSC//////AQDyBSoBAAAAIyECzrgonxvoWIwfydrc0JwZfPFzpoqE7TRNHP6fDLJXYR6sAAAAAA==
Block: 51
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFz8SU0BfQYvUDJTSC//////AQDyBSoBAAAAIyEDr0DSfmYfDJs++dvPnylmZNXo6w+uI1FSJ9pE0/LgxQisAAAAAA==
Block: 52
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGX8SU0BBgYvUDJTSC//////AQDyBSoBAAAAIyECR0ME6erPMG6zEPONKd2e4PkWuxQbS3McimdcBviLh5SsAAAAAA==
Block: 53
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBBX9SU0CrgAGL1AyU0gv/////wEA8gUqAQAAACMhA/EIOKqd9tFpqUFm5q8D3f0UmaPOpXYHzC+BdKh9Q11lrAAAAAA=
Block: 54
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDX9SU0BGgYvUDJTSC//////AQDyBSoBAAAAIyEClk2EdET+f2E7Kt/Ayfl+I9X7zZ6Mz8jkqR2flAMszmusAAAAAA==
Block: 55
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPn9SU0CwQAGL1AyU0gv/////wEA8gUqAQAAACMhA8v9vShdzgiq3fYDiu7o2fmp0vTpVdo8k7kTuWLDU+xtrAAAAAA=
Block: 56
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBP39SU0BAQYvUDJTSC//////AQDyBSoBAAAAIyECmp028rYoYhYHasQ1vK47uroaK1B6WLIP1WHqfo4iAzisAAAAAA==
Block: 57
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEr+SU0BSQYvUDJTSC//////AQDyBSoBAAAAIyECej6GuUWYaRu62yUOCQje4vi8K9C+VTDELG/6lMPSPbqsAAAAAA==
Block: 58
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBF/+SU0BEQYvUDJTSC//////AQDyBSoBAAAAIyECcEE7ucUapHJFm85zreQ3upb18xlIoRNc+wdnsfzPUVSsAAAAAA==
Block: 59
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKP+SU0BQgYvUDJTSC//////AQDyBSoBAAAAIyECyPrrEQItHPOXtZlEQ9qQrCdLxzTF327jDNhBP+e9kHmsAAAAAA==
Block: 60
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLP+SU0BDgYvUDJTSC//////AQDyBSoBAAAAIyECyEpYC2LXJzJqHz8198VHG19CD1+n/kSCnxc2e6ZpBfqsAAAAAA==
Block: 61
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCX/SU0BbwYvUDJTSC//////AQDyBSoBAAAAIyEC5QZU5g1XN84Sap0NGdZwTrxu4t3M+0A+VJ1mYM0LMcSsAAAAAA==
Block: 62
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBH7/SU0BVwYvUDJTSC//////AQDyBSoBAAAAIyEDydEjy+7iKghK4PUM8ZyOqRFwsROlC5uw/gNCN2Q9UdqsAAAAAA==
Block: 63
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNL/SU0BTQYvUDJTSC//////AQDyBSoBAAAAIyED1WiZB9m6NTr+d+ME7Wj2XpWGXSnNkIsP72cPYxEHU42sAAAAAA==
Block: 64
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBD0ASk0BZgYvUDJTSC//////AQDyBSoBAAAAIyECzGG9c2zi1DiTrg9QPSeB2rX+VIf/oONq+eJVPLX0qgasAAAAAA==
Block: 65
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJQASk0BUgYvUDJTSC//////AQDyBSoBAAAAIyEDeVzpequjyO8ZQQeEmHHhsoYTJsewby6iJGgc6KSWwpqsAAAAAA==
Block: 66
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKMASk0BCQYvUDJTSC//////AQDyBSoBAAAAIyECAiEO+Qdmz5FpUwry8Ro1MOTfWXk5J1THOTFvnXFi6VysAAAAAA==
Block: 67
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKgASk0BAgYvUDJTSC//////AQDyBSoBAAAAIyECirk7Gw8pjP7Ir8lsWfcMStVKPfkms+Go/OqOJmr0lXGsAAAAAA==
Block: 68
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOIASk0BNwYvUDJTSC//////AQDyBSoBAAAAIyECh5wT3uZUInQ/YidZdpAh8mLwMJ7VCQxJR6ieVMBNRrGsAAAAAA==
Block: 69
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBMBSk0BLgYvUDJTSC//////AQDyBSoBAAAAIyEDA66EL4cQecB7lIS2SvJhOKdVbBqDvMz2sUpg3XCrwK6sAAAAAA==
Block: 70
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBC4BSk0BFgYvUDJTSC//////AQDyBSoBAAAAIyEDk1oBxCVyg2vY53MZolz9+ZSWC+MZx9p3j3k8OFAHJ9GsAAAAAA==
Block: 71
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGYBSk0BNQYvUDJTSC//////AQDyBSoBAAAAIyECDmH2JO8GPQAM7t9hooYcj5sUinvZ78qBuw4Dd4n0K5usAAAAAA==
Block: 72
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKUBSk0BOgYvUDJTSC//////AQDyBSoBAAAAIyECFF5f5/Z+jml3cQzeXcJRDdK8UipNynl5WxeDmlSjq1SsAAAAAA==
Block: 73
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPwBSk0BUQYvUDJTSC//////AQDyBSoBAAAAIyECnhA+aRuRezF2e8WEGG/s7V8nc8EtaztPL+0EpbfjPZqsAAAAAA==
Block: 74
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBM0CSk0CzQAGL1AyU0gv/////wEA8gUqAQAAACMhA8IkXPeRF5hovk2URYw48sE8qBZN2/hVmGHDTqfIOUPqrAAAAAA=
Block: 75
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBCEESk0CTwEGL1AyU0gv/////wEA8gUqAQAAACMhAyF77cSm6Fcc1+7SixaXLAjqbcACJueGouOB/8fL9KdbrAAAAAA=
Block: 76
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNgESk0CsQAGL1AyU0gv/////wEA8gUqAQAAACMhA4Q4ZrFzL7O+rRNPn1GlFZSj1QPbpIB2mB+Nl8BtW3JgrAAAAAA=
Block: 77
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEEFSk0BZQYvUDJTSC//////AQDyBSoBAAAAIyEDBWUMsPAGRZhzGK/mJPCnGUdp9Uv+IEvklL2r1UTpj8CsAAAAAA==
Block: 78
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLgFSk0BdQYvUDJTSC//////AQDyBSoBAAAAIyEDeN6b8cqvdr+sNsSTYFnPf1UdCFbmKi0gWv1FKVHr7mqsAAAAAA==
Block: 79
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNcFSk0BHQYvUDJTSC//////AQDyBSoBAAAAIyECxtpvDSQjzrxLIXUx1r9SY34QVRzE+AzhV/lFnFMV2aisAAAAAA==
Block: 80
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBP8GSk0CIQEGL1AyU0gv/////wEA8gUqAQAAACMhA4fXPIkMjM8Fw51yXPpY0LpoBqIRi49vNM2NvDZZRrNCrAAAAAA=
Block: 81
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBoHSk0BFwYvUDJTSC//////AQDyBSoBAAAAIyEDPiCVXPu1XICM1gydMr47Nc0ePwNmnm7hUBXmqskaY0SsAAAAAA==
Block: 82
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBI4HSk0BcwYvUDJTSC//////AQDyBSoBAAAAIyED4YYspc2ccGWimDbH1cofSdDAkepk8ackLroibbzSpIusAAAAAA==
Block: 83
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJ8HSk0BDwYvUDJTSC//////AQDyBSoBAAAAIyECTp/aW1UTcPN28O7w1Go7jamne+51lR8QCiSC57OzxWWsAAAAAA==
Block: 84
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLwHSk0BGwYvUDJTSC//////AQDyBSoBAAAAIyEDLD0fFf178690BLd3hIBRMWutBwHaeksqee/yOiAdxNmsAAAAAA==
Block: 85
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPkISk0COgEGL1AyU0gv/////wEA8gUqAQAAACMhA8ku4jTOrGgCQdXBhEmQwa8CIcIYVrgKek4mIuFlxOr8rAAAAAA=
Block: 86
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBH4JSk0CgwAGL1AyU0gv/////wEA8gUqAQAAACMhArdNqbvb9LnevbFlhSY+uK9qvP7Ue7psxbAcg4rlJ3eWrAAAAAA=
Block: 87
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPUKSk0CcgEGL1AyU0gv/////wEA8gUqAQAAACMhA6S52CxTnl/IQyoeBkQYmzBZckrsJoGYVwOEOiZERacPrAAAAAA=
Block: 88
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDcLSk0BPwYvUDJTSC//////AQDyBSoBAAAAIyEC/xp5RA5PGqknb6ogNmXbB87Wz3BDHcexnVgIQRSCbeysAAAAAA==
Block: 89
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDsLSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyECERJMGxQyGb/271PHI4bhd1jU9F3RNHBSRzEgBKCY0BmsAAAAAA==
Block: 90
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBEgMSk0CCQEGL1AyU0gv/////wEA8gUqAQAAACMhAknGp243wvzVZofd5rdbvfcvze6rb+gVYanEGskNnR9IrAAAAAA=
Block: 91
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIkMSk0BPwYvUDJTSC//////AQDyBSoBAAAAIyECC6nvDf8UAxjJV0TJgszNp0/vSx6s/xp3jS9KNQPNECqsAAAAAA==
Block: 92
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLMMSk0BJgYvUDJTSC//////AQDyBSoBAAAAIyEDX/Pb/4LxrP8BUqJ5toAAX7zLYkAnR6CSS73Mza4uJ/SsAAAAAA==
Block: 93
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAYNSk0BTQYvUDJTSC//////AQDyBSoBAAAAIyED238//BrNaXpFgoJQqhDfbG03KklVowE63vIF/LhRwzWsAAAAAA==
Block: 94
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDgOSk0CKQEGL1AyU0gv/////wEA8gUqAQAAACMhA3Lt3dFjLO00uwOF5Qi0rbMWM5i4w1Px/zIKRDhJNU8ArAAAAAA=
Block: 95
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBD0OSk0BAQYvUDJTSC//////AQDyBSoBAAAAIyEDuKDxIuMDhmTrMmCxNE6VDkEzSChCj8yFp/VZ9ydLsASsAAAAAA==
Block: 96
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEEOSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyEDaMPL9oFu1z1Q8EjbqHa/qAZLxBTLLyVrKxEi3Yok30SsAAAAAA==
Block: 97
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFsOSk0BFQYvUDJTSC//////AQDyBSoBAAAAIyECA23/zJ/0yI3V3PGTelRLpNJwSDDjSmV4vwATu0APHSusAAAAAA==
Block: 98
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGIOSk0BBQYvUDJTSC//////AQDyBSoBAAAAIyECseBU+/S+VjT6CZMxNhF7s7MdCesDGFzR3+7ebDcDIJGsAAAAAA==
Block: 99
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHQOSk0BDQYvUDJTSC//////AQDyBSoBAAAAIyEDYJIpTSiKIZSZb4WuYs6egFJKl/UljgFQHNA+aU+wlzSsAAAAAA==
Block: 100
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOEOSk0BaQYvUDJTSC//////AQDyBSoBAAAAIyECp0EHEWS0CwHErSiRPEqioQFcxbBk8MgCJyVS8Xrgh1CsAAAAAA==
Block: 101
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBN8PSk0C/AAGL1AyU0gv/////wEA8gUqAQAAACMhAuDXugKxeyPjCOvbF3DocZCvUcibYhIRvwm6c4WnnLOErAAAAAA=
Block: 102
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOgPSk0BBgYvUDJTSC//////AQDyBSoBAAAAIyECjWrD9Yi8FDFKE0YTDEAIqat0AqqfwVq+Fc2LFSEwSbKsAAAAAA==
Block: 103
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBO4PSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyEDYorAJhhfbpTZx4n/5cuSwMREKksSS49oEfoujNLXrtqsAAAAAA==
Block: 104
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBAQSk0BHgYvUDJTSC//////AQDyBSoBAAAAIyEC3XXrVkgaG+NMvqLawe0bJMcD/ULrIQ+8MBEt9Tc+zBGsAAAAAA==
Block: 105
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFMQSk0BPgYvUDJTSC//////AQDyBSoBAAAAIyEDKziPAFRNIxoclk2zUULokJ6weapTPItw8jlHqKMAKomsAAAAAA==
Block: 106
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJIQSk0BPwYvUDJTSC//////AQDyBSoBAAAAIyECnap6EmSxNxBja9sb9WKBjEOc+IaVL11ZEfuhicQETSKsAAAAAA==
Block: 107
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPoQSk0BYQYvUDJTSC//////AQDyBSoBAAAAIyEDQbRZLdFqTyYVWs1rOWpWBLenSg+e/GvSst+fkWElJtysAAAAAA==
Block: 108
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBM8RSk0C0gAGL1AyU0gv/////wEA8gUqAQAAACMhAlCVtoPrkh4/BjYdI2SNmZQslxj2Ai6F4L9nsNGOSQ94rAAAAAA=
Block: 109
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBHsSSk0CqQAGL1AyU0gv/////wEA8gUqAQAAACMhAkVeiQoVVJnM3cKkTS2KpE6VtNM7Hv5m81yM0OLoeE35rAAAAAA=
Block: 110
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJ4SSk0BIQYvUDJTSC//////AQDyBSoBAAAAIyED/MYoWE+Nakd/ASdja62uaaDg8YBaBlPId6zNo9QvOeCsAAAAAA==
Block: 111
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAETSk0BXgYvUDJTSC//////AQDyBSoBAAAAIyEDulAFvCPjIXYYydMeS9Hy9GgxGV1FMXPhjeXT4TAsWwisAAAAAA==
Block: 112
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBMETSk0CugAGL1AyU0gv/////wEA8gUqAQAAACMhApYlJaLMQwsCUvCvE2GitF+TAmd3RtY1/OlpcSRgBxWhrAAAAAA=
Block: 113
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAUUSk0BQQYvUDJTSC//////AQDyBSoBAAAAIyEDKEdW/gN0khwyVjZKfx9nJcvH4qOOczj8zqJLykLlCwesAAAAAA==
Block: 114
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBoUSk0BEwYvUDJTSC//////AQDyBSoBAAAAIyEDL/EK5v6tK6oGqFFqe8//IV0PA4SAAQSL9oBlHCE7+I2sAAAAAA==
Block: 115
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDAUSk0BEgYvUDJTSC//////AQDyBSoBAAAAIyEDrFOsSWu4ejinHQ0ZyCsYeFn2lmOi0IZCNlCN7jEiEVOsAAAAAA==
Block: 116
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFIUSk0BHwYvUDJTSC//////AQDyBSoBAAAAIyECj0sipvPHM6oX2Suk6PK+LqKb1d4d/p1V/1QzP9w28zasAAAAAA==
Block: 117
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDsVSk0C5wAGL1AyU0gv/////wEA8gUqAQAAACMhAmeMh63HQmd8cON/IfxgbUeQ7dFT1K21wLz9pxQS4Ry8rAAAAAA=
Block: 118
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHEVSk0BMQYvUDJTSC//////AQDyBSoBAAAAIyECN/Qd2eah2UkEmQg2RIfkcLW0ioNNergQqVMdEfek6resAAAAAA==
Block: 119
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBI4WSk0CGwEGL1AyU0gv/////wEA8gUqAQAAACMhAzMl14BRqQarAAF+6UfE6MZ9xSjCdSfs1kvgxHmb655FrAAAAAA=
Block: 120
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBIsXSk0C9wAGL1AyU0gv/////wEA8gUqAQAAACMhAl/2wZV0zb65Vo0vpQlAoAGfK6mW/XdHHHGupdwMOK4vrAAAAAA=
Block: 121
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAMYSk0BdwYvUDJTSC//////AQDyBSoBAAAAIyEDFeUkW4kgurJkKtZppFFONYbuCUqngDiX/Pt9+H0NJHSsAAAAAA==
Block: 122
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBAYSk0BCwYvUDJTSC//////AQDyBSoBAAAAIyECjMDQibQYuqWWAFTuz6dY6kNMSlqIosrrvIdLsUQmfRusAAAAAA==
Block: 123
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBoYSk0BBwYvUDJTSC//////AQDyBSoBAAAAIyEDxmWiC8T1BP8SGur/FIWgXfxYYcHKeL4npwGuFq67ACKsAAAAAA==
Block: 124
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBEgZSk0CKwEGL1AyU0gv/////wEA8gUqAQAAACMhAwHf2sC7W2d2IH994GJVVX7tRHe32CbuCtrzo2MLuMYVrAAAAAA=
Block: 125
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFUZSk0BCwYvUDJTSC//////AQDyBSoBAAAAIyED0hDa6WdJtpZ6p98G6m2UjqiixKyIuJ0MFPajGmjssBmsAAAAAA==
Block: 126
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKEZSk0BSwYvUDJTSC//////AQDyBSoBAAAAIyEC6Tum2NedfqmBS8N+FQE+NDwZ9KFXXPVWJyzmRk8JCCqsAAAAAA==
Block: 127
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBO8ZSk0BSgYvUDJTSC//////AQDyBSoBAAAAIyEC7KD44OHRMoAgeSAAC7x0Oj84FPEZi1Xg4SBSggQS4t2sAAAAAA==
Block: 128
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCEaSk0BLQYvUDJTSC//////AQDyBSoBAAAAIyED03efe2zTPZ5E5IEp9ISyf0FMMZEaBTOW03/yCvR2GM+sAAAAAA==
Block: 129
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBE4aSk0BKgYvUDJTSC//////AQDyBSoBAAAAIyECwalSu7EuBcSrjEG2inHKaIpIuFyoK1DRQJVYLf+HSjWsAAAAAA==
Block: 130
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGwaSk0BGgYvUDJTSC//////AQDyBSoBAAAAIyEDnJcLkSa7HVF9W8TBdvX3Vc0B5uy2lxV8HzLiYl89CSSsAAAAAA==
Block: 131
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKcbSk0CNgEGL1AyU0gv/////wEA8gUqAQAAACMhAgwI2E8OE8zFqqaK+g+tivMz9gGHpo+bHjh6ezyFdarBrAAAAAA=
Block: 132
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMUbSk0BGgYvUDJTSC//////AQDyBSoBAAAAIyED3vQjnrHezODS7A3yL6p+uEqBalS+A3ZcnJv1TGYlmdusAAAAAA==
Block: 133
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAAcSk0BNwYvUDJTSC//////AQDyBSoBAAAAIyECPgylKGKmLvlCsYsvfc6etncxnBfkOzyCsUc+2f/5/D+sAAAAAA==
Block: 134
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDkcSk0BNwYvUDJTSC//////AQDyBSoBAAAAIyEDmAG3xKRdjqz1TlXMHkjy8VCwBa7Z0BXDgSFyRhbSsiCsAAAAAA==
Block: 135
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNQcSk0ClwAGL1AyU0gv/////wEA8gUqAQAAACMhAql6KbWWtQ3glHcRUGYj3ZoP5FNTn8LrGsWCelXHorCDrAAAAAA=
Block: 136
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOYcSk0BDgYvUDJTSC//////AQDyBSoBAAAAIyEDI8XxVM4wiDQ8N0moqKA3aYzTf30OHKpT/oNa8gWnr2qsAAAAAA==
Block: 137
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBMwdSk0C4QAGL1AyU0gv/////wEA8gUqAQAAACMhAo49WfWmzQi7F5tzwpGkvJ6e8RKR7OYSVJSeKT9IiGhtrAAAAAA=
Block: 138
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNodSk0BCQYvUDJTSC//////AQDyBSoBAAAAIyECi017LAVObSf/5Rwfix/FhWBC2jNRTlZ4KfrnUnvfmTOsAAAAAA==
Block: 139
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBO8dSk0BFAYvUDJTSC//////AQDyBSoBAAAAIyECW2XIUIXSxutXOlHs48KS0x7TKI/XXyPp59+kvgAFu6isAAAAAA==
Block: 140
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPcdSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyEDpl1cLBpqfSzONTnwQsdqHOFjhHH0fdVVFDXhrKHzcz2sAAAAAA==
Block: 141
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBIkeSk0CjwAGL1AyU0gv/////wEA8gUqAQAAACMhAo639YmdK+SsumPwiPgosjcIPN4bguWzANGhJONA6npKrAAAAAA=
Block: 142
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBP4eSk0BcwYvUDJTSC//////AQDyBSoBAAAAIyEDh1Y6ou0Q7r88w3LyFO4Ou+VAckXDrbCqK+ieFH3jksCsAAAAAA==
Block: 143
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAcfSk0BBgYvUDJTSC//////AQDyBSoBAAAAIyECgYYEfoORKB4/4+fBR2LN2pELTRbhJSpFEos+/kwqOWmsAAAAAA==
Block: 144
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJofSk0CjwAGL1AyU0gv/////wEA8gUqAQAAACMhAlR7Ij1Y612nx2kHSPcKO6sVCct1ePqskDI5nwtrzjHWrAAAAAA=
Block: 145
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDsgSk0CngAGL1AyU0gv/////wEA8gUqAQAAACMhA//fMrrnSOufu49dboDO10CHqbQrMLK8IVpadlmbklNIrAAAAAA=
Block: 146
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBH0gSk0BPQYvUDJTSC//////AQDyBSoBAAAAIyEC5OG3sNSMSlP9KpYGnUWZdDg5VNohjMPMsH5fW6AxYNesAAAAAA==
Block: 147
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOggSk0BZQYvUDJTSC//////AQDyBSoBAAAAIyEDeEPHfTsL4Bfb3ccC4idXbDyNqcTkrZKEZVvj17uvpRSsAAAAAA==
Block: 148
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAAhSk0BGAYvUDJTSC//////AQDyBSoBAAAAIyED57ygEjbUgyC3aieMvHbX1pcm4LCUC3IOfdl+PP4fbGWsAAAAAA==
Block: 149
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBC4hSk0BKwYvUDJTSC//////AQDyBSoBAAAAIyED+FCDPTLkqxp0MVfJluKh57I19Dn9Iih7Woi6Tb8afRWsAAAAAA==
Block: 150
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJIiSk0CXgEGL1AyU0gv/////wEA8gUqAQAAACMhA+mAqc9h4nD0t45VfLx2UUUA0/p4kqxabd2ZmYuq6gbkrAAAAAA=
Block: 151
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBLQjSk0CHwEGL1AyU0gv/////wEA8gUqAQAAACMhAmPucb2v4yUFUs+fsMFzQHJ1j/9ce58LGgRe6RRh/euHrAAAAAA=
Block: 152
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBB0kSk0BZQYvUDJTSC//////AQDyBSoBAAAAIyEC9xVG/Fl+Y+KnLa3u61DAymQHmlpTDLAd2TlxbUHp1ICsAAAAAA==
Block: 153
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIckSk0BZwYvUDJTSC//////AQDyBSoBAAAAIyECTRtIq6UP01DI9p7iiDVWNa/jito7eNknrlptxob8CMmsAAAAAA==
Block: 154
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMUkSk0BOQYvUDJTSC//////AQDyBSoBAAAAIyEDRUuy+NWMnk9ILuZ8DsapFVsOEDCC2KhTZXhMPg/0pLGsAAAAAA==
Block: 155
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCglSk0BXQYvUDJTSC//////AQDyBSoBAAAAIyECpWAAkqzDwjMqnXaDKK1kwh8APDmky4ymzsjsiQwAPIysAAAAAA==
Block: 156
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBOklSk0CvwAGL1AyU0gv/////wEA8gUqAQAAACMhAyNBmkFIDhmpISxIaAl8BYhRlGkBGV02hWlvr5HUQ8SNrAAAAAA=
Block: 157
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPMlSk0BBwYvUDJTSC//////AQDyBSoBAAAAIyECVUwl8GtKXoE/NvfIsnO79lk3xtuTS0whn0U9xaWNfZ2sAAAAAA==
Block: 158
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBIEmSk0CiwAGL1AyU0gv/////wEA8gUqAQAAACMhA2eaRhiZvGK0In2a/nKOXB769+5t51fHwe27IRDD8RDWrAAAAAA=
Block: 159
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJUmSk0BEgYvUDJTSC//////AQDyBSoBAAAAIyECSnRxC9g7iWyJOp5+YM/FZgmbcbPsmVh5aSkjv/1Fr+KsAAAAAA==
Block: 160
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBL8mSk0BJwYvUDJTSC//////AQDyBSoBAAAAIyEC5D7rknn6lh1+hyHQtrGTqi5eDm7RQ3kZ9nTgfZeqQO2sAAAAAA==
Block: 161
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBIAnSk0CvgAGL1AyU0gv/////wEA8gUqAQAAACMhAky0lADzyWXLORNQEhDBS4Y+ALXvKIBDqAc++PzHoWMfrAAAAAA=
Block: 162
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPwnSk0BeQYvUDJTSC//////AQDyBSoBAAAAIyEDZl+fHnBeazj0LWAi5pTzm/sexX+/HOAWCH1HgkKwPJGsAAAAAA==
Block: 163
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBMkoSk0CygAGL1AyU0gv/////wEA8gUqAQAAACMhA8WnNOO3JQUBUrPDxen13ndh2yW+n3MxlW+XRd2iTLcCrAAAAAA=
Block: 164
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOooSk0BHQYvUDJTSC//////AQDyBSoBAAAAIyEC/lxWWAay2wT4o39Tr2Ns7nwO+lyMF5SZq8rI1U1X/FKsAAAAAA==
Block: 165
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBHspSk0CjwAGL1AyU0gv/////wEA8gUqAQAAACMhAk3t/tXOCj9LycCuXAWJ0v8jtOUZvOEgiA/jVcpaDVusrAAAAAA=
Block: 166
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBBIqSk0CkwAGL1AyU0gv/////wEA8gUqAQAAACMhA9xfxtKVRJeu2iyjBtle7aNf4PX9iJp49sOdNZngbhberAAAAAA=
Block: 167
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBUqSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyEDzt1mHK9GZEgenCDf5gVQ9pkqBW2ynXSIx+R/u1p4+7+sAAAAAA==
Block: 168
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBB8qSk0BBgYvUDJTSC//////AQDyBSoBAAAAIyECcmG4uffmlftTc8/q0HovvNkqByGT9iSYD1JLoD3T2KGsAAAAAA==
Block: 169
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCQqSk0BAQYvUDJTSC//////AQDyBSoBAAAAIyECKJDBT07ersXWrdbd1y6AZ2YDmQQ6+Vp4g6NLUMTJ+qysAAAAAA==
Block: 170
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGgqSk0BQgYvUDJTSC//////AQDyBSoBAAAAIyECZWWUoDCWh1c1W9w74ve+UH981Eo1UM5e/1v5cAU6fOSsAAAAAA==
Block: 171
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIYqSk0BGQYvUDJTSC//////AQDyBSoBAAAAIyEDF2fHjUsx87d2NosEP+141eCTd+K3U51XYtvUrlrtDN6sAAAAAA==
Block: 172
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBK4qSk0BJwYvUDJTSC//////AQDyBSoBAAAAIyEDFRrbmh92qUy24UA0dOBXZkjabZdjzX09/eehBoXur4WsAAAAAA==
Block: 173
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDQsSk0CgwEGL1AyU0gv/////wEA8gUqAQAAACMhA9V0fQUO8S9LLUYyAF/C1pjsS4Nj04HBCWOIMBeJQpIfrAAAAAA=
Block: 174
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJIsSk0BWgYvUDJTSC//////AQDyBSoBAAAAIyEDUY2+hN3z/qi3FLQeVdbXeo2qvk+n2HI7YnmL++mj2JqsAAAAAA==
Block: 175
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBA0tSk0BdwYvUDJTSC//////AQDyBSoBAAAAIyED2ajBIKQoSY0sQtN9UXzjxN9RdlATZuFxZtE/VNb8TRGsAAAAAA==
Block: 176
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCktSk0BGgYvUDJTSC//////AQDyBSoBAAAAIyED0zYlPDsSgALLnDg8eSTEv1O+XSZip7udyNxu6mct6dysAAAAAA==
Block: 177
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBD4tSk0BEwYvUDJTSC//////AQDyBSoBAAAAIyECnmCVvaEzV5T+87o5aRJ7V+zCO1cDMiN8RQrpstQoIC2sAAAAAA==
Block: 178
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEEtSk0BAQYvUDJTSC//////AQDyBSoBAAAAIyECw1GLuJsZoO7CcGxZqIj0Fde9iM46b2hCOkkPzYbPpVCsAAAAAA==
Block: 179
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNQtSk0CjwAGL1AyU0gv/////wEA8gUqAQAAACMhA9FiMoAzSvLf//IuTOJ7iIr42iWVGqjSPJgOwD/I11G1rAAAAAA=
Block: 180
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBIkuSk0CsQAGL1AyU0gv/////wEA8gUqAQAAACMhAgzoxgCUp6u2tfbFsyVyNtQa1/eOlPEKsP22ypizmbPArAAAAAA=
Block: 181
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNcuSk0BSQYvUDJTSC//////AQDyBSoBAAAAIyED/KDiunzajPWWBt5052FD09r91nJKgwvJUXu9j+zK8qCsAAAAAA==
Block: 182
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOQuSk0BCwYvUDJTSC//////AQDyBSoBAAAAIyECAbjIKatNox8k1l5eferyl5W0rT74d1W4ZMHOlBmCypWsAAAAAA==
Block: 183
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDYvSk0BTQYvUDJTSC//////AQDyBSoBAAAAIyECDCHJxkNMLSKT4njHLAKf6Fie9Y6EIKdO1Sh7OpFaHB2sAAAAAA==
Block: 184
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNgvSk0CngAGL1AyU0gv/////wEA8gUqAQAAACMhAkuwZCiL1dTp6Gkdi29dKmRdOduF1BfZOSTmEeGVX6b0rAAAAAA=
Block: 185
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPkvSk0BHwYvUDJTSC//////AQDyBSoBAAAAIyECxpIXgk3R2CVVVDs9VbcrPR9+ENIS/+EmgydRuJb02CisAAAAAA==
Block: 186
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJgwSk0CmQAGL1AyU0gv/////wEA8gUqAQAAACMhAtL4lYkIp7ccSXLAtdvkK4ItTk1+TGDCEzuV5nEyBVErrAAAAAA=
Block: 187
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOwwSk0BUgYvUDJTSC//////AQDyBSoBAAAAIyECPCzw98DWpVH8vkz5wB/gBPPv/PSW9hpJuvuBmUzqyyKsAAAAAA==
Block: 188
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPsxSk0CCwEGL1AyU0gv/////wEA8gUqAQAAACMhAvngQPVLq7NX+R44ubEpXFXPa54gDs75/TuqqNVfIISqrAAAAAA=
Block: 189
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCQySk0BJQYvUDJTSC//////AQDyBSoBAAAAIyECcV6R030jneqDLxRg6R42gRXYymzCOn2pZnlautnjtpmsAAAAAA==
Block: 190
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEIySk0BGgYvUDJTSC//////AQDyBSoBAAAAIyECOsJ4ba9fVJTKq/sBzn8ZyEMY40Xde7mq8IqgxzJsiP2sAAAAAA==
Block: 191
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHwySk0BNgYvUDJTSC//////AQDyBSoBAAAAIyEDYaxjeSGC4vmLLnZSBiOQoVs/N8OQhh1VjbsmvSJWDeOsAAAAAA==
Block: 192
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKcySk0BKgYvUDJTSC//////AQDyBSoBAAAAIyEDE6nEK2vcgUcSPaAGG1lcRoVpH9pMgMELnLyWp8PSEtSsAAAAAA==
Block: 193
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPkySk0BTwYvUDJTSC//////AQDyBSoBAAAAIyECgiabwnuNypax6R76wnwP+WoSo5URuQfZJNXGzMJMDHCsAAAAAA==
Block: 194
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDozSk0BPAYvUDJTSC//////AQDyBSoBAAAAIyECRpq1+j+DYgxIgFHEm9UXzHN17P9kTVK05kSzXTwJbgusAAAAAA==
Block: 195
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPUzSk0CtQAGL1AyU0gv/////wEA8gUqAQAAACMhA255L0d5BkzSHLyHyk1k2g8YQ+rO+KUmbt2wRBdI4IAXrAAAAAA=
Block: 196
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBE0Sk0BGQYvUDJTSC//////AQDyBSoBAAAAIyECAIZcl1++mP3bwjoeLm+zNyIQs+IvDkC1PCV4PTBlmtGsAAAAAA==
Block: 197
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHI0Sk0BXQYvUDJTSC//////AQDyBSoBAAAAIyECjLR7uNNby9GgkoGEDLZJ9E+5jbEpdYjmn+DIaqV7EICsAAAAAA==
Block: 198
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIc0Sk0BEgYvUDJTSC//////AQDyBSoBAAAAIyED2qBTZEmx5B7uBDjoBvifJC47pnN69ttFkXMLKYbIV/2sAAAAAA==
Block: 199
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBN40Sk0BVwYvUDJTSC//////AQDyBSoBAAAAIyEDqq5d+o3hT8+n8SFTXNxKed5P2hHyzqF5aueZsBs8q/isAAAAAA==
Block: 200
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFw1Sk0BegYvUDJTSC//////AQDyBSoBAAAAIyECfYhreF3fEPCFznCYEHUP49yTjI2+QNlrB/Gnq5CcsF+sAAAAAA==
Block: 201
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIE1Sk0BIQYvUDJTSC//////AQDyBSoBAAAAIyED/MnOAprXSvn+yszmi8x3XMbvywAKC4zCs6rK1IULxLCsAAAAAA==
Block: 202
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIQ1Sk0BAQYvUDJTSC//////AQDyBSoBAAAAIyEDGLR8jsPYWgkNOT25W2J35cPx1tEynq0CqOcvIzc+/JesAAAAAA==
Block: 203
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKg1Sk0BIQYvUDJTSC//////AQDyBSoBAAAAIyEDpTE0hjwmpiIpprcrlfdySjeIXsPXiHcRsbc1nuzsNeCsAAAAAA==
Block: 204
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM81Sk0BJQYvUDJTSC//////AQDyBSoBAAAAIyECFv8YWuZ34zrgQrQJtZm7l1uU/+VAiK+MPKNp6LwyK/CsAAAAAA==
Block: 205
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNw1Sk0BCQYvUDJTSC//////AQDyBSoBAAAAIyEDqIiMpDLtIWiJdsenyU/cG+8Dkb1K6fFgIw0+xtrJpH+sAAAAAA==
Block: 206
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDg2Sk0BWwYvUDJTSC//////AQDyBSoBAAAAIyEDkkPygwnlTXCiX1sKhnXsLegIt0Ljcr9xpFA1SAchL5usAAAAAA==
Block: 207
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEY2Sk0BCQYvUDJTSC//////AQDyBSoBAAAAIyEC0cirEKovJKnAWPMlnZASXhXiq5hBtVY9NmHia/SDip6sAAAAAA==
Block: 208
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIs2Sk0BQQYvUDJTSC//////AQDyBSoBAAAAIyEDR3mrcSLWZyPk+AEZeqDYbMU369AyilWs62jasGgH/FisAAAAAA==
Block: 209
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPc2Sk0BZgYvUDJTSC//////AQDyBSoBAAAAIyECI1tcjpvtgMvY13MdVfn9cI0Q66cYW5MEW2YTmMF0DGqsAAAAAA==
Block: 210
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKU3Sk0CqwAGL1AyU0gv/////wEA8gUqAQAAACMhA4UT2yCaEBXO8+K1tsUXtXvcF/gUyER4o6Mp88+7U7o4rAAAAAA=
Block: 211
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM43Sk0BJwYvUDJTSC//////AQDyBSoBAAAAIyEDQztds6F7JDGdYV3FwkUj1r7QuyPBfdtwItfxQpwDjPSsAAAAAA==
Block: 212
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNc3Sk0BBgYvUDJTSC//////AQDyBSoBAAAAIyEDkO6NUxYzgjwm87IpiOTuAOggdX4N8eq3yLWExeVjzxWsAAAAAA==
Block: 213
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEM4Sk0BaQYvUDJTSC//////AQDyBSoBAAAAIyECVggb+D65XJ0dUkYoiY6b8dQ2WrI/1Slbqnx1ksHEndSsAAAAAA==
Block: 214
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKo4Sk0BYwYvUDJTSC//////AQDyBSoBAAAAIyECBIkqmiTU8fNIMESRp4yM/BAhwbuwjyf3JgY3lYArr06sAAAAAA==
Block: 215
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBI85Sk0C4gAGL1AyU0gv/////wEA8gUqAQAAACMhAkuKR3KQysRLoewC6BecSqjM+t3ka1XFiNlBB86Te8ARrAAAAAA=
Block: 216
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKE6Sk0CDQEGL1AyU0gv/////wEA8gUqAQAAACMhA7jPtN3qUeGA6atc5I6F+797GlFI9rOt/oDjZhAEJ/x6rAAAAAA=
Block: 217
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCE7Sk0BfwYvUDJTSC//////AQDyBSoBAAAAIyECGcFv4b+90LIVuMhMZrmZrBL2HElwCE/ZeIwp2lSkbFOsAAAAAA==
Block: 218
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDI7Sk0BDwYvUDJTSC//////AQDyBSoBAAAAIyECVMM/t4acgW2wl3m7rNrmW2Bcb6o9eysiGc5ZkimmKk2sAAAAAA==
Block: 219
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEU7Sk0BDwYvUDJTSC//////AQDyBSoBAAAAIyED9fuhtvoIzHBSYAYPUi18+TxpIuT3xLBEo5jugxaqzJKsAAAAAA==
Block: 220
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJg7Sk0BTQYvUDJTSC//////AQDyBSoBAAAAIyEChBswuJJl+LxHr3C8ZIa0nhEHu9dF7CBr9KIg9nc3UWesAAAAAA==
Block: 221
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBN07Sk0BQwYvUDJTSC//////AQDyBSoBAAAAIyECTfrdKVALUbJ2oTu3TOt89rmu14vx8AzqVBauraYZGgWsAAAAAA==
Block: 222
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDM8Sk0BUQYvUDJTSC//////AQDyBSoBAAAAIyEDEV1Fnz7h+T1mFnKt5rmQfzQyPHUQ1+2t4ggDkaMcc9GsAAAAAA==
Block: 223
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIE8Sk0BSgYvUDJTSC//////AQDyBSoBAAAAIyEC2sGJQbO4JHenGo2TZQQJcET2SFD2GiXBolI5/CuAU7ysAAAAAA==
Block: 224
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIk8Sk0BBQYvUDJTSC//////AQDyBSoBAAAAIyECAvjkjnxZZ5iWH+/mxnKPN4D4g5CowExSUXPQpoi3S42sAAAAAA==
Block: 225
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM88Sk0BQgYvUDJTSC//////AQDyBSoBAAAAIyEDEuJepCVFIAzYpkz71pIQRcbXJntufmttiYSx4Je26desAAAAAA==
Block: 226
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNo8Sk0BDAYvUDJTSC//////AQDyBSoBAAAAIyECLZc94YDLPFptsR2czEZhaZ+pcdPoLYYVJB751wF34FesAAAAAA==
Block: 227
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOI8Sk0BBgYvUDJTSC//////AQDyBSoBAAAAIyECfG5yGKhAyG0ZcdqyJU/qSksw97f/IiRxi+V5VaeyOn6sAAAAAA==
Block: 228
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBC89Sk0BSgYvUDJTSC//////AQDyBSoBAAAAIyEDLtOWt889VoeQivkM0OD5gPvu4EZjsearjW+6aAktEIusAAAAAA==
Block: 229
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDM9Sk0BAgYvUDJTSC//////AQDyBSoBAAAAIyECANaEjBFFTE1JizLMEMoGfQVkfiSwJHqradz50PWbYwqsAAAAAA==
Block: 230
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBGo+Sk0CMwEGL1AyU0gv/////wEA8gUqAQAAACMhAiRR64mo80zoSkOCKV95wLrA3gRJbNMCE9T0oxAIvcjYrAAAAAA=
Block: 231
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMQ+Sk0BVwYvUDJTSC//////AQDyBSoBAAAAIyEDcn8cAvoY/POn5kd0YqL63Ub6xgexr8TqR0Tls7wu60msAAAAAA==
Block: 232
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPA+Sk0BKQYvUDJTSC//////AQDyBSoBAAAAIyECjWiw8RmTXPx4gsMqorvySezHazpv92KB9eZ9PHj04BqsAAAAAA==
Block: 233
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBA4/Sk0BGgYvUDJTSC//////AQDyBSoBAAAAIyECNdE1/RytMjMSHbHimpZmjabjB+8EYqZniTebq7N+ghKsAAAAAA==
Block: 234
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFE/Sk0BQgYvUDJTSC//////AQDyBSoBAAAAIyEDmekRYSKx5XfTCkyZVAdiP6Q4DTHxwNivraFaO97GvEKsAAAAAA==
Block: 235
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNY/Sk0CggAGL1AyU0gv/////wEA8gUqAQAAACMhAkHJPaTCsoHXiY2be2mOKtscOGlv2qpYRa79Jz7Vp3UnrAAAAAA=
Block: 236
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEBASk0BZQYvUDJTSC//////AQDyBSoBAAAAIyEDeDF4XubIYSUDpx4+aosCmjB7gkUp08Nr6gs7QBx18N2sAAAAAA==
Block: 237
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJZASk0BUwYvUDJTSC//////AQDyBSoBAAAAIyEDq6NpbCSWZNlsn+fgnTEBAHEYnACZXZVzAmrrV+4Y4UKsAAAAAA==
Block: 238
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBChBSk0CjQAGL1AyU0gv/////wEA8gUqAQAAACMhAtyS1H1w3anahuWIOZyrKS1kex0IvtxmonHeXFfUWmEDrAAAAAA=
Block: 239
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBM9BSk0CoQAGL1AyU0gv/////wEA8gUqAQAAACMhAlNuTA+BQrHA0LOtsgkwKzhzIuzDbyjyHdMgEQOc+ANSrAAAAAA=
Block: 240
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOBBSk0BCgYvUDJTSC//////AQDyBSoBAAAAIyEDdrS5vHRcn6Akg58B/WI11I9TDq5rwQxpB87c95kCDOusAAAAAA==
Block: 241
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBO1BSk0BCQYvUDJTSC//////AQDyBSoBAAAAIyEC+sHBligYx4TtS+cWEZhv2wbBlXfUEPREeqnI5wWYNgmsAAAAAA==
Block: 242
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPFCSk0C/gAGL1AyU0gv/////wEA8gUqAQAAACMhAz5/DxQyf8ROkF4Pg2gD8MYJED0F/URrV0awvF4FMRKNrAAAAAA=
Block: 243
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJ1DSk0CqgAGL1AyU0gv/////wEA8gUqAQAAACMhAvEL6Z0o6OqWZOUYN/3jknjg73MN6uEfYrO8U0szpYcOrAAAAAA=
Block: 244
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMVDSk0BJgYvUDJTSC//////AQDyBSoBAAAAIyEDgzMUayirzRYw3yrhUGTSSwIKEH7UVviFj4UC72FDRlesAAAAAA==
Block: 245
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBClESk0BYwYvUDJTSC//////AQDyBSoBAAAAIyEDsknmetlzUMelgrf+MTCgNbpc6IsOyW0170PjRJT2dFusAAAAAA==
Block: 246
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBLJESk0ChQAGL1AyU0gv/////wEA8gUqAQAAACMhAuNLBd7+swlxHxCEeLiXEOYRW/gFQdlgwnIg1JmHbbFKrAAAAAA=
Block: 247
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAZFSk0BUQYvUDJTSC//////AQDyBSoBAAAAIyED8NnbkMpwQSlCl2bnp7p9Ah38qaf/idUQWm5qElWt89OsAAAAAA==
Block: 248
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNxFSk0C1AAGL1AyU0gv/////wEA8gUqAQAAACMhAt7m1hSRY4iYKgdUxenze6Z4eKAe2wA3KD8ldqOw8IohrAAAAAA=
Block: 249
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPtFSk0BGwYvUDJTSC//////AQDyBSoBAAAAIyECoxw6WUVf3l0sGw5/qht59qsliYPKImFMIBrzITNSvbOsAAAAAA==
Block: 250
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBB5GSk0BHQYvUDJTSC//////AQDyBSoBAAAAIyEDa/5HErDUCl+ilct1eVsU1FR8A3nFJHHBJX3myJtQuSusAAAAAA==
Block: 251
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJtGSk0BewYvUDJTSC//////AQDyBSoBAAAAIyEDOfeN78x5nXPqNHxfujrEVkRbFrgKArtNuKQz4umMDMKsAAAAAA==
Block: 252
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBO5GSk0BTwYvUDJTSC//////AQDyBSoBAAAAIyECgARqRE+dW6czGMxEd4Qp62s/tOtSOf2yfqTXLQigx/isAAAAAA==
Block: 253
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCFHSk0BLQYvUDJTSC//////AQDyBSoBAAAAIyECGlK3+ujjmC3/bNJUwmrULEeC9wxE6uUTymGByu0Nop2sAAAAAA==
Block: 254
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHJHSk0BTQYvUDJTSC//////AQDyBSoBAAAAIyEDr1fLoRViqetDWdhvOnfoTg/YbqmCjZK6n5vUAjOHw1OsAAAAAA==
Block: 255
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKJISk0CKgEGL1AyU0gv/////wEA8gUqAQAAACMhAiF850NCmPpCLZg6E1c2vK8Y12mh0SRqj5UHoiwegTE0rAAAAAA=
Block: 256
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBN9ISk0BOwYvUDJTSC//////AQDyBSoBAAAAIyEDVsPykwKGvHLHzZXEaKdvUxqXECAP9vU1aEunYXrtTQCsAAAAAA==
Block: 257
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFhJSk0BdQYvUDJTSC//////AQDyBSoBAAAAIyEDa7ISIXjuDKz+uNL5/TL3KYXhTFXj2qfjr02EURWSut2sAAAAAA==
Block: 258
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDFKSk0C1gAGL1AyU0gv/////wEA8gUqAQAAACMhA/VtPpHLdmU8spftyBYtXH857a+QxbZ/5G3YSxObE+lhrAAAAAA=
Block: 259
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDdKSk0BAQYvUDJTSC//////AQDyBSoBAAAAIyEChiMwbDSEP/9mZGdOsFD4JM/8Vhhu8zcqulQnDwtEhQKsAAAAAA==
Block: 260
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEhKSk0BDQYvUDJTSC//////AQDyBSoBAAAAIyECKsh+x8WJnVho7hFgccsYTtUwz0slkPW7SKfrY3QC0FysAAAAAA==
Block: 261
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEtKSk0BAgYvUDJTSC//////AQDyBSoBAAAAIyEDTn70G2FwjOklF1WM+0/h6OHxm6gEkcgB1gXdJ+wxo0CsAAAAAA==
Block: 262
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHxKSk0BLQYvUDJTSC//////AQDyBSoBAAAAIyEDypCWFxqTkpoIgRo1OgVBTuxOMkz4n0IODvsmMFEG2kSsAAAAAA==
Block: 263
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBAJLSk0CgwAGL1AyU0gv/////wEA8gUqAQAAACMhA7Zo5osQ9NKd6UJNOmEqvjmveXdSUeIUkQHv7qSlQ6HVrAAAAAA=
Block: 264
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDZLSk0BMgYvUDJTSC//////AQDyBSoBAAAAIyEDfIBMO0DZ7ILWnWPjgPsbCXd2iCFmDhdnCL9+17M2bcusAAAAAA==
Block: 265
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKRLSk0BagYvUDJTSC//////AQDyBSoBAAAAIyECAMcAWmPnFWdAjyLXES99MTnr6TbIp9rkinzUOV0b04esAAAAAA==
Block: 266
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJ9NSk0C+AEGL1AyU0gv/////wEA8gUqAQAAACMhAtK3cpic/viQVF/p4GRN7ZuuFbmka41cnYUgfhae21zLrAAAAAA=
Block: 267
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOZNSk0BRAYvUDJTSC//////AQDyBSoBAAAAIyECHZsSLy6OzVh6BTL+lnMJdJUFg/y+lNn1gQdFlQIu5iCsAAAAAA==
Block: 268
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPZNSk0BDAYvUDJTSC//////AQDyBSoBAAAAIyECR26G1B7pkR0TbXpUbz0JJ3gA+J4ijsBy72VgfDV/xyysAAAAAA==
Block: 269
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBVOSk0BGwYvUDJTSC//////AQDyBSoBAAAAIyECuBY3aJnhxeMerlYihgEGBGF9vCfoypFS7Z1Xjm9P6I6sAAAAAA==
Block: 270
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPdOSk0C3gAGL1AyU0gv/////wEA8gUqAQAAACMhApd8Sk/3u6WL5vWSHaDvg3UUaZ604WHJfqODwT7TyA+QrAAAAAA=
Block: 271
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDNPSk0BNwYvUDJTSC//////AQDyBSoBAAAAIyEDnBENVP9DDw7ClCIT+HHnwbXsUqh9MJ0TupDZ8rDdBoOsAAAAAA==
Block: 272
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBERQSk0CDQEGL1AyU0gv/////wEA8gUqAQAAACMhA7GPp0LHwkqy4FBy0SgDqXYhTiWEsCWs7GNqKgM1iYRPrAAAAAA=
Block: 273
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFdQSk0BEwYvUDJTSC//////AQDyBSoBAAAAIyECt+vOKLtL9wKpEUjVVVWrSsQ99sgx/YqV+8/CkUiY9HqsAAAAAA==
Block: 274
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIlQSk0BLwYvUDJTSC//////AQDyBSoBAAAAIyECs2+OzzEBWMfTShnFaTJnjEVCXava4psybbPWVrovnDqsAAAAAA==
Block: 275
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBI1QSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyECTZvPfgwKuXVlOrX5UJ54Mpxb4uVzFgSN7HYolgaJbMWsAAAAAA==
Block: 276
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKZQSk0BFwYvUDJTSC//////AQDyBSoBAAAAIyEDU498ZAACzeVS1BhC1r6RWvBYcBlbiq9lLkteirNrzQisAAAAAA==
Block: 277
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBHJRSk0CxwAGL1AyU0gv/////wEA8gUqAQAAACMhA/RFf4WMmTOKzPGcvMS3CZmOYRCCC+fZzAFrhrULAvuPrAAAAAA=
Block: 278
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBAtSSk0ClwAGL1AyU0gv/////wEA8gUqAQAAACMhAn4j+GKryGb9RE6dVgrP62b6Nq6hK3rEjZ+ZmLvWwOsNrAAAAAA=
Block: 279
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKBSSk0CkwAGL1AyU0gv/////wEA8gUqAQAAACMhAu76Jj0FzhyaSUZQlcV3LuFbz1pOz1IfyvdlM4Oos8yHrAAAAAA=
Block: 280
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBFlTSk0CtQAGL1AyU0gv/////wEA8gUqAQAAACMhAs1FOotXlgkLRDgWQU/yi/aE0U8U/zQpR6PbM6pu0q4hrAAAAAA=
Block: 281
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBLBUSk0CUQEGL1AyU0gv/////wEA8gUqAQAAACMhAkdpln3V9AtTGVHXI7VTPBdGiI9Rnb/wO28AHp//mHFnrAAAAAA=
Block: 282
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM5USk0BGQYvUDJTSC//////AQDyBSoBAAAAIyEDRMzrgAFXp9wnzwC8uCQqwgnar1WobSiC9WzGZNzfXVasAAAAAA==
Block: 283
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBG9VSk0CngAGL1AyU0gv/////wEA8gUqAQAAACMhA3j5R+g938N7rDkoun/hCAMimKYCp+86cJn/7z13BjXWrAAAAAA=
Block: 284
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBFpWSk0C5gAGL1AyU0gv/////wEA8gUqAQAAACMhAgjV9Yp7qlyyUjp5/dIb2fmwXBp7gClhYOOpnlKCdQHSrAAAAAA=
Block: 285
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBLlWSk0BXQYvUDJTSC//////AQDyBSoBAAAAIyECcSk5hCxpm5aMlEGVoaA9RywmsnNHrssmAsRGksFNnT2sAAAAAA==
Block: 286
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMRWSk0BBwYvUDJTSC//////AQDyBSoBAAAAIyECv7BfnETqQMg9qkxrz2QfCbDysKg25BOhNICvsMqjw1ysAAAAAA==
Block: 287
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBP5WSk0BNwYvUDJTSC//////AQDyBSoBAAAAIyED4HbHp25RfjeF4/IL8+qUbozO7SV8OKJ4XkJ2OZmx+9usAAAAAA==
Block: 288
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBGRYSk0CYgEGL1AyU0gv/////wEA8gUqAQAAACMhAtEEIYRvVcin+cG9/gPyEcuYrmfYMyuHqS3SzgnHr5ddrAAAAAA=
Block: 289
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBN5YSk0BdwYvUDJTSC//////AQDyBSoBAAAAIyEC05rigcMpbb2gI6UjOmpb/88BwcYraM/jY2DxyM3FJmesAAAAAA==
Block: 290
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPxYSk0BGQYvUDJTSC//////AQDyBSoBAAAAIyECYiGYIUzxQ9c4YeyROSxocG03qkh20EfIbzSHcErfvZ2sAAAAAA==
Block: 291
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBA9ZSk0BEQYvUDJTSC//////AQDyBSoBAAAAIyECjyOgf/1GIcunyn0Cfe3RSX+sTQvyqAi7qJY2IPQ3bgqsAAAAAA==
Block: 292
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHRZSk0BYgYvUDJTSC//////AQDyBSoBAAAAIyEC0V1OVIMreuaIkQHBRjxouu1+JiPFsRewlyid9DhqlC2sAAAAAA==
Block: 293
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBPhaSk0CfgEGL1AyU0gv/////wEA8gUqAQAAACMhAxu9yrpjkeru+WGSNSNnYZsFVyczB75DrMuFS0O1yfCjrAAAAAA=
Block: 294
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBM1bSk0C0gAGL1AyU0gv/////wEA8gUqAQAAACMhA0YYJPx+9uCN8vVD4mM5yy4P1OuyBMGfQWXC3hHWShEprAAAAAA=
Block: 295
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBM9cSk0C/wAGL1AyU0gv/////wEA8gUqAQAAACMhAsPL3L0C3ePoQz3QeR49kSGk172zGa8GOtvgXF3j8AsLrAAAAAA=
Block: 296
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEhdSk0BdgYvUDJTSC//////AQDyBSoBAAAAIyECGX/6hW/UpcmWJHDxEiKvpWKpxfMAM0UaWGEZX90iA96sAAAAAA==
Block: 297
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHddSk0BLgYvUDJTSC//////AQDyBSoBAAAAIyEDDkC6bD0vBFNhdHlq71Fra3jvriynTUE+Tf8VCLYcE4ysAAAAAA==
Block: 298
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMBdSk0BRgYvUDJTSC//////AQDyBSoBAAAAIyECV+oP9slNLFb1OX8bo+r1BWGUuIA1T7cz+9WfbiDfyQCsAAAAAA==
Block: 299
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMtdSk0BCQYvUDJTSC//////AQDyBSoBAAAAIyECT/h+SGj1AvaJDPeLhBajxkANRuZel1P/8lBAXGHmxB2sAAAAAA==
Block: 300
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCNeSk0BVwYvUDJTSC//////AQDyBSoBAAAAIyECUDdwpPmbGWv7WSTQzccC+ZGKRZMQMw9ueAQebmL/Fm6sAAAAAA==
Block: 301
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDVeSk0BDgYvUDJTSC//////AQDyBSoBAAAAIyEDShd/ShSrI5j25YHL6AdMyynwXwPLE7RA3zih+25NfPSsAAAAAA==
Block: 302
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKteSk0BcwYvUDJTSC//////AQDyBSoBAAAAIyEDm5d0lWNxKRpg4haXTbnqyGGh4TkM6vqhwN5cKO9uET2sAAAAAA==
Block: 303
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJ5gSk0C7gEGL1AyU0gv/////wEA8gUqAQAAACMhAxNe3FaWa8OEIOs7vES7Q1oobsGXPC+ZdrkgxtAxIxCGrAAAAAA=
Block: 304
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBI5hSk0C7wAGL1AyU0gv/////wEA8gUqAQAAACMhAiND40HQsVyLEQ9MBsuL2VRt2j781ePe+RlnqwIjCn3HrAAAAAA=
Block: 305
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNlhSk0BRQYvUDJTSC//////AQDyBSoBAAAAIyECskvdq1owUIMtUU0/wCJxztKXIn+SEb9h0o9tmH8Dbk2sAAAAAA==
Block: 306
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBpiSk0BPQYvUDJTSC//////AQDyBSoBAAAAIyECiHXTU2Qrp89KYrw5yarUE55ZxOgJK5p4QOC7f3Li5jWsAAAAAA==
Block: 307
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBHNjSk0CVgEGL1AyU0gv/////wEA8gUqAQAAACMhA+bmB9+1FT/JHTSR0DXe9L5qTZMUGMkeCyAqvAh9x33GrAAAAAA=
Block: 308
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMZjSk0BTgYvUDJTSC//////AQDyBSoBAAAAIyED04A+WhT5nJIlRChBs3K3PqoDj3GKt6Xs2ib+bI0EQlasAAAAAA==
Block: 309
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDZlSk0CawEGL1AyU0gv/////wEA8gUqAQAAACMhA9sulRR4GAhwIIoWySbA7Dv8JiHu3R25D1UuAZgUdmnBrAAAAAA=
Block: 310
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDtlSk0BAwYvUDJTSC//////AQDyBSoBAAAAIyECRAZ0utIh6PixGzYmncAGio8s9Er18UDGf8YOrr9qkC+sAAAAAA==
Block: 311
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBMBlSk0CgwAGL1AyU0gv/////wEA8gUqAQAAACMhAp2lvs7yS4KPZo+Rzl3O5r2U8zxJqx9BAe4RNWejmdmRrAAAAAA=
Block: 312
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBChoSk0CYwIGL1AyU0gv/////wEA8gUqAQAAACMhApggy0FpE/aiEX61RBVgGj/jLyb+aEJkkApHWkP8SjlNrAAAAAA=
Block: 313
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDBoSk0BBQYvUDJTSC//////AQDyBSoBAAAAIyEC1RZXAXheb0vne7pyxo0wJ+6gdMp8KrGy1ogtsA90N5GsAAAAAA==
Block: 314
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDloSk0BBwYvUDJTSC//////AQDyBSoBAAAAIyEDu6E6EXgrPYWgrmSNq2HKl3o8Huo6YETBMtmnEkv4jh+sAAAAAA==
Block: 315
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKJoSk0BZwYvUDJTSC//////AQDyBSoBAAAAIyECn0ZcxFfxFSVd1QxxYiQy+4Xr4WgsyIV+bOGMSNJoxLOsAAAAAA==
Block: 316
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBK1oSk0BCQYvUDJTSC//////AQDyBSoBAAAAIyECDR8TNLIw3DOojCFg18iSDPPyHd5Hr0dY4xZU/AbTpCusAAAAAA==
Block: 317
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBD1pSk0CiQAGL1AyU0gv/////wEA8gUqAQAAACMhAx/cpRd4jHhU40CZ3Tt09V6NV6fRnY6oops5AaK9hFkHrAAAAAA=
Block: 318
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBExpSk0BDgYvUDJTSC//////AQDyBSoBAAAAIyEDWz3ypJACXosV1QLe/I8ajC08ezpMgRdpPO4RCyt0oP+sAAAAAA==
Block: 319
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMRpSk0BdwYvUDJTSC//////AQDyBSoBAAAAIyEDEQInMLJ9QQ6q+X9sFucLwJ22KlvRzbpgCcd0bRFvMdasAAAAAA==
Block: 320
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPJpSk0BKgYvUDJTSC//////AQDyBSoBAAAAIyEDzDSFi5e6rt2VKVQUkHqaUJtMy4mH3KJzocE3/EqmW9msAAAAAA==
Block: 321
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBLVqSk0CwQAGL1AyU0gv/////wEA8gUqAQAAACMhA1wQCXL/jFctyA6qFalYq5kGTXxrnlXw5kCN7BHt1N67rAAAAAA=
Block: 322
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPdqSk0BPQYvUDJTSC//////AQDyBSoBAAAAIyECYcgeGzWMxdkmN3wHj3FqGdiqCZ/s1gvDeaiJl6GW/m+sAAAAAA==
Block: 323
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBANsSk0CCwEGL1AyU0gv/////wEA8gUqAQAAACMhArOwhWKN7fNEsylQYOs9FrELB8SbVvlhYfyWK1AIUYPyrAAAAAA=
Block: 324
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBA1sSk0BBQYvUDJTSC//////AQDyBSoBAAAAIyED6SIqWnTyJt0LeaMotEXe1vnDoifwcnOYzQ3GYPtKBbSsAAAAAA==
Block: 325
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBZsSk0BBQYvUDJTSC//////AQDyBSoBAAAAIyECW7o6ef/zh8wZx+wqvW+PGW49b2dGgXC3Olhnx8pUaWusAAAAAA==
Block: 326
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBHdsSk0BXgYvUDJTSC//////AQDyBSoBAAAAIyEC54WZrmPKmTwjRDgZxaPojONpKtkTfLE1MDfDfNR7So+sAAAAAA==
Block: 327
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBI5sSk0BFQYvUDJTSC//////AQDyBSoBAAAAIyEDjSNUWZW6G78p6QlDKas3EGrj5TtxwcWmCpdLrLQ78CSsAAAAAA==
Block: 328
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJ9sSk0BEQYvUDJTSC//////AQDyBSoBAAAAIyEDzm4l+afXBIHj0t8M3TF9aBPC0y2yb2ShJrweti1oJ8GsAAAAAA==
Block: 329
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBCxtSk0CiQAGL1AyU0gv/////wEA8gUqAQAAACMhAq+s961cy+5zZRwWiP64GdvmGWaCNG57f8agT/pQs78OrAAAAAA=
Block: 330
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJNtSk0BYQYvUDJTSC//////AQDyBSoBAAAAIyECeYMamvcTAjuxTSHsVdyGrWsBE+DREQ5pcDlZFwbdJOSsAAAAAA==
Block: 331
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM1tSk0BNQYvUDJTSC//////AQDyBSoBAAAAIyEDd/5YWLMVLlnl0XfU8rV5PwVj48yLh1H0H+xLZX1pTESsAAAAAA==
Block: 332
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOltSk0BGwYvUDJTSC//////AQDyBSoBAAAAIyEDE9MeitjuD8RJO44P/dQhK8nRfb4w+WbPJQBn3TuQbyesAAAAAA==
Block: 333
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBG5uSk0ChAAGL1AyU0gv/////wEA8gUqAQAAACMhA7TFGsk9cOJsjGgjkZUqCZ1InChkARUKbSqHyGXzb8WHrAAAAAA=
Block: 334
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBAlvSk0ClwAGL1AyU0gv/////wEA8gUqAQAAACMhAgkQvHJqWPZWjZhL3O8FWochVbyoXZvKo8mRAAlsubADrAAAAAA=
Block: 335
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBGtvSk0BXQYvUDJTSC//////AQDyBSoBAAAAIyEDToi/gEVC+9ATssGR+xe8TrEGe7xT087HDfTpEaFQ4JOsAAAAAA==
Block: 336
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBL9vSk0BTgYvUDJTSC//////AQDyBSoBAAAAIyEDpcbNO3Den8ygi53GyDQNLhsM0AFsemnf+q5+f1SZ3TGsAAAAAA==
Block: 337
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMRvSk0BAQYvUDJTSC//////AQDyBSoBAAAAIyEDjTbrEyBGn55+QMdhMTW0ALOjMiBxJVdTv7O8vjz0PbKsAAAAAA==
Block: 338
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNxvSk0BFgYvUDJTSC//////AQDyBSoBAAAAIyECv++suofydbTR2BshSi4TFSv9weOt3ziWGZSuXgyzsEesAAAAAA==
Block: 339
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBLZwSk0C1gAGL1AyU0gv/////wEA8gUqAQAAACMhA7QLYU686ntrf/wH45PCQjghwcPS0KP7GuUWIrqCcE+lrAAAAAA=
Block: 340
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBMFwSk0BCwYvUDJTSC//////AQDyBSoBAAAAIyEDqkfWcPmElLwGnloEQGeiJaKbvS1ttNJcSJsrwc4t9FisAAAAAA==
Block: 341
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBEJxSk0BfAYvUDJTSC//////AQDyBSoBAAAAIyECnfOs+lLcdqrdzKNb7tGW6n++dVtSQ/Uz6mTcWZwsHhGsAAAAAA==
Block: 342
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBM1ySk0ChwEGL1AyU0gv/////wEA8gUqAQAAACMhAj0hDV0TQPXA4+ZuWecJc39kBtnueq0mwtFSnezLLUv+rAAAAAA=
Block: 343
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBH5zSk0CrgAGL1AyU0gv/////wEA8gUqAQAAACMhAtgsz0IPBasVvf73ZzDk/OUgRonWeLSaOTCswNvd48zdrAAAAAA=
Block: 344
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAB0Sk0BfQYvUDJTSC//////AQDyBSoBAAAAIyECcEHP7r1zbYuawJrt6no2y8N8tnUk9Mib+I/26ZgMoAmsAAAAAA==
Block: 345
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBR0Sk0BEgYvUDJTSC//////AQDyBSoBAAAAIyECAfxLln08efJ1y0XyGJRaEiNLIUELSr/LQk2DOL63wDCsAAAAAA==
Block: 346
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDl0Sk0BIQYvUDJTSC//////AQDyBSoBAAAAIyEDViUFv+39ptdQjCVo0V3s5b1sna+2UM37QPdSQEGR+KKsAAAAAA==
Block: 347
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNx0Sk0CnwAGL1AyU0gv/////wEA8gUqAQAAACMhA7W6nNXsPLrQGlqXYLjbrH4QA7Yew5XzfwgmmJ3++u0wrAAAAAA=
Block: 348
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBOJ0Sk0BAgYvUDJTSC//////AQDyBSoBAAAAIyEDjWYOqswb4F95Qu4QnQD73TpcFfXYuTI5UHMx8qONuY+sAAAAAA==
Block: 349
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKJ1Sk0CuwAGL1AyU0gv/////wEA8gUqAQAAACMhAvUBO2CyHCfprywohcYCrObMWDjWh4iGylfRt42/1Ke2rAAAAAA=
Block: 350
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNB1Sk0BKgYvUDJTSC//////AQDyBSoBAAAAIyEDY8Id8oMz8KkrFlWs2zYsO5n/HftyDzj3GKHxJ9V9CiisAAAAAA==
Block: 351
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPt1Sk0BJwYvUDJTSC//////AQDyBSoBAAAAIyECpw3MG+iKsTO2dOw/kPpg2bYgLtbrx+NRY3tAjb+cTVasAAAAAA==
Block: 352
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBP91Sk0BAwYvUDJTSC//////AQDyBSoBAAAAIyEDJcoHYbHrsuX1EfRdUswfmhHkLNFPDIkdzadoUN7QPEqsAAAAAA==
Block: 353
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBH12Sk0BewYvUDJTSC//////AQDyBSoBAAAAIyEDHumdK3hqs7CZEyXy3oSJJGpqP9twD20FEbHYDPX0zUOsAAAAAA==
Block: 354
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJp2Sk0BGwYvUDJTSC//////AQDyBSoBAAAAIyEDHqOre8xHkf6rEaOlIqsM4UBRkFatZaXfGW/BGLvg9CusAAAAAA==
Block: 355
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBCp3Sk0CjQAGL1AyU0gv/////wEA8gUqAQAAACMhAoKaYUbtTnM73y3uxNDqKy2EjGcfb32Ucwh9Md77ea1crAAAAAA=
Block: 356
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBF93Sk0BMQYvUDJTSC//////AQDyBSoBAAAAIyEDBIr7jOb7aJ0a/iUHTn7M+cx5guxmfURqOuKR91Hfm5OsAAAAAA==
Block: 357
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBAR4Sk0CoQAGL1AyU0gv/////wEA8gUqAQAAACMhAtnHD4P5OuLMEOMkwaIhv/0BZgFPVfwHf+doYzMyMdTbrAAAAAA=
Block: 358
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBLl4Sk0CtAAGL1AyU0gv/////wEA8gUqAQAAACMhA0dcBAU1zrAGZtQrALMpjf60ui9Aio1qm+lL9lzAHraVrAAAAAA=
Block: 359
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDR5Sk0BdwYvUDJTSC//////AQDyBSoBAAAAIyECu2AGwvBdGHsRUnGxV3tYL18ftxBRiUhHSPiZ31qmXcWsAAAAAA==
Block: 360
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDh5Sk0BAQYvUDJTSC//////AQDyBSoBAAAAIyECdJAbBaGTd0AVUcdVxiIt31Liw14t1rADGJpqXUlSbvysAAAAAA==
Block: 361
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBGh7Sk0CKwIGL1AyU0gv/////wEA8gUqAQAAACMhA9D5EgGSNwefKx9VG7GdxvuZGSqjQoPzZM2jAI23Yo1YrAAAAAA=
Block: 362
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBBN8Sk0CpQAGL1AyU0gv/////wEA8gUqAQAAACMhAxGnoExVuiond8iy2n41H7oZmGcEX6VQWZz+3O0c9cXprAAAAAA=
Block: 363
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKV8Sk0CjQAGL1AyU0gv/////wEA8gUqAQAAACMhAky76WsHdHTJbAkvnuv71R2saHBNel6F+sWbfPnJ+TyKrAAAAAA=
Block: 364
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBKh8Sk0BAQYvUDJTSC//////AQDyBSoBAAAAIyECwZ+K9C9cBS1I97OKfXeQJ5tvV2pyVJBYOT928W8+IKesAAAAAA==
Block: 365
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNF8Sk0BJQYvUDJTSC//////AQDyBSoBAAAAIyEDPW+87EPmSI5uMg5P8lfuj1SXRMdSzCHcu3EnOKEaTh2sAAAAAA==
Block: 366
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBN98Sk0BCgYvUDJTSC//////AQDyBSoBAAAAIyECmpEQKEnlGICR+RkxXGObpraJYmDOMJRTixqGZnZYADmsAAAAAA==
Block: 367
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPx8Sk0BGwYvUDJTSC//////AQDyBSoBAAAAIyECLTqckuVJ7uIQT0VfNhCToauL6WpF8Ou/lrtUqn/k1+KsAAAAAA==
Block: 368
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBJt9Sk0CmgAGL1AyU0gv/////wEA8gUqAQAAACMhAxyoEW56li5Lxiceziox0uHpnsRqAMLMJFxCOLte8oCBrAAAAAA=
Block: 369
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNR9Sk0BNQYvUDJTSC//////AQDyBSoBAAAAIyECsCKD2KHnlrbyu6WUGTT4JIEZZvQMv9PmvEbRwSoD4DCsAAAAAA==
Block: 370
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBMp+Sk0C8gAGL1AyU0gv/////wEA8gUqAQAAACMhAoIdJ/fOa8RZvWU7iU/aGUaiOrQCMgKT5ZMJb2Vjk6SbrAAAAAA=
Block: 371
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNJ+Sk0BAgYvUDJTSC//////AQDyBSoBAAAAIyEDMXygp4z7PzMk9L7OEaGTetj4XOyHhWB29UHISJMqUIKsAAAAAA==
Block: 372
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBP9+Sk0BKQYvUDJTSC//////AQDyBSoBAAAAIyEDVX1IbruQG/FSHMZBck9prAvpQODDfxT75baRcm5iw2KsAAAAAA==
Block: 373
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBB/Sk0BDgYvUDJTSC//////AQDyBSoBAAAAIyED7q6wlz4R1zS4FOXOMyh4RLvVCAQ8AldHstZlA6PlZe+sAAAAAA==
Block: 374
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBN5/Sk0CywAGL1AyU0gv/////wEA8gUqAQAAACMhAu5RJpSItwynYmPLEtbLfLzyCaG8cyfnEx8VTm4LOk+brAAAAAA=
Block: 375
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBO9/Sk0BDQYvUDJTSC//////AQDyBSoBAAAAIyEDH/sHLBmnyAmHAmSlPZLUclfVIzBOl1ZgxCXL6yX14MesAAAAAA==
Block: 376
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBG6ASk0BeQYvUDJTSC//////AQDyBSoBAAAAIyEC5GhzlVJNLsDjLR/rP04KbenNO/6fkglYm+N1Wuo4LwisAAAAAA==
Block: 377
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBDaBSk0CxwAGL1AyU0gv/////wEA8gUqAQAAACMhA/kTeZISeowcv6IKrLBhWHjeB2wqtRN4gvvHh8CmHR+trAAAAAA=
Block: 378
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBCuCSk0C7wAGL1AyU0gv/////wEA8gUqAQAAACMhA9/eKmncdXdW9oiyDggTgYtgoZarW7FmkalS/WmZTHnprAAAAAA=
Block: 379
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBMqCSk0CmQAGL1AyU0gv/////wEA8gUqAQAAACMhA+zqQs/smSu3+uNnC6Wfr3epSEQDCasZgNQ221DSkdYvrAAAAAA=
Block: 380
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNKCSk0BBgYvUDJTSC//////AQDyBSoBAAAAIyEDlg7ykxqE16PC4P4V7m7mW+KY7t61w2tV1aq/4EyVrdSsAAAAAA==
Block: 381
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
Block: 382
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBJSDSk0BIgYvUDJTSC//////AQDyBSoBAAAAIyECyQc/AvZwyrHTCiSHE7OVE3hiXYaMb6HcDqixfIzW5AusAAAAAA==
Block: 383
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBNiDSk0BPwYvUDJTSC//////AQDyBSoBAAAAIyEC76d0dqCFNEIwEJdooWxlngL6mw6wnOzB3G/MzEq8qAmsAAAAAA==
AQAAAAJDTSsPKYh0w/bYRnwH3qaIOmUN4A1IKYzW+0joMi4QWAAAAABIRzBEAiAr8Xh4YIOG+y576Bs5z26mLrlAc/tSCVdA3AoYdZ6eOAIgPmpvra1X7KfblGuLSMBoyHx6m68HXlsomUEWwrMSa6oB/////+c5F21itYhWavpH9fu8DsAao/BYwDbKDujzzRPkIj4BAAAAAElIMEUCIQCiUWkgI7wj6Ls2yBHmgQoCSA/shxmxAnBLCnlimmuvmwIgJpQT7kHtd56+dMGlQKwc0knzs823gDNzP1cirD63EToB/////wJAT8PtAAAAABl2qRSyIFpNvB1YfF0Hdpl3lisXPqtQdoiswJRIZgEAAAAXqRRB+2UE+LyyggZZYYT9QKXtQrzlPYcAAAAA
AQAAAAJsfZDmPcVCGCJ1ODFlyl7mkUVv029WqDmwSocC6x5ifgAAAABsSTBGAiEAl0A6zPd6BxFwZo+o+MJIyjIeDRBNW3IC3DXAoWh67MACIQC4o5tDaAYqIV7qU/+lm3dRIIEiYwZ3SNPge1XCDegKWQEhApcd1yLs7nu8PNvIxqc2XbdBErbsQTarPVdzS9gNeEHf/////6ru+FspdiLs8xHcXSlmn9TjhjRUxv7qNh7OT1R7pS5qAAAAAEhHMEQCIGQTIa3I+y5klSwSm2zDINek016Q8pokSLGPrELPIZXDAiAeLkfySMQvKc2L0/DtY9eXCYud5hIc57VEkDZfxXNcjgH/////AoBAtigBAAAAGXapFLyfR0jI5kmy0HcomI7spk3zCtfjiKzAyq0qAQAAABepFCkLujKkkxV4mgMLtAsAR/j7kP9mhwAAAAA=
Block: 384
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBHGESk0CjgAGL1AyU0gv/////wEA8gUqAQAAACMhAjEGa4bqDL3auhqvd6WOXyPzubyhsKYufOFrPP0fx2yXrAAAAAA=
AQAAAAKONDBXPP3i8+Huzorv5mHdhBvLZl01gyQVurT3UmeFIgAAAABJSDBFAiEAnMqPscSjSYLE6aWf0VhWQEwCCF+SYEPPxmZJJKW5420CIFgR+Fs5XENJIWS4szhn10UhHYx//c0bKI5W9029rtFbAf/////jq/WYGhvWRX7Azcq3bMKhdtwNfhb203ga68aE8TzE/QAAAABIRzBEAiA4e7zumeNw6iEV6sz9jEjrOAZTMDtmxpRuCQP7C7xvhgIgKy7wSFGdRVJUE/ZLcnodhf8s99katGBzCCJLTDDVhGgB/////wJA8fI6AAAAABl2qRQiA8pZ7fZpaXV+bMkjixs29Nw1uIiswPIYGQIAAAAXqRSeshmA3J1BPY6sJzFJOLnakg7lPocAAAAA
AQAAAAJzosVNU2wZ8NCRVu+60Yym+WsenzvISQNClY8k7Y/DLQAAAABJSDBFAiBMhuLgS149dvF38s3XyBcLJctyfM8cmxTOkmK2vGfp0QIhAPp2suH3JfxZ+04h48HWZ40QgcHt04ESfQJjzRuypfBTAf/////oBzpcCoD5jhX8Auz9GV1ioEUEKyc8ZVyLNg9mYOjnIgAAAABrSDBFAiAtloB14eFcqB/nJUQNxjV+AgMBlyXDygW3fL04vMVdBwIhAMZAhqcGKbMHV4U1XYtcVXdyvsnG/JZiNfkwUw0ympNkASECOZ3dTkuqwZZe/E2IJlbySGa+FM9bz2QiIzTx/dWSBIH/////AoDi5XUAAAAAGXapFHzHj+QlGySumyOjmeIWCHnxiDNiiKzAXuOhAQAAABepFONxeCWCpK3bVBNixVVl0s31b2SYhwAAAAA=
AQAAAAKjDj8UKb8qjtFMpuyfM5a4WTuLtqweTTW9Q18FBYCU6gAAAABIRzBEAiATvXKkQqFB1YzKA4QXAM1WETClMNONxQymJ4EMqf6DbQIgZpBxlR1C+pCwJjN1I+H/PKQvojKsHUp3ZpLoXXBjjJYB/////yQ1aPL/a/kDhqTXV20jzZIqgpx9mK0SUdeNnlGk32HyAAAAAGpHMEQCIGom075AfeA/vSILSItlgz4/T7VRZM1a69VJr4UGADTVAiAjOn1iq3gqJGfXl+IHbwQ/lgzkqx9gfCkiuxRlhPyrZQEhAsukzpMrON2dpTZox4fT/D0ks37RFtlrQsWIWFqGWf1W/////wLACT51AAAAABl2qRS0Qdm9GwTXUvkfFNxk7Xx7eu4TT4iswCh+3QEAAAAXqRQJ9wuJYWnDeYHStUs3HfDYGhNqLIcAAAAA
Block: 385
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBCOJSk0BYQYvUDJTSC//////AaB4ByoBAAAAIyEDumW4wKCi0CnkzevDkYheRm5ly9+odjj4tkYNDSvo1aKsAAAAAA==
AQAAAAMozhDHGJAmhmvPwdBrJ4mB3fIewONk4o4pQ2W1wyjNQwEAAAD9RgEASTBGAiEAp48YD1hR6+nefmrm+I7PNu2fFl5d8eF+7BayLmOX3AsCIQDDrohAApSuRkZl1juANfHeS7Gd3XzAzFwdWj/ij0/K5wFHMEQCIG8DXOQ2+jBwOL9LrBWouX+ts8gJttkonq594ND51SexAiAmU01pW+LXrb69pdLEze6D4nAV7tMqX/lQ7PE2oduFdgFHMEQCIBoKasD0iOfcj8fJrKXXm1QdYNetGq9h9V7lfmH/LatKAiACZ7/M5SeBDXr1SjDr+wztNxqiS/d5HuckdMX/VwPTUgFMaVMhAsoqgQqxckm2AzoDjeVjmDiBtAaScBg/PAq6lFZT5EIWIQP0gPG2SNDVFngErU1Ybg51fMM/3g4TP9A25F1g0ttZ4SEDwYEx2N6Z1F+3KndMqwzMJYzSq9lgVhDaILmiMsiKPLZTrv////964AGu9Wb4Jzp80U3LwdK815J955LFBCN1AzmR71UjwwEAAAD9/gAASDBFAiEAtI8WWuCTGlQKXSFR6pQIpVESLbrge6T+JrLYQNiBKuACIHzIc0bC3qOtKHOVF20VqWOWFB+xsb2qu6nb80ZQb2AVAUgwRQIgJvLblShumDHC78YMKmXD5JKKX6nwRVYVQPaJ2N6FYiECIQCuzXd+F7B+7wRtQARtoLkPzqhpOLIUeasO8NFYq4Y53AFMaVIhAsoqgQqxckm2AzoDjeVjmDiBtAaScBg/PAq6lFZT5EIWIQP0gPG2SNDVFngErU1Ybg51fMM/3g4TP9A25F1g0ttZ4SEDwYEx2N6Z1F+3KndMqwzMJYzSq9lgVhDaILmiMsiKPLZTrv////+lG+N67kx28jRhFo7m2C26BxgbMYOQYluayy7CvhAEugEAAADcAEgwRQIhAOSi6NuNAg/BXsg5YYIPAhvO3HSAdeW0mF7r+gBt7BTsAiAW6lFGG+rILHrvBZqDWQFShmcpY/pXH8P5hJfuMwOzdAFJMEYCIQCObY1WDjvY6uKvYukM00OdgPaOTEUyfBbZikRcj/lBqgIhANOb7g//ImwmQEcmTbtCG/N4NiyJML9EY7sJ7xtP34pyAUdSIQLKKoEKsXJJtgM6A43lY5g4gbQGknAYPzwKupRWU+RCFiED9IDxtkjQ1RZ4BK1NWG4OdXzDP94OEz/QNuRdYNLbWeFSrv////8FwMqtKgEAAAAXqRQdnKce+jbYFEJOpsoUN+Zyh66+NIfAlEhmAQAAABepFCT7x3zcYnAq3nTc+YnBXl0/kkC8h8Be46EBAAAAF6kUr7+3TumUx9RfZphzi8QibQZSZveHYEOZOwAAAAAZdqkU0qN84grJ7E8V3QWnxujp+9uZhQ6IrADyBSoBAAAAGXapFGsgRBRqRDjm5b+8ZfFHr+tk0U+7iKwAAAAA
Block: 386
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDKJSk0BCgYvUDJTSC//////AQDyBSoBAAAAIyEDeTdOC2CP5ahK99R/fs1AWCY1BuzhE4oiDZ/tLY00/x+sAAAAAA==
Block: 387
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
Block: 388
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBKGLSk0CHQEGL1AyU0gv/////wEA8gUqAQAAACMhAwX9IJKSmlcapcG4YDQm05VDWbbhumnE3UuFJurVG6j/rAAAAAA=
AQAAAAFsfZDmPcVCGCJ1ODFlyl7mkUVv029WqDmwSocC6x5ifgEAAABrSDBFAiEA2eqQkvC+WlQ3MHYZM3373Scyzz8j+Zd/tDW0pbS/RmgCIAw33THNfTjV9LmgDHUekFk1b+8O1OiPUqdbTnx0PzRNASECyiqBCrFySbYDOgON5WOYOIG0BpJwGD88CrqUVlPkQhb/////AsDOGB8WAAAAGXapFCOVLLskny8m3VZ8LoNF14XGNUN+iKwA8gUqAQAAABl2qRQyBAF4xc+ByyAKuZrxEx8Yd0W1FYisAAAAAA==
AQAAAAEkNWjy/2v5A4ak11dtI82SKoKcfZitElHXjZ5RpN9h8gEAAABwAEgwRQIhAOmPoLEPUZJMoLIdyy8enTg7ZSzi9RkWyu7x5H0T/2ekAiAmy5/zI82unted3YKaDMG0nJN0wmKT9U2RnLbcX48K4gElUSECyiqBCrFySbYDOgON5WOYOIG0BpJwGD88CrqUVlPkQhZRrv////8CwNinAAAAAAAZdqkUSy0ZmkDUiL5v5TBaHUX0kFOvS/6IrADyBSoBAAAAGXapFGsgRBRqRDjm5b+8ZfFHr+tk0U+7iKwAAAAA
Block: 389
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBAuMSk0BZQYvUDJTSC//////AVC1BioBAAAAIyEDJGxAijhRNKm/X0EFXtwmUwawz0PM+8WvaeoSnQegJsmsAAAAAA==
AQAAAAJSJqjPEi4VVb4BqQCCGW1UhFTnPFG0i0G7IE7FOPIZ9QEAAACMSTBGAiEAuW4v0gFbs/4iwjxxLDrEqGNtSnjffWabq9ZOq6MUwjYCIQD0AtfjOS0XcM4r4Mgj6rASK7g+4L1l9d5Uof61PkUu7QFBBMS+5ebbtcFlFDfLQ4bBUVx3dsZFNQdyBMbyTwWjfQSjK8eL6yGTtTsQTJlUxEsM4Wi8eO/V8eHH251sIbMBZZn/////cRmMYXCfjZiDFfRfo/kWCnDwUlX72tDY+6yriJwASNcAAAAAa0gwRQIhAJLpb0GF/Bu3S02cJYIZ3F/8ca+0PnPsDni92RuvvjhuAiAZ/Fs9lgIAW2H13HXnvU3eHBmgcAwKeVhQNSgBTTkBkQEhAidOrgHTkbvsMtS2DiTV0k+cwjyo2mcIz2wGI4G/pxAG/////wEA8gUqAQAAABl2qRTb+JUJF2qXXkHQTMCvJM/I3kOUqYisAAAAAA==
Block: 390
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFmMSk0BSgYvUDJTSC//////AVC1BioBAAAAIyEDfDnB8DlD9eTbYyQ10IiEdqtdt+iuGlZQ79UD9qNfIXusAAAAAA==
AQAAAAboBzpcCoD5jhX8Auz9GV1ioEUEKyc8ZVyLNg9mYOjnIgEAAACSAEgwRQIhAJBBmeGlaJDYHZVXilP7vGU7cdJTv3r7amIwhMR/d2oiAiBLCE75DLf+MR9xDlFsEicgKLcHFnZ9oJKTjUE1kaobhwFHUSECyiqBCrFySbYDOgON5WOYOIG0BpJwGD88CrqUVlPkQhYhA/SA8bZI0NUWeAStTVhuDnV8wz/eDhM/0DbkXWDS21nhUq7/////cRmMYXCfjZiDFfRfo/kWCnDwUlX72tDY+6yriJwASNcBAAAA/UgBAEgwRQIhAKw06INxKPXAIAp3h4XdxMp4lNsgehkH6l8Hvg+qU3gHAiALmCUQrc2gBtRykbvnIMXsTxqmZl+ussn02o7Kgu2dSAFIMEUCIQC8Uuohl7lOF/B+vPq5rc8Ngog0SbkOG/FKc/VY3dToDgIgUkflx+QlIbxHuyHr83M5oGpBvQF4NK+EpHKPVegLxt0BSTBGAiEApsB3UUPvfleMYVn+Ln/0B1PZYiMLilAq0xqY82mnfLoCIQDgTVrBnqsoV8PEphIESZBCtZ3j01qvPjyNvws2yzvgHQFMaVMhAsoqgQqxckm2AzoDjeVjmDiBtAaScBg/PAq6lFZT5EIWIQP0gPG2SNDVFngErU1Ybg51fMM/3g4TP9A25F1g0ttZ4SEDwYEx2N6Z1F+3KndMqwzMJYzSq9lgVhDaILmiMsiKPLZTrv////+yyBJsy4LbegArWg61VwLSRQwVwpcxOUYPwsu8yK/XEwAAAABrSDBFAiBhi6lNXcCQCSQGyymONwRsC0dtDlKax/X/Z/HXZKJ81gIhAOl6XNOJyFP9l6HLVkpn9ka2xi1Y8H+2/MbxK+ksTOEAASEDEnxLvPb/FM/YU7+SF2lxMIy3shLaKORrKJ1ERMQhXlT/////ssgSbMuC23oAK1oOtVcC0kUMFcKXMTlGD8LLvMiv1xMBAAAAakcwRAIgARPiavSxwFKjCTfQpdu271OiaQMiwWa1c2soASiVUlECICoikRfdzJJoZBcygWBPfIfgoF4iaW5V4gXntkCti64hASECyiqBCrFySbYDOgON5WOYOIG0BpJwGD88CrqUVlPkQhb/////UiaozxIuFVW+AakAghltVIRU5zxRtItBuyBOxTjyGfUAAAAAa0gwRQIgB9HtDBH9oIsz6+c+OdWR27B2zo6Z8ZhPxlH60Yzol8cCIQDgtVEqPco7rZ4LEqPzsF487AA6rT0qNti+K4OhzoofWgEhAr/BmwSVNL5aaSq0IHiWiAfDuHu1DKR330rNKW4p5RVz/////7EkzKfpaGN1OAyEXQ/QAu1wSu9EcvTMGT/KSqGzQE2kAwAAAGpHMEQCIEnw8K/fx/3SDZ9lT+ozvSqcdZ3kkVnpgoDVMeXkyxWSAiAc2Vz/wIYiwy8Q3uzcvAbj1Uhjg9BfdDAXmjSJwKBkxAEhA4c2LbJ9I8veyiFmSLo7pRnVO3dqYDHPjucKh5ODqZ1x/////wLQ3QYAAAAAABl2qRR+my2sJ4obHRDml7wpo2A8Cy43pIisgHN9SB4AAAAZdqkU2/iVCRdql15B0EzAryTPyN5DlKmIrAAAAAA=
Block: 391
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBI+MSk0BMQYvUDJTSC//////AQDyBSoBAAAAIyEC9TSrbZ8/QJobDAd6MZORdK4GdzdThyfnkyXDILNNmn6sAAAAAA==
Block: 392
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBFKPSk0BOgYvUDJTSC//////AVC1BioBAAAAIyEDvoTLWezyb45BZ7zEyR3Us3sUS0mYCzmelEbXIY64AUesAAAAAA==
AQAAAAHOQV6rnLo1SuBCwirJ8Gwaadel26ZxNvq++T2C83TdPgAAAABJSDBFAiB3NTA++3Fv5asTpCQePVx2VWuL5ToC8wKbhih4iuS8igIhAMZyNEufv2E8KRo+dfJfmzBLeevpe9ryVLihAw4NKiLiAf////8BAPIFKgEAAAAXqRQpC7oypJMVeJoDC7QLAEf4+5D/ZocAAAAA
AQAAAAGDKMjO0oyVqz+XgfONl6reqgfFgmf9roJ6x8plzhnwKQAAAABrSDBFAiB7cPcRvrTWTdVObIsT4VYcgwJdynx08WdNHm99d1PgwgIhAPJAUfw4vVIT147Ze6bYJCz+d6m+GcuIT81RaeHrRQKJASECZmcCPB/PiNe87QJpmXx7gTbPIOmu3oP/WVFORzQPHvT/////AYAaBgAAAAAAGXapFNv4lQkXapdeQdBMwK8kz8jeQ5SpiKwAAAAA
Block: 393
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBIGPSk0BKwYvUDJTSC//////AQDyBSoBAAAAIyEDNpb7mdoBVlmuNermDC62XfiJkUfwG8ur8R0qSulSX4WsAAAAAA==
Block: 394
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBM6PSk0BSwYvUDJTSC//////AVC1BioBAAAAIyEDn+iPQp+cSxRdE0IKHAFZmt2djOluPWsZhmm1BjnavT6sAAAAAA==
AQAAAAHkoS/eVsA+6hrLXrG1fTWrHablXVROghLEfOJ3QWsbPgAAAABKSTBGAiEA7es8koOmJhXkaSVtgxuox0Ggavk/t3eKgZp0LwcMRpwCIQDrYPJhNBhf4pz+OvDnT7vMhX+UrcxmFmDdjF2VPlotbwH/////AQDyBSoBAAAAF6kUQftlBPi8soIGWWGE/UCl7UK85T2HAAAAAA==
AQAAAAEARQQA2oX+EPd8W3TQYEMAO8TVxDpZyEeAEdKBR1IaXgAAAAAmJVEhAsoqgQqxckm2AzoDjeVjmDiBtAaScBg/PAq6lFZT5EIWUa7/////AbAuBSoBAAAAGXapFNv4lQkXapdeQdBMwK8kz8jeQ5SpiKwAAAAA
Block: 395
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPmPSk0BJQYvUDJTSC//////AQDyBSoBAAAAIyEDOcEdldIyfNcAZe0ChYQJazMtYhbi9QeycTlbwnTERmisAAAAAA==
Block: 396
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBA6TSk0BRwYvUDJTSC//////AQDyBSoBAAAAIyEDtvkQ28+OY54ki+oXYvWa0fw11k8vxB/B4cMH7V58twOsAAAAAA==
Block: 397
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBPyTSk0BIgYvUDJTSC//////AQDyBSoBAAAAIyECx9UHjpCRe3FVOjaiFqNnSgnF3v2HBWMDbbwmwU43LEOsAAAAAA==
Block: 398
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBDiUSk0BYQYvUDJTSC//////AQDyBSoBAAAAIyED6NynJo7IyuATbKSg3y1fpVP8O+mZS7AI0jEGsnyk6TusAAAAAA==
AQAAAAMozhDHGJAmhmvPwdBrJ4mB3fIewONk4o4pQ2W1wyjNQwAAAABsSTBGAiEAuRiVHMVfuyhRaABN5+qyHnAuidxDwWe6D8GwknPinPUCIQD5XCS2x0DiMGpFvqHnoMjyAyydTaTY0cxrXEFm0fq/5QEhAzst1v5TYR7z0RK3CYqJmfSL8nx7+UvQRUOdh6nsEfyj//////xPHtSYxfMf6QsQOJ8SVmozUKUIDbHbofAfiDTlgTypAAAAAEhHMEQCIBYe4n760oLoyYQFFBj8wrymhU8/XU4kAxuVC814U5Q6AiArVWbHKur/IpXbgsedUtiNvpRQ4BxslR1dAUjCkPbLvgH//////F7s+pDUau7aNrsaLy2mHk+b6BJTAzrlViXQCssT7zUAAAAASkkwRgIhAPfZlrw57wCyFwFO4+f4tJ7XFPzOL+lwoq2iuah6dBwtAiEAxVpgicKyPsh8UGNRPGyKv8FMkT+Ktpz06+1qWMIglGkB/////wNA8fI6AAAAABl2qRTwaXVv/Z0zERnlQwJoQ3rtFCEK+4isAPIFKgEAAAAXqRQpC7oypJMVeJoDC7QLAEf4+5D/ZocA8gUqAQAAABepFB2cpx76NtgUQk6myhQ35nKHrr40hwAAAAA=
Block: 399
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
Block: 400
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
Block: 401
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
Block: 402
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
Block: 403
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBNeYSk0CigAGL1AyU0gv/////wEA8gUqAQAAACMhAvSAIBforWw9d5r61WUFwLbKiqG7Tp+aErawLUcCCw9BrAAAAAA=
Block: 404
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8PBEuZSk0C5wAGL1AyU0gv/////wGQwgkqAQAAACMhA2M90osFInstoaaOr1OuVZ68aSxOd4R1qmtfVh38juDPrAAAAAA=
AQAAAAHUz5ov//pM08kXm1o2SBNfLeyYmaP9/7v6utrFI8jiZQAAAABqRzBEAiAvPMxWNCWyfhfCGKBsu9BBnfGhj/Z4TOZCOh53+ypBMAIgKQTG1IJA/WaHUP4uWOi6nsRW42jVmqH539sowoy5eTMBIQMtlAKfQyMs9rD7Od6KLeXjL83x0LAqYCg9Jl0P6nO9Y/////8CnoyJJwEAAAAZdqkUhcLH3x399PH5vfZsvUgypPnj1YWIrKCXDQAAAAAAGXapFJI6pCiACahG/QRJoZ57kFlM9aW5iKwAAAAA
AQAAAAETJi/Em9crkuHXMYc4av2HOPRwgR0bl+5K21jgh+/dbgAAAABrSDBFAiEAs5Bs1KcJLYpbPRJXfCLDiPfAoy5Z9mXt+mN3Wh0VK9wCIHEtTY79qYP865OodCc7J9qQde7OPZi+TRLAK+KzVyNPASEDcl0mtwg9OItg6p4NEsMl1rPtf1dkb4dBturQdRnx9rr/////AvIyfCcBAAAAGXapFPjNQHXq/0oRUc1H5trANhjd1Hd+iKxclgwAAAAAABl2qRQYXsXAUBKpQ4ooqiBjAJcVOQe4uYisAAAAAA==
AQAAAAHNH3Yh//0+QlQ4KMVm0wi4AB+4LI7tE+KFvtp9KEWiEwAAAABsSTBGAiEAi09l6CH4tlTGfpJpsLIJoES+MglJXJ0scV3lvYuiDvcCIQDcYqnWS71lO40xjwaDeGlQU1Tfpt4NVo1cKNwDgAC3tAEhAmay0ZebRYarD30nSlO4rKAX/8h63499dbdXXyKNIFM//////wI3YngnAQAAABl2qRSugUfjKIsvTmPoR1eYaPGrIsGx+Yisaw0DAAAAAAAXqRTMrfNVbSe2QIbGg1B57YfKTlV8vYcAAAAA
AQAAAAFBe12aREF9QTLAfeZARnqRBNgvc8cHVdGU8IfO40uWsQAAAABqRzBEAiB/xOllg6Pqly0rhU3mKT65GThAvBQIhaOBLK+tQr6+NAIgE5cposZIj9e+jGhBxrFoEX/+muYz8NJMwyRg5wPjvSYBIQPdNRiHz07EbettCy4OQRw/v9mo3o8AAG0kDOCT7lO0Zv////8Cz0xzJwEAAAAZdqkU6HnXJoHyQItNzFADHpdOkG6L+8+IrBhSBAAAAAAAF6kUr7+3TumUx9RfZphzi8QibQZSZveHAAAAAA==
AQAAAAGIjBCCsjgls53v4HcZvaWIlbJAn1W6eTiqefPP9NTwDgAAAABqRzBEAiB4evy04bEzyTTB1l1MfmvnFET5FSmUO4uVvOuvAvB3YwIgd8cCiHMcB/kGWp4xpUnZtRL+LLRZVUWQvTpMsZ5JilwBIQNsVirqETKlqd8w7wMTdW3YrscT6ZELH6ts7jJNTei5U/////8CAiltJwEAAAAZdqkUqOjsIat4A4FqxXwrWQ7Ilm42vaiIrH1gBQAAAAAAF6kUZfb3FRfJ/UhUFwScLe1SdVPC0QeHAAAAAA==
Block: 405
AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8OBBOZSk0BJQYvUDJTSC//////AWCgECoBAAAAIyECkBtqJQm5YwuQc2mtkL4R8wNRLVEvJXO9n25nMQ2cQE6sAAAAAA==
AQAAAAFhldXXUfA8qI5grl07VtrzyM9xBWyH3uHkoD64c273igAAAABrSDBFAiAb0vXSFTGgFvlF8WQIgZIbQwqcGVEU/jgyoUikD9iqmQIhAL6LNwvzkG4uWva0f5GKzDJAFyF+FKxidhvRsGhATS3IASEDovMc0ddyWkwSZcDgsmBX2TfVoYDAoMi2F70I78P5Udb/////AgO8aCcBAAAAGXapFKMK+dh2UxMCPe11K/lyd50ZPd3iiKyvqQMAAAAAABepFGX29xUXyf1IVBcEnC3tUnVTwtEHhwAAAAA=
AQAAAAGyOCbJrPrzGpy1nA+0q8Hg6ExxBOSnyQiawMFfrnorwwAAAABrSDBFAiEAxI67mKvZMvUI8UhPSvIXnU2bEP9rK1ykZjwJcNO5TF8CIDysrUX3UpJOgwOs1RKkztAthskd9dZ8sTgvnLE0wtOEASEC+KGUbAvD6InsFfYQ3XwLsV9euPWPMCHMlapNGQXnqFn/////AuJzWicBAAAAGXapFLnytHG3TwFFBgTckCyiEAsG3PrwiKzRhA0AAAAAABepFAntYXJTMF/TNJK3Q8CdU4kCoBiLhwAAAAA=
AQAAAAFYU2PU5kuBwcJLBK9XZl96b8st7aYHna/KsujD1e0pBwAAAABrSDBFAiEAjJ2iivel8Maa+jswt0hFdfD+ZUY53zYpT/JFj9I/WQcCIGUoAvaldJHyYFbmLLib9/JvxXmOv6VT7S/zYor4PHUwASECJL4GCi64cZgHLaT/lYmH68Onwk0k9djagcMNzKclZO3/////At3rUCcBAAAAGXapFEqPZHTUFSN4WjmzcB1jd5hhAJPEiKy1xAgAAAAAABl2qRQYXsXAUBKpQ4ooqiBjAJcVOQe4uYisAAAAAA==
AQAAAAEY42X4Ld8uymyn2Rvu/rFBy788uDnkSe0sqwT8PKKymwAAAABrSDBFAiBJ0Vt7RIXCL5sVqG5gm98Bn+RhnVMO4BkMg7+lX/ImlQIhAMEwvj/oiw99qHIqQDn/njRhuLTV6rNt9V6CZTFPn9K6ASEC+gUNEFUuJI+vPj1tPnvZ6lByNdRNV5ydk9EkzV8j71H/////AraxTCcBAAAAGXapFGGEsDebzf4aHma6j5QO0oD6N4jgiKzXdgMAAAAAABl2qRTBI26HmhE8AhJQ3EBHkwW2Lw/25IisAAAAAA==
AQAAAAH/aHqY3wtK2wUG3Elmz+rU/91y+MIOl9dhMHt9hpRTqAAAAABrSDBFAiEAhYkDXYns6LMztX4EFhwiTgrIN8Rdla9nBNLNPj/zV6UCIGO+cYlT4Ma9fTSIT6/fUTUYW3rh/0U66Wue5RHKxNRvASECr2l8hpB7XeO8Ya1SZmCWDNuwzrzOWkPqc/V9P1/c50b/////ArfTQCcBAAAAGXapFByorEBlr6G5gpZ8KMckZB3gA3WniKyvGgsAAAAAABepFK+/t07plMfUX2aYc4vEIm0GUmb3hwAAAAA=
AQAAAAFpH0edqd1pTTin6zPek35NZ/DoLBQB5mcxz5dxVrot1wAAAABrSDBFAiA3zCqnTclkg6NC86G/2CQs2IoMSFdFnZ6u9Yfc+QErGQIhANJqEYChnRdmm8rg4ky4j9d7zp2EzcHu20ifafty/rkmASECD1N6YNQe8g6mG94PF3sGUePQyru32DoF5u6fwRQoHTX/////AgtmPScBAAAAGXapFO4jdIus1KvVWDRApglfvHkIp7jDiKxcqgIAAAAAABepFK+/t07plMfUX2aYc4vEIm0GUmb3hwAAAAA=
AQAAAAEA74iO28JmRYEuR2G6spASybE7T54xqM++fiijlBEAKgAAAABrSDBFAiBA8F+NIrtFjahWEgrSOCzG4ZJD4dSvjHCM4MARNvCTsgIhAJ6nD0PPINdMkLbM1mjw2yIhvpB5t7UF+sUwkZvvAUSoASED6ZFni2vECCgvpbz5A3rN07mAecanEANZwU0Yq3Sw6R7/////Arx+NycBAAAAGXapFMmMKeBgpqVTSivQVOGTDT5mGz8UiKz/IwUAAAAAABepFPJoJEifN04t5t3fXmCyZg8lSSHxhwAAAAA=
AQAAAAGqre8N2pavcDOCNDKK7bo534zFo0XqsJMcsHx7h7+6dgAAAABrSDBFAiEAjdK1aPBwZeNmPJlcozS8dd3/P8eNPDfzPhcaonFS4/MCIFMgbL7umAsxk/rAk8VDdePbJZKQnDSrkyKho+zhDv5nASEDV3CpenYFdHUzjoMG8pDWcj+PIQ5Tw5p8eAuD3Ywavkz/////AibaKicBAAAAGXapFJ6RXMzJ41l2SNk/4pIEZvdwWzHxiKxG4QsAAAAAABepFMyt81VtJ7ZAhsaDUHnth8pOVXy9hwAAAAA=
AQAAAAGvPOv89gbEZQBrOl7H9y0o7fd6iqWcBJbL8uNOkNhHUQAAAABqRzBEAiBvq4hcoCmU0IaY7boYg8BimonJPzXtECaidXT2WQFqjwIgKkE80nHXsfIFbpFiBVLJFWhA+G6cuM+IQu7ubM+yrTABIQOOzp0qDbIH3L0JBSxKPtvW+B8nZ/rwXKIT+gAgvHzdUv////8C2qUZJwEAAAAZdqkU5RQJh5ecQHkg29azYbgQ+4gQt+OIrPxwEAAAAAAAGXapFDqj7ClcYp+kQzbctKO946eVAoNIiKwAAAAA
AQAAAAGVV22mSgPrcOFgajkgI3/tORHA5ix2lr0V9iCli4Y3hQAAAABsSTBGAiEA8GhExGDxaLXRehAXFJUY/EiObEhVmdKGOKebbiLcTQMCIQDRspQnjFd70dYSi+i2RDohcEzkmqWzEhajS8L4vEDJJAEhAmMHJwCToZWoQgKuc6fCsUrZ7z7C8Vp7A5TUZCfgoh8I/////wJ3/xYnAQAAABl2qRQa822KO9zdQUE6d/j1ODUsL2SRWIisE+MBAAAAAAAZdqkUC0MirAFxkDCnELYLCjOXwHTPnt+IrAAAAAA=
AQAAAAHMsXnTs46zU+YiNiNHtoZaZaQ/xqAaffNMIkH8Hngv5wAAAABsSTBGAiEAtSUn/YrIbUk5CsVyfF9ubs2cC06PYa4N4CjAzPSdo7wCIQC4Oc6fOnjSaAW4/zdJ+sXXHSZHTk0FYl5y2gDSut7+QwEhApqKcAtp9We40KHb+VbXyYLQH6tOvjVZkxof44CGU5YK/////wICLgsnAQAAABl2qRS+7VGnGMMgnqTQ/p1IujJzP0roRIisJQ4LAAAAAAAZdqkU7bHfr24LOUSdqBEnU4bt8utUurqIrAAAAAA=
AQAAAAF752CCpayw4GVGHNONFMyYwKKnmLbswm65+2v+h7UEyAAAAABqRzBEAiBwFzcBFCEBsO+1vMA/gn30WTWN1Gxok7cPtaIi/qsuXAIgde/sbLMwCO3YuMSQS7s7hVelN5FdnbnMor70zA7I3UwBIQOMykXrEU8XLaLD53bGdzelui3cD6gzqCp9Nt5mjSd/Kf////8C8Lf5JgEAAAAZdqkUwoL3jmIARIqGEwLqjHDba9Qm6l6IrMKyEAAAAAAAGXapFOapex2V0x6A/CTBdggM1llUGNyZiKwAAAAA
AQAAAAELkd36RITtsW01m4W4vSwMr0Me3EAYy0CEnvAO9bOthwAAAABqRzBEAiA1LZrTV9j41wTaABvOhUZgz6Kx0eeHs/U8cT4TUtNazgIgGYcLkEA6mkg1WcZ61cQtg2b02SZ0MtBf54tVpKA10uUBIQPN5RghsnVku8Spq0S4mn0Xf+6RbRBS1YLl2MwXuKvg5P////8CYXPpJgEAAAAZdqkU27jKWhJ4hRvi8pId3LEa+wLsU/eIrD+BDwAAAAAAF6kUqLs6uFxWMQTKkMQFGhRlMta38UOHAAAAAA==
AQAAAAEZ5Oce0Ev1SPzT6/xb4SvzWWRiMlL92NsKZhT5L2PkRgAAAABsSTBGAiEApMCzbaxQOhzHvLEcJd1I5c35bFYnzj3RkxOEqXFj26gCIQCoX1b/vBgiBUJmmgrUe3Vmpc0o0UEETSV7vLHwCkKvUgEhA6945mYaZYvjdMNrBidI1NSLbvaSMkzdJLW+7OhKFjhP/////wJtYuUmAQAAABl2qRQApNRHhMQXlIN8aWITZ3aHbwtxqYispE0DAAAAAAAXqRSvv7dO6ZTH1F9mmHOLxCJtBlJm94cAAAAA

View File

@ -0,0 +1,908 @@
Block: 0
Transacion 0: A4E5E1B4AA8BF9A32315A8883CB18CF716F86776E3C27CA72B21B7A7DFDE3AB3
Block: 1
Transacion 0: 0F13F5CF8307D907DA65742E028453D83D47F5C33E7824328CA0C729AF0B8CAB
Block: 2
Transacion 0: 0222E29BF085595596621C21BBA50AFDA45BBA3C01E7126A59A0CEB3E253142E
Block: 3
Transacion 0: 174261297DDA0C89C010E867A40579F4951E56B78AA8B15130EAA235CFA5AB14
Block: 4
Transacion 0: D2F156E779F027C4C46D099414258AB32D79DC018EE69D03AD2ADD6775D679C4
Block: 5
Transacion 0: 8610BC1457372250463CEC3CD43DA980972EE47AA5C71AABA6B3C8111C6C6C3B
Block: 6
Transacion 0: 8E541CF5D114C509F18BBA0D04816D6BBABCE03F3A58B5B742DC9A6896207E1D
Block: 7
Transacion 0: DA362EAC5D49076F8B3800BCF91C84DA1CD14A083928BE397C9144EC95F17D1C
Block: 8
Transacion 0: 6796EC299FF3A9DF15FFEA42E34070B64E5E80C86F5910AA6BEDE9EDC5334120
Block: 9
Transacion 0: 25AEB9B769B7906FA26CFEC93E56CED4FC80AAABD601ED6FD843D51627447916
Block: 10
Transacion 0: 45461B3C2F15060F81F3DA864A6038D8D2A10CEA0E950970E2EC9423C6622CE2
Block: 11
Transacion 0: 5EE1217BDAF7E1AB3716DA73AF2E048DEA39CEFAF09C1D62A3F85BDFA594BF92
Block: 12
Transacion 0: 1831BACF2664CE54943CE4B34683608DB0E8E23A26CC810F8C5757554435D8E7
Block: 13
Transacion 0: B69E8C913E734AF35B8327569232EAE99927D9055BEDBA6B8ECA0F3E53EB3FAE
Block: 14
Transacion 0: FD0025868F865136D4050245D0CE6BF6EC90F7529B49B23FB88DB8AF3443C44D
Block: 15
Transacion 0: 9E4D7F149C78A036E538B1D03AE8C8D734C25FC2C842AA56A7910E932C85FE0A
Block: 16
Transacion 0: 0D58283D17F1570D586C8178F40B0D94EA905DCE59CEF6A5DB82F9B44517C245
Block: 17
Transacion 0: 71920001780EECEB8A1DD41E56D3C55F69829D47B61CEA567F671FBCFA7FBEDA
Block: 18
Transacion 0: FC357DCC8DA390A9FCCB13E91EC0E1B3013E4DB26A575B96DF6D6BC98B2DBDE4
Block: 19
Transacion 0: 374A89A8FD64B25604FC5A09790814472B89FC4A937FC3A170C2C2F6DBEB757C
Block: 20
Transacion 0: 4DF5D97A639197E9D9B70DC32C097E8057AEC4AB5DB6B8FF1A1553BFBBD39FAE
Block: 21
Transacion 0: 17A43D53A865866049E18BF7144FC2A9896AB17AC368370C6B7569A190EAD705
Block: 22
Transacion 0: D22CC7D8B4895F2EDE00C9CF61A44C99F0810EC3D4B5177E089F8C7B2B5C1F15
Block: 23
Transacion 0: F36ACF2E619EC1D99C6A6217869E8DFB4BEA75EA0C2D560944C2EF6C8E326328
Block: 24
Transacion 0: 9FED83E8D0CBA6F70DA131CCA8A7072DA5032DCBE98E792858C47A5A452E9EEF
Block: 25
Transacion 0: F43C1FC65D59123D5E042E7E2AF1AB855683B347F0529D7AA24488C84F984F09
Block: 26
Transacion 0: 2A19795218960268DEF8E2C4D882027ED2A31CDEFF6584BCF66B61089C355D6B
Block: 27
Transacion 0: 02371302C953F1C670BB9A40ABAEDC9F6095882B51859EEA03999F324DD43F2F
Block: 28
Transacion 0: F3DAD74E05BD02BF367339E434B3D170233D661DCF8F9F5CB198E8883AEB5C6E
Block: 29
Transacion 0: 3DBCC2BF111806EDD2AF70D8C999399395F796A88B93F0F31469335A1798E62E
Block: 30
Transacion 0: A2D96809C737AA708BF5F195662F25E2D21D0FC2D95317A77E8E8ACAF8D6BFC4
Block: 31
Transacion 0: B16C8BCA53554A697CF4C3BB66A80BA195647EF11810283D5E9AAD453783B822
Block: 32
Transacion 0: 8939616292F1BF479806F15D6E07E26B50F06A73020EE334929E28956B3D04E5
Block: 33
Transacion 0: C196190DE8616BF4E140104CA8437B0B693E9AB9B7770B748112116A4CA10B5E
Block: 34
Transacion 0: F4AA9D561AA29BE53CF4E220E2DF856E45B5F565495565FA795C7C29E1CAC19A
Block: 35
Transacion 0: 5D503E8FC5B7ECF3C0222D9F1281814F1A3A0A613122833D2050A07F8219F19E
Block: 36
Transacion 0: E65228ABB7A5968CB8D820718E33D34932CA4B6B8451DE66569547CF55DBAC96
Block: 37
Transacion 0: 57379ADBBC73CA97E43ADCB4022DA01F02EAF8F14C17493A1CCE9784AF2904F2
Block: 38
Transacion 0: 70195C1C86B83B8BE6B9C59297BF20A1B91E0CA561152BBA72366B36CBDF3ECE
Block: 39
Transacion 0: E6169C8D9A63269D482903A22C8153374537F6597F4FAF9436F26D3412ABC234
Block: 40
Transacion 0: 56815D13D9AA1FF1A596BD66A2D2B04A88B356BBB8521FB5A823FCA752BB3A11
Block: 41
Transacion 0: 4C959D16CC06A721FACDA6A802E0481FDAE802122C47F51EE22013DD09AC64EB
Block: 42
Transacion 0: A9E267F4B01648CE18FF63C5A117889D71DD0580EDDA12F65CB1DDC709435279
Block: 43
Transacion 0: 6323464AD31CC13367992E482999DACA95F9229AC152B1648699675AA1F11A78
Block: 44
Transacion 0: E1E929712E75314C38EF659CB11ABB8DF7C4EF3E83C190236E94229BAF73189A
Block: 45
Transacion 0: C3369FDA7A0C7FA6AC29A63239DDB3B6172487AB9DB8B4214C2D3D891175125D
Block: 46
Transacion 0: E880D69D5CBFD81FBA371A352C353B372B768D602510D1942D0F97958F05C4D2
Block: 47
Transacion 0: CD491CE8CD04CDAC46011ADE0EB98D6769111E35FC28251BAA6B35A4C6980B7B
Block: 48
Transacion 0: 4B188DFB56D2D2A93FFCCAD074CE30C573A74F89BF156416ABA374BA6901E1C1
Block: 49
Transacion 0: 782CA94DD3DAF11B870CF1949F2A0E5FE2B4F6EB13617CCB413CF80AD93086F6
Block: 50
Transacion 0: 42C2FAC11C4F42A172391E5E70CCD95C272F36D9AFCAE0FCDBAD3AB935122D09
Block: 51
Transacion 0: 764FC1684F34CAE7004F49DDB6D52B9E99AA467EA735778290C64EBA233F71D0
Block: 52
Transacion 0: 73A4FA7498AE0294544540944B51AF0861AB49FD925EAFC0441384899A13CB7F
Block: 53
Transacion 0: 8253DF0375A4A60B066C1BB8116ADB52E053D7BF63729DAD48EADDF29046F8F3
Block: 54
Transacion 0: EBF19047FB8CE2031DC0032639494C929749114DB29F4AA179FEA5452808FAF6
Block: 55
Transacion 0: 27FE886C65EE305D083A9530E0279958D85439EDBCE8E888CCD2E704F837D90A
Block: 56
Transacion 0: 85312A3737DDFE943B0FFEF9A7D638A04781C968880EA63CD76C6B4375EAB744
Block: 57
Transacion 0: 2E2A48C47DF96F22D71BC451973C5FDD9F2AA3CAFA70B88BDA463A946742555B
Block: 58
Transacion 0: 750AEEBD659E338668035B0EE706A0E540D5E0A8EC6030575BED6ECD524DFE5D
Block: 59
Transacion 0: 77109E090BF6B6C5AF69876DB8DDDC30AC2EF21B65587F50EACCFDA9B2D41CE5
Block: 60
Transacion 0: 2E8E9E02EF089A5F847FD4511A2B36DE7C824641119FBF08DA6E9D7A072A3583
Block: 61
Transacion 0: 7F64EE18122B5CE6ADF968E2297FD1D3F5BD58964018D8D3EAE6149C2C7E397D
Block: 62
Transacion 0: B6E7B6D0E4D21A650F5B5300327B63C21DF5213C8AC376ECDAF428578854DFC3
Block: 63
Transacion 0: 72AE85BAEC608215D46636BD4024989D8FCF76067FC416E5C3D1B519F58802AC
Block: 64
Transacion 0: E469C10131523AC7CDD85870D87D0D302BB2794349759FF70C96A3667DBB4DAD
Block: 65
Transacion 0: 793780DFDBAD331F77D5ADE2935AFD53EB760B80C606A0C7AF6564DEE6F39DA7
Block: 66
Transacion 0: 1CE9C6F3F200A2EFABE5644DCBF0DC2E70853537610A27AC9982C8422CE110D2
Block: 67
Transacion 0: EEF95E45637283470BDCACEB0E072B6653278CEA847BD9D46C535D0D2FB01AE8
Block: 68
Transacion 0: 42CC2E40E3ECA94551B6924C1C08C4C10D50EC9C79410F8C25065840D1C9B9D5
Block: 69
Transacion 0: 21F032E8663935EC5E621C874216AA93FC0F54ED14BD7C7224452E846FE339AB
Block: 70
Transacion 0: 381D5FD0F83F0BABE7073E2605D7E31E60B5D94513F9320EF595BB97F6A4E79A
Block: 71
Transacion 0: 11845976ACC2AD8E319F3ED6269EA60727C35423177389BE28DCC83B5748DAB2
Block: 72
Transacion 0: B5B337F698A9F4CBC31747616B17B61BA79C8CEE5FF3F28F82DBA2098C25E844
Block: 73
Transacion 0: B9F945589F1A2EEE2EA3AF7557D395F59C516F541D42EC4C66C3E35E98705578
Block: 74
Transacion 0: 6B2DFA54A31F104C4156AE706290E0B0E824E1FBD840F15A3C7EBB4855C2879C
Block: 75
Transacion 0: 41C1793B12E76424EB296D61BB88128EE51CCE046C7D51A42A136B08D4B0F88B
Block: 76
Transacion 0: 8ADCB38D0A4F4B5F59A9D52D3997771E607FA98EDB434F1E07F8737A1DEEFEA2
Block: 77
Transacion 0: C933E3D8FF83C1572E442B5084AA1B9487246F3373574D848BB6F2ACBCAB27B5
Block: 78
Transacion 0: F2FD55491D4D47650EB4061908525D02C5C0B15570D0BBA65387B75DB9DBFDC0
Block: 79
Transacion 0: A53BE0523C9E8C5E30F7CE58BB550AFEABE45209773318A922E997A1693D2A03
Block: 80
Transacion 0: 79AB45C7B83B56ABAA1385698CC7B40086621C71B43382AAF8E2E4802BF37B53
Block: 81
Transacion 0: 1DE8145EDC1A55C11121C4879C7DF75A0E604BC7A73E2F2417A4028F7C5D0F6F
Block: 82
Transacion 0: 22C793F05837F6613DF3992FAC656E9D3D52A92526FA3CFCCA8F9F31C043756D
Block: 83
Transacion 0: 864C4D0E50425D23128C84B739454B8FCD9BE09F5312D78D547C496DE51A4980
Block: 84
Transacion 0: BB756A5FF9F3D0FEC49872DCA7D3EBDF26691D5B752856E80FC30B46022FB9FD
Block: 85
Transacion 0: 0723C7FB8998BD250C8924F52199CDBB59D370C0FB157EECA1203DEB69833377
Block: 86
Transacion 0: FFF9F5E1DCC63AB8813C971890CD7E5DC18EE0D135921DBA4F149D469A89C3E5
Block: 87
Transacion 0: 4929B967E61B21C313A6067D70CA568672599E87CA7959844CC415D064D917CA
Block: 88
Transacion 0: BED49855568974D074D6622FBB032A2A57F835C16D942DA543BFAF47E2B821AC
Block: 89
Transacion 0: 5EA4267AEF9246E30A721EA9C7077C6664B7491F8A6F613C5CB2C323EA5EBEAB
Block: 90
Transacion 0: 20C5F74B054FC5C921E778D60136E3B9F8AA258B3D5ECDAE28EE68AD15B2B1A4
Block: 91
Transacion 0: 39BDFB42528C6BBD24F6F8B6821A70F0B1689310B5BB7F96F413B42DF591B4E5
Block: 92
Transacion 0: C7DDABEAC231AFDD3FA7860FBD86E032094B3ADB545BDD96EAEE0ECC0DA31A52
Block: 93
Transacion 0: 1CA2A5AC3EFE7D880F88CFAFD662E74D68181AEAD4F274B7AF060C0520476BEB
Block: 94
Transacion 0: 462F13E5224DE320453FADC2F713BB02CEE41306C13A536AE5E06428F3380B5D
Block: 95
Transacion 0: BBD413A6AC23D5915F4631137266B8DE22860A905AB9982E577B21E53B614DF4
Block: 96
Transacion 0: 9443F91C59B440AF8D136CEE76E5CC3DE5D654BA4BA801F131ADD3A79FB68F61
Block: 97
Transacion 0: 0CC41453670377733FDA84FE5E5D90BE8C381E0D84223B2ACEFCA6084A849223
Block: 98
Transacion 0: 6DCC0DA064CE086B24F46978169C4C0334C7587260C5D0F76EF380FF04183241
Block: 99
Transacion 0: B5A09B3E75769B73FC5557E4CD840B6F39BC64187122282C578707A634DC09D0
Block: 100
Transacion 0: 274AF90F85926F3CA180A9C9473194C81B1809FF8C9302E8762AC71C95332A89
Block: 101
Transacion 0: 1D24FF86321874A2D276316822CC09A63B37097F56A7D37431E3D420A315F90E
Block: 102
Transacion 0: 6FEE3ADDF456635330445A533EA7148771B0AB818B174A426D691E694D3D5B55
Block: 103
Transacion 0: 95D84FF92436C233ACA0BF8357DD8A3219DA6BACFC1EC56D60A7B7FA8029FA94
Block: 104
Transacion 0: 769467A22E021C7050557699CDCEB96B5AA4B788E14B9B1623A333360BD05B81
Block: 105
Transacion 0: 5BF2FC3095ABD4EA10EFECD4FB99704F9593F67F55EF3CFA44741A058B6456F8
Block: 106
Transacion 0: 4107D20DB19E32342C40AF84C8B0738FF1245008A7CF3395B71F41122B94E8A7
Block: 107
Transacion 0: B9845C6516211C96AB876A27700C30294947E14F5BBEED573E0D42EBFBA3B9B8
Block: 108
Transacion 0: 82F63509F597F986634B6185C242D8ECD6D34E2145F57DEAE3E2606C3574B5EB
Block: 109
Transacion 0: 6EE27EAACAA4DEF6C905360A881A830C2FF3A8311C83BCAD467B44A014E14CB8
Block: 110
Transacion 0: 8F5CD5C2A31B270EAA3F2AB70DEC42362949D26AA350C4F6C8C52F6EDA19E28E
Block: 111
Transacion 0: E3DD473F28D39FEBAF63176ABD5A7D96A1C60F9CA22C240EA453ABC9BAE514EC
Block: 112
Transacion 0: 4600AE9F51506E4F515F5FE34975A5368C6669942D1B381D3FE14141272B33FF
Block: 113
Transacion 0: 55C4C9F33F9B01148A29F909FE97E92185787F5B4BD7A7D888A8617B00C77719
Block: 114
Transacion 0: 810CD8B85D8152783330E9722BA547D58B6A928C77E22A6631C17078F2AD078A
Block: 115
Transacion 0: F08DA27F8BC70DBC5A1DCE77D509A44DD0751FA2AB3EF3973AD3424DC863D45D
Block: 116
Transacion 0: D2438452865CB38913FE6725085FF91D153C8FCE908F88766F8BD579D4F0DEEE
Block: 117
Transacion 0: FDA9353057B3F0871A690DABF5826BC3C353D0407A6C89DB7455D6496592717D
Block: 118
Transacion 0: B4518A34A3D058AD7A9A07842B9CFA718CF9A2C13458DF883F30B74D69210758
Block: 119
Transacion 0: B99BCC672614F4E61E78834B9FB955CA2AD7E7D17584465C8D604D91D5651C7B
Block: 120
Transacion 0: 9700FF159A785C679924EC104DF962CFC18A229B725B2C1E84A8005A3629A690
Block: 121
Transacion 0: 1985DEF8BDCC65373924FE62694B041113B198DDB9732AC3BD674201D7D37E5B
Block: 122
Transacion 0: 6B417A4E70C86DDE0CC3CC7833349DA8E71D4087081CDD36CF87A2C676804B83
Block: 123
Transacion 0: 9F558EBCCE91D5B1E59AE27DEA61235FAE1155B1CF7D3AF0DED0B6508C5734C1
Block: 124
Transacion 0: 4B27CA6FE3FADAC37657E04307DB40C59C0065F332A955AFFDB11F20F5896624
Block: 125
Transacion 0: A9F3AC66CD6D2E0E314B36045CF0D40808C2AF3E078B997B97DA25304325605C
Block: 126
Transacion 0: 17588504EFF9F3706D3ECC205BF7486F5B48CD831228FB2759A78C618BC4592D
Block: 127
Transacion 0: 32456269E0F40C03DC0A5A20A429CE3DBF4D69C2E0EDA2A09240375DCA2417B1
Block: 128
Transacion 0: 52BE53C2ACE54B98C9FCAE139E2214D6FFB9AB7E47B96DB9C23F66BB14029496
Block: 129
Transacion 0: 30A5899E2FC047CCFB11098C5447BECE0837A9DE522509EF73124ECB0052D5F0
Block: 130
Transacion 0: 5ADD490797C2A96DDF1A014D1BC9F9B2B270BE692D9335A0E0E10C1BF2A0CA8C
Block: 131
Transacion 0: B7F959E0BAA981D1FBA7FEAD3D11C95ACF8C96C679153EE8C22754D4226B7251
Block: 132
Transacion 0: FF862E8F129AA42D1972281B3F9690AD2D1AA073840BCC87EB30631A78FD7B96
Block: 133
Transacion 0: A643E43EBB13BA2BFF89AD6996C3F0DCFD135384E992C0439B79775E49DAAD58
Block: 134
Transacion 0: 26DE07B5373DEAABF450F9ED0DADECCD0091E48EF1174675D0A379E845203600
Block: 135
Transacion 0: 7DD993C21FE2B29B85F4C71E7EF53EBD7591143E65828A5C99203F3D235661FF
Block: 136
Transacion 0: DAAC50396C315BB389AAAA3D0BF7398D589519BAA6C6225184B6D87746EFFB7C
Block: 137
Transacion 0: F1FF402E25DF797B4AAC64F3FF0263D4E9814A7B9190AEBC09599E6F150C8ADB
Block: 138
Transacion 0: D2A49B49F0E0D2FDFA3A5DC8A12AD55E93B172104FFD454C6E672FEBE480AAC4
Block: 139
Transacion 0: 182497B07A3AFB497AD8B0ED1E675476A134E828801F9C3BBCB2FF5D745CE559
Block: 140
Transacion 0: 410A7CE37AA854449C6DF6A0D358FA15722F95FBE0FBBF1EB33486EA6CBB545C
Block: 141
Transacion 0: B974F15E4BD428D4347F78E3317103BBEB186DA4F3A6077E98C42E40D8453653
Block: 142
Transacion 0: CC687462C47BC20D806651C62A464A1D1466C2989941FFA95BEE16FA9473A0F1
Block: 143
Transacion 0: 274DCF34CA75A6B4F2F1531E3B012A8DA301213AF6CD8731CE326764592033FC
Block: 144
Transacion 0: 225876257F4BAB51423853D566BCB148DD166EFEA8ECEE1E3F2EDFC3750343E8
Block: 145
Transacion 0: 704E6A2D1F74223161491ABBF6FD90C69E81E68A96E110F40E14F69FCC09E622
Block: 146
Transacion 0: D54D07B9630AC02A00CA412E4CF349DB09E9378A92556E28558532837F86DBA0
Block: 147
Transacion 0: 95312925CD6AFAAA7F6583B02C3654652878C93992BE93F11015025FD6625E87
Block: 148
Transacion 0: F65FDFDE5D6BABC425105B36248BEE7D0C4082BD326C488135CA6AD833F16B2D
Block: 149
Transacion 0: B142EC4CEC5091FD20A84F1439F461C1F3BD6CBB6F113DF33FE9B0860FC30B1F
Block: 150
Transacion 0: C50C6A5AA28A141998510D930F40A523A1BF6AF9428142BA2544D2A0F9E66987
Block: 151
Transacion 0: 8501E2238E84BF6DC89284D00ED056A3886AED70C7648D6F3C478892F0B2D434
Block: 152
Transacion 0: 10040CB5759E5A8280DC82B0BFE7A00DB0C8838C0E220C24E5825237815101B5
Block: 153
Transacion 0: DE79DB20034CCFE9356ECA2D088A37BD65930A78FF8547EF086A470CA8986EF1
Block: 154
Transacion 0: CC4CCC27B0A3F659F4B6E25E13B86B1BF9B40B76CC7E176D6C7D4692754BC71B
Block: 155
Transacion 0: D23CF8DE42F8592430948CB3F9E1B69F6AC81DABFE65190D0F91C635D45C2A37
Block: 156
Transacion 0: 4AF5A9429D64EFADB1C6E275B19A14CA9051F5D4A6953753689EFC3120C58DF6
Block: 157
Transacion 0: B97AF236B791CCCAE09A7FB91B00088096DB3D254646E7CEB9F286CA4AF76569
Block: 158
Transacion 0: 1B24142042F0976925620B518F8DD4F6E9A6FB566070F15407DDE707A728A5CE
Block: 159
Transacion 0: 081275A54425179975884E95FC8C180898F999A7588F2E8C0C5D864DAFD2803E
Block: 160
Transacion 0: A9124A08448259A61650202556D2B59B56002CD250F15FA089BEBBEF6CEC1AEC
Block: 161
Transacion 0: C77230FD6B2B7CD4703C5FA4F7B146480DD7D7F703BF2EEF5107EDEBB6902F96
Block: 162
Transacion 0: ECC90E655EC6FFE481925BF7DC580CD1897DED8086B2C92E8C223A1A3C15B82B
Block: 163
Transacion 0: F4F1F722AF674BAABDF6F9039029056E71D4A16E1F9C0D67CF26E4EBE50E1416
Block: 164
Transacion 0: CF0D80464703DAC273D32425212096528400C3D0607237605C22AEF50E20B2E4
Block: 165
Transacion 0: 2BED756E9291332DA0CC14CA5EEAA6A86DE4F98B483EB1806E8548E7108A89F5
Block: 166
Transacion 0: 1380A067B7AF4AF7C6193A4B03C2397C8D8BF11CFD686473B012BEC5909BFC5D
Block: 167
Transacion 0: 65A1C9B523CBAF222290FF857AA9E0FFBCFF830E7CD8AE046AA284A751E11F57
Block: 168
Transacion 0: 34D14A443C5B63788468855A5E74DAFF6EB08B50A7FD1BBA6D8657AA23BB3054
Block: 169
Transacion 0: FA95FAA636E0896DD940F57A818305AD3054497B5582AAD4CE821F7DA7D5AE13
Block: 170
Transacion 0: 98BE93DF4054D67C601A6627BCDE85C2CDEA7DB1A6A4E2832AC4266BF8592EEB
Block: 171
Transacion 0: 1E50E1C396BEE2AC32A307206C864D39EE9EC198EE133AC010AF002E34EC0EA1
Block: 172
Transacion 0: 5BA5B3BEB03EA33C268EB90D54C37555046348A430B69080D1FBAA9A40879264
Block: 173
Transacion 0: 776BAB8BF26A81F3A1387B50152EB2A75542B074F98027FAD943AB5E1D45851D
Block: 174
Transacion 0: 4840EE9C31A591F83FF72F3F6B503FD4BE863B451C8E6AD0898C1EA9CABB6457
Block: 175
Transacion 0: 2F8DB71AD63FFD8D5BC13CE4E9E7B375C6BDBB27340C041278F33E784EE4BAD8
Block: 176
Transacion 0: 974F39F6A3DDC1831508C61E5911554B21601E1828697A975A7CB47760737516
Block: 177
Transacion 0: 7BB7EF28041E793A0C403E416431BA92CCC5DBD63F28BA5E689DD818EECEBB4B
Block: 178
Transacion 0: E15FB5A869FB5ACA8AD56C68458CEDB4BF9C724E1B31BD65727E0652ABA18CD7
Block: 179
Transacion 0: 3291B6FDDDE92D944AD9A840561781E92A89F6D0FD542A113CBC367A2C442CA5
Block: 180
Transacion 0: 2EB377CDC77C8DFF306E0A34311BE354DAE5B9961F22A353D3CDF3DAF24E6E06
Block: 181
Transacion 0: BE5D1FA61FE999FEE18004D11ABA8A4D50DE218BE962385009FE4122D2F7632A
Block: 182
Transacion 0: 9AC3185E4388F10F1ABD1BD0805A0533A66521F98301B09EF13F5C894DE1F4CF
Block: 183
Transacion 0: 7DF85C829FE00738F2DC6BBF81C1835A33651D5F6AB862DA14EF502671666522
Block: 184
Transacion 0: 0A920E24FDB994B503FC591C8C78E698E2D93552D09716CF15B5F9C33F94DC19
Block: 185
Transacion 0: 53FE31BCA00D52655EA33035218EB9F4E16AD2F2A1BB63ADEEA64D09AFCEE5CF
Block: 186
Transacion 0: 4013E6BE12D943854C7AA15FCBA3F5979BA2C2024EC2484808A509F27B17D474
Block: 187
Transacion 0: 75DB616F062ED403F6F326C69BC51DB6D70C6196D770475107182FA20EE34CCB
Block: 188
Transacion 0: F44515939990A0DC688902918CC2A267EE2A544465A80ECA0C15BE23798BC1AC
Block: 189
Transacion 0: 00038DB28BDAD97D66F49D2ECB410DEAD3C93BD4C25DD685865EFB98A92BF4C2
Block: 190
Transacion 0: 1E25E57201E1F145446D5B1984E2A1E6F30D785974E22F60F6FEB28232B19E86
Block: 191
Transacion 0: 8513A31BA0E68D6F694E67B9062A7E9F4AE5A828684D89BD32357B7B01B9D23A
Block: 192
Transacion 0: 84478A66084ABB4935D771A69BE6D6466EF8716325EAFE3AB7311AA56FD4EBFE
Block: 193
Transacion 0: 3D9DF8495896FADD682451329A4558743743E6BB638D47D773D5DC8D37B7CCE0
Block: 194
Transacion 0: B25A526C33669B7E184112E42681A27E7BA4E6ADFAAD8F07568308EF17960C33
Block: 195
Transacion 0: 72E9408813BCE244D1B6DA2B04F295129CE5A2D11B0143F4F9C26AB430637848
Block: 196
Transacion 0: 046F44EFE24A07E4DD99AE2ECF3E1ADD608C4252D0250FAF0106307140E1E557
Block: 197
Transacion 0: DDE670E27B0E29CACA83621C3D6412C881D807875940CF6197E5156A650A39E9
Block: 198
Transacion 0: 05E31685EE3F88D6F6DBD9731CBF0E4A471D64E98A149575A68E2C024DF20B96
Block: 199
Transacion 0: F7603D45451CE00405E3304B776E359DA698FE741CE054896F33EF6F5B8BF0FC
Block: 200
Transacion 0: 547104DB4D373CC3A29D12D341318778EDD268281DFA38363244BBA44C214D88
Block: 201
Transacion 0: DF4CC31F486CBEA1873D6F61E7D0CD671A2CC67BACDC0CE7546DB1A1895FBA3E
Block: 202
Transacion 0: B32F74E782D6748C99977B415F130798ED9546FD94A423719C6E8DDDBD0DDB41
Block: 203
Transacion 0: 335E2EAC0B5ACCFEFF0AAD66F5B8FDBD78902612B864538CF4FAFE5F64A7AD7E
Block: 204
Transacion 0: E7E9EC57FEBB95FD3BE82454AF9174346336D62B355806A6ED1C2C13F7A686FD
Block: 205
Transacion 0: EA0F17D9ADC6C33B9C30D98BB6C3A19AD79A32828B92B1F927E9EC88514731C9
Block: 206
Transacion 0: 646E19BB59854C33324257C02137DD229968837178B8F8BE7C784D180ECD5898
Block: 207
Transacion 0: 5F38A6A30CFBC62554127E6CE228FC63AAAACFDCA30B736AD4718FA75455DE96
Block: 208
Transacion 0: 26C32873E5596D430ED220A8A56FA7E379002CB526183EE7A7DD352D4331FBE5
Block: 209
Transacion 0: 2EEB010E97A954ACB04CF95567229A5AC8157F5979E32AA864A1B20BBDC818F3
Block: 210
Transacion 0: EC42B7CE0A6A9B2997975941A07444A6730A484EF154EE479BD4A9550ED4A433
Block: 211
Transacion 0: BFE7DAA72079393E28C925A3ADFFC3D6AED7CC12798C331527D1F269FA63092D
Block: 212
Transacion 0: 92BF17129D0C1347508907DD878F2BBC976E0934EA9C8FC3B91972CA46465F4A
Block: 213
Transacion 0: 5ED0C457ACC8B1E615B51BD74543E8FFA861DE7A959D3C33A21CFED0CED063A8
Block: 214
Transacion 0: 29B1E8AD9C4BFB47F97643BE82945CB59C5EF685559504844DDD46A1DCC37BE2
Block: 215
Transacion 0: 243260DA2118368CFD808A484B7959012F833A869AEA72141F86FDA89DE4F58F
Block: 216
Transacion 0: 722B3FAEAFE96569BE678A69C05905E227B746F043D430A13A5C99B19AEF622D
Block: 217
Transacion 0: B0283F61968394BA35B7F9601FFAC6F1B8A177E16179A0BEC4AF62F47ADC88F3
Block: 218
Transacion 0: 7178A912E54E192CF1DB3E2EBD090F735E171E673208A8E3AC533C71110FD7B5
Block: 219
Transacion 0: 24FB2B2C07ED381C3EBC1F32C374E609C6E568A4A29D8C04842F0F0DC0242997
Block: 220
Transacion 0: AE49085050F534DB53D4E1CA6BB8B3958B6933F9CE6AC41DE8A2FB9241F3E03A
Block: 221
Transacion 0: 0338BC898080D83A808870F3A59C253C0AB25A249337B63CE26DF34D641B11C3
Block: 222
Transacion 0: 93D392D2650FEDD9D2CD4CD67AF8792526BDF7509AD9C4104F766EFCAEB3C71B
Block: 223
Transacion 0: BF2A8B59866740CD1BD0C1A399FDB1B5801AAA84EB632B9FE70B5A89C54DF42E
Block: 224
Transacion 0: 4C365AE469930A4CE2C2B52BB6CB0CC25328A3C424F8A948C34F07B4B40F23C8
Block: 225
Transacion 0: C5DAF96771C7646ACEEEC484892CD4E8D9778FB9EC7C8579941C298DBD060F95
Block: 226
Transacion 0: 17F898824DE670FDDAC71EE77474FE3235F638968995840020CD834AE06C046F
Block: 227
Transacion 0: 67C3B1FE96340ED2C96069BE1E3829E26275C584D9FE709A9B98AFDA73C3CA95
Block: 228
Transacion 0: FD784B0505E776DF56731C579985984CF739864F1B349FBE031827506353E52E
Block: 229
Transacion 0: 2124DD113F28088226FF292FD05D9AE665C9FD9D0A45028A47F7388BF1FEA351
Block: 230
Transacion 0: AB3D904C6C32198304D1ABEE9A3EDEF06DD3173DE598069F18964443B8693812
Block: 231
Transacion 0: 2B2F2AF6E7FCD81AB3AF6D453ADDA38E7CAECF2A4AF76D7330CB4B0F8A1E8F7F
Block: 232
Transacion 0: B5EE6BF7B6A0B0B70CFEE686E58CD51B97F95595F4B4BF0131A4A904A2C9B46E
Block: 233
Transacion 0: E3B1B614772EC74C2128E445D55E6AD1BA53D75B1BE5BCA1AEE30C65EDF21A4E
Block: 234
Transacion 0: 35DC0CBE986E28ACC5532DE06D6F067403CAF57CA129B7985FB0DF8C88A53AF0
Block: 235
Transacion 0: 0FC94817E1476C418BAF9E387A37CB7BA744FF999977401482D86FB87D99CE3B
Block: 236
Transacion 0: 550377252E9922FBAAB445B1393944288094831059B54D7148F6DF463C8B52C1
Block: 237
Transacion 0: A6E25AB745F4ECE163AEEF6C4543683E4DF96692D5CD113FCE226792B58FEEAA
Block: 238
Transacion 0: B59FEB8D4DBFF34EE30262E81875DE29ED1B85643D577BA8A222B6368A381DAC
Block: 239
Transacion 0: CC16AB9F1835608FADF8D91E5020F3EDD0CD9462D9A86CA7F6C3881B94A2D95D
Block: 240
Transacion 0: 760DB09C3A33EB03DCAC07BC773D0DCB980529751D1C20799C667B42A3B0992A
Block: 241
Transacion 0: 10E3224E31DC3F8EE0AC630C850F3AA10CE0CBBF5F74AFA665885B26D671937E
Block: 242
Transacion 0: BF15760DEA728B80335BEC2797EC77FFC1A01F2B4E8C2812217E5DD2CEC2F5AF
Block: 243
Transacion 0: E146943CD1D6EFD812B1D7059A9455277E71F39CB1A5643A3A81A853E3D58F17
Block: 244
Transacion 0: A47E3DE47480ED9CDFBF0158FE838286A5F7D789E6724867E029F9E8A033A046
Block: 245
Transacion 0: 64290A6A8911A348C1820C333039F770052AC4981B0199B46AAD556A270F60C8
Block: 246
Transacion 0: 11C47D4554BCFA439E844A2137E6F09E62DE50AA741EF9FA90BF187AF1EA3903
Block: 247
Transacion 0: C2C27A64DD86B0F2B02E626AF8CF2F945F9805C43B590E0108C0D69CA6290E2F
Block: 248
Transacion 0: E04FB7918E070C886A4044B7B56BF7EB35F2743685088C58511A3DBDF4DE503C
Block: 249
Transacion 0: CCB64DA9DB3AC1752806F2C9EF207B55E77D110B9A9320C1BCA749C596CFE804
Block: 250
Transacion 0: F09D91F3D8AAEFD8F100E54C5955A0EB05ADBD2C502B9141E595F77ED04D35CF
Block: 251
Transacion 0: C6F00826031E4E572D3BF8C5E4E89262C0F34B3F2451D1D8B15D49EBE6E156C3
Block: 252
Transacion 0: 238AA765770816A8BDE3A8B039E42AA470613CF7E5A915F7C314962EB02E0B29
Block: 253
Transacion 0: 15AE5DD71A77AAD7B14B9D62AE93A2C416D5158DC1DC12ABAFB2CBC737ECEECE
Block: 254
Transacion 0: 904A5F0927AA6AA53DEAB0E4743BF9F8176AC0B5BD99BCEFAA13B876AE3EC218
Block: 255
Transacion 0: 3A0E1E9B7A22020A156DAA08F1B1248DA8A64D76344EE5B97E10763AC2612691
Block: 256
Transacion 0: 7B64E63E637AC7F9128B792FCC9ACF026AF45A21892C6E21731DEBDCD68187AB
Block: 257
Transacion 0: 708CDF710539593B56B92626DB7ED741782E1AD739718DDE0F39C6651F097105
Block: 258
Transacion 0: 5AE06A6FF0F242FA09997DFC47761E948943F50DE170BB951F4A9B3F8B01A8F5
Block: 259
Transacion 0: 952A69E8A179A49B4DA6C55ACDC5CF022678D9813385E7D14BFADEB917C59847
Block: 260
Transacion 0: 8358B279FF43030387BA5D95BCDB85A4900E1BD6BFB8AE53390DB20EDD88B6C4
Block: 261
Transacion 0: 3A29DF8EB46B59C66AF3F2299994F9163CDE3E759B676D2B2B93AD2E7D47AD41
Block: 262
Transacion 0: 36927167905873357B104C399B47C243774CC70283AE55B54BD5C2B443D4FC67
Block: 263
Transacion 0: 2A4957FBF6A80F74D6F344A094114EE338E5A5C576A85D5A3278DB4F554A8CD2
Block: 264
Transacion 0: EE8167476C693DB55DE1500619C39EC674318193E9B2327C1B8D7A36598FE070
Block: 265
Transacion 0: EAA56C2DAC02C8E12A663273D16561C9421209CD5264F84078E764A22BE94FA4
Block: 266
Transacion 0: F4DBE6D395C7E93CF0E527C3D6C5FB14F1CAB10088B2FE0B782C4CB04329D437
Block: 267
Transacion 0: 3FAD31404D8404988697F3C3221E26C3E5CE81FB4523F368AC5F29F358758257
Block: 268
Transacion 0: 0A4FE4E326D3E9FE15FDE6732B39DFB5A1AC26691A6515EDF71F866AB394CD62
Block: 269
Transacion 0: 68F723467C0D39CD822314E57CD56554C3C93C19C135536B4A50C3E9E738A35E
Block: 270
Transacion 0: 975E17E211AFAB0674B881B4FB820360C3A31A2A2CC77B60DBC27C2F531C3080
Block: 271
Transacion 0: 418F2343797ACB0990B77634CFF89B8004736186731DA21B69C1170BBD4291DA
Block: 272
Transacion 0: E8AE5D397F893664281E375F02B9D4ACF7ACB9CF3BB9D86862A064881C8B0155
Block: 273
Transacion 0: 87A7327727E0B63577808F62DED3FB460253A34A0AE03176E7CDD965E37F4D45
Block: 274
Transacion 0: DF4A6FC4671F456EF277B6719EE69E16244F81ECE8F20DEC7A8AA13A5EB5A6A6
Block: 275
Transacion 0: C8E3DF1808DCB932EDD2903EF5DAF5B228A294373F075A4C0FE1A7AF76737081
Block: 276
Transacion 0: BCB248F3CA047C720068837652DBD2F6FD18928D328269713F41972E7090A51E
Block: 277
Transacion 0: 3B224AC24234E0C9699ECBE3C00EF8FA0830BACDA03D039E88FC498C1E88CD6F
Block: 278
Transacion 0: 884967FF0184272F9CA36C15FE924B6C4F08D061E1F28A951F88CC839E2BC118
Block: 279
Transacion 0: 7D6294D1EDD1E8D094BDA5E171C8629932E3B5C7A47AF7F5DDAAC3922F89FFB0
Block: 280
Transacion 0: 07927F55432755A5424FBAA5772907614EE972A65BC2EBA6A2DC80D1A7005B77
Block: 281
Transacion 0: A286B5736560D59ECF4478C802303B897387BB2EC900AC3038C573CF5D503405
Block: 282
Transacion 0: 7F5CA571B6BC1D00A863777A6029F426FA98E4A450E9AF3D959C4F493D9C9761
Block: 283
Transacion 0: B760A4BD2C34A782B9B7165B4C404853FAF145B21C73E7E6738DA21E29D6BD52
Block: 284
Transacion 0: E3E040D88DA72F2B805D1A73CB86E132BBD2BBA436437AB5B0D24DE3487B0619
Block: 285
Transacion 0: E291A329072C2310F6DCA22D6F96F6A98F8E700B98992524094B7E4943A91851
Block: 286
Transacion 0: 4DF437A5C7CEB7150BCBA89AE850226E322E591F5FD304B8A958767B4344EF6C
Block: 287
Transacion 0: 9009265BBE017E7739030E7D75292A37E77017137AE671DCC7385606098F6D21
Block: 288
Transacion 0: CBBF961139F9F8B1330A9B2FCA606B9BC12AE77ECF9C1B4CFB6FE33F5754BA54
Block: 289
Transacion 0: 880A09AB0ED3D5C360A48DCEF4982A6C92FABD0738C9ADD39ECE4530D04FE272
Block: 290
Transacion 0: 6FD4837D07212F04C08278CD4BFB7DF567D1F3DD871ED9FF20E39913BFDB57F1
Block: 291
Transacion 0: 1C3CD06143D410F638D51A29CFB3CBB7C74F2C27285B83270B2D45EAC36422A7
Block: 292
Transacion 0: ED567767572E73D8C36543265DC07ADDA68D9D77030EDCCEC80F6D1DB2E89937
Block: 293
Transacion 0: A0807C71A404637606295AA2C34E64360B0C3FDC3AF5B6BCEADBD1D6B896D840
Block: 294
Transacion 0: 6F0284045D2E8CEDB02B8361A907A88676FEB700DE502F10148EC08C1C5F48FE
Block: 295
Transacion 0: FB9928BC2D57A6E23B3F134BA687B3D7E33B94B111D2C148DA88D4BF0EB7B02D
Block: 296
Transacion 0: 2B544C2144C96E18865BDC2587608994B3040870C3203EEC4764BB05D901F57F
Block: 297
Transacion 0: 5349C232586129C7199A903B2AF1BE9D952BD5AD46E5E22315329452876B1DFC
Block: 298
Transacion 0: 5237D9837A59972316691BA82D8B865F301CCE5FEC64640FBF82A78CBFD2C421
Block: 299
Transacion 0: EE408DEF96C7F38E05378E9069B597343499C04694CFD51A64680FC0C158F69C
Block: 300
Transacion 0: FED86F29C1533394C0EF76A659C00A830C369D816221C40BEE701A8E87CBEE57
Block: 301
Transacion 0: 8E27628916CCDCAAD5D7379057C6D79C40AC21250E51A06E79E18751A970C937
Block: 302
Transacion 0: 2AF236410966662C0C5257F46DA184C3830272F6D5551966C75C262B2B645B6A
Block: 303
Transacion 0: 34578F62E43649464CCE0E9AA54763376DC8D7511336C03290F36350121C99AB
Block: 304
Transacion 0: 70DADADF7728CD087A77EB7E3AB9B8E72A12C0D135AD63BAF78572AA0F00D6FD
Block: 305
Transacion 0: 40610F7D6525C7EADFE147D8BB4C13239BAE3EAE77B8191AF083020FCC65E016
Block: 306
Transacion 0: 73363375BAB4F662B4FD2FBDCE2BEC3A5E0B9DFE83DDBE7D7FAE14C95099FFAF
Block: 307
Transacion 0: 90E5BE62397951A3BD95AD76AF33B4DC3E7A19B3494E8CE0A18AC54AA485A0EB
Block: 308
Transacion 0: 18D2236DB947FCC7FA2D81158C747BE4D473143D55394FEE3E32391051FC095C
Block: 309
Transacion 0: F4D9F729573ABF344386410355B456CF9B8587E4812810A9747C1C04E1731F7A
Block: 310
Transacion 0: 98D9C4D7A64D0689B5EEF36BE54E98F5497339DAB2D8E3C44A3CA3DB47AC4940
Block: 311
Transacion 0: 6639E7E42AE559FCF44A940EDDCEE8E63C39932FC637576F9E3C5D238AE18006
Block: 312
Transacion 0: 515EA5F03C185AA49F3E728FC522700028AF4B05CE1F0CD826F39CC07D2B1DF6
Block: 313
Transacion 0: F38E4AD932FCEE2878C9FEF03AEAA968FC7CB938FF10EEA71EA5EE458788CC4A
Block: 314
Transacion 0: BC39041B0E204EAAF5E609C48C634B6B68EAF6B8009AA902D8584F9A0C77185E
Block: 315
Transacion 0: B2EFF3AC5056EE12E2B5A96AF746F5973818AAB93FCF4738B3F391F27C66B159
Block: 316
Transacion 0: 18993059912EC40D6E99D0DA4EEAB6B6C68B9F959B31DC0C2D4D2D30498A62E2
Block: 317
Transacion 0: B100A150AEF9B61591B6CA2CFD8692925204627EE2F661B37D151E08885A446A
Block: 318
Transacion 0: DD3925C652A893370AC0D0D3B5DEC42AF6391A3AAFF91996EE48E71E58DB290F
Block: 319
Transacion 0: 835FFAFF59E532597D29F974049EC861AB865AD8991DD054EDCFBB4DA5C945BB
Block: 320
Transacion 0: C026E8D8047E96DA914FB6EBE3BF7ECFBCFAA19D8A1DD6732C2D4B8787C315BC
Block: 321
Transacion 0: 30F086EEFFEF66AB6314B07C9617FC740DB852B92C2A9D79AE2115038D0E3A16
Block: 322
Transacion 0: 6CFDF75F7A699B9856521D5982DA57E5668D02E94AA614F9669763A784C8FDBC
Block: 323
Transacion 0: 817ED60CCE3E03EA3BA82C06EFCFA7441861E7BD3EE016852596BAFF29EA61FC
Block: 324
Transacion 0: 6C2B940931F1F4807BA24CB13ACA6B13F26100E84D5C4BA55CBFB679895CEE71
Block: 325
Transacion 0: 2B3F28B6368049E01917F44EEAF8EF96844B9D0CC72475C86323BFA4AF8DEF0A
Block: 326
Transacion 0: 21512B092BDE6528C9840184F1D78E665C78BD1C765C829803B0A482A5D46161
Block: 327
Transacion 0: 8B8C325B6B2C154F774CF1DDB46EA98494963793D38EC3E416980CD89D33FB24
Block: 328
Transacion 0: 06DE54975CC13CB84CB43B229496ED9D1F004BEE7C2B52601C8031591D60E3B7
Block: 329
Transacion 0: 0569C1508BF9FB344A65935BD8AF967F7C72B2DE7D1ED6A3BC9AF082517B3EBE
Block: 330
Transacion 0: 39AEF4674D4C0B262F46D7737A9A19A9CDB6E567F8585BA57C30489C3DFA0641
Block: 331
Transacion 0: 8720B1B397FF28606E4EA4317F9D5E7B01EF8C89617A37516215D8FC443D31AC
Block: 332
Transacion 0: 5629FA1E2E63C145471455E7FA87A47165572007EA1324B5CF7147C91B143F41
Block: 333
Transacion 0: 70B0FE7E9F9A287348DFA35A534BAD004A064403E9B8029DB18B705B7D5CB82A
Block: 334
Transacion 0: 7CCFECBAE66AF4EAFAF3306F1CDE711ABE277E216DF252A3D74F10B79C76926A
Block: 335
Transacion 0: 3F9AE2B0505EAD2BD2B701C419DF519538AFF99CC036A174AE2B6C569CA2CABC
Block: 336
Transacion 0: C098334CCD1B4BB48FC6B460A3F6FF3E1184AB9776181E55A80097E0B690FF3B
Block: 337
Transacion 0: CB090B2BD2CDB73C3ED8A828AA20FFC3EAFFE72B53A345363E15C0DF188E4447
Block: 338
Transacion 0: 3DDEC50405754518AD33CA09D9B35D4AC00439AA88D8A5B5D57D72765135F787
Block: 339
Transacion 0: 0D46267788252FCC1C88FEA3C59AC443DC8A058127121AB83A4FA078B94850DF
Block: 340
Transacion 0: F0AA1AF92FD3E1287043D7B3B9CCD1798454776D87D1985BEEB24F2F6EBFA80E
Block: 341
Transacion 0: AADC016A5DC27002B6B7D5BC70ADE49F46A3E83A86D48C1BA0F68D003383E6E1
Block: 342
Transacion 0: 32BA3D2E00F08F8A89461B76261DDFB73388AA230C1271D5215CF163DBB40F1C
Block: 343
Transacion 0: BCC5E3AE406243C4DF00290D31DDBE4827575C0B6F929C2C5DB775BF69A84255
Block: 344
Transacion 0: 6743246DCA88E466A693633F39A4D68C95404506ECEB214C40855310C2C05C53
Block: 345
Transacion 0: F38136E53DA65AB5367A0EC73B6A495A5050D49133B1DDC5C6D90F409710F62C
Block: 346
Transacion 0: D71CBADDDBD255A7321C73FA552BEA8AD8969A2D3DBCBBA2652DC9BF604BF089
Block: 347
Transacion 0: 3D756DF956E48B9A6E376B17C8C6A3A98D85B3CD47903AF1F3FFBFE52648A139
Block: 348
Transacion 0: ABB7EE4AAEDE4D65C06245655ACA8F4035284A6947D686AF6D2314351346FD9D
Block: 349
Transacion 0: E771ADC73320CD15D1374E3B406ACBA471A17894927BC034F8004C2E9EF94C29
Block: 350
Transacion 0: B791A0CA3698AF9FD0F9D0D67AFFE631C3A5D3BBC6F65085C00C96E7843BBC93
Block: 351
Transacion 0: 39AC112A53A81BD270242242CF853DB983F793268C817AE29383B90D5315721A
Block: 352
Transacion 0: 4EA1F74C4877C69D3133945CDD07285D34431E0E0697C123BCAB0F4779BBE9AB
Block: 353
Transacion 0: 10A40D28A379C75B8A5AB4DF9CAA72EC94768CF31DC5F4F97220856827D51E0C
Block: 354
Transacion 0: 18FF334A67C25F9312F923895F7100BF7D64FA4BC8D84944FBBB4BB7AD2640E3
Block: 355
Transacion 0: 3B938EFA4F754E3E457DFD664FDF088EDEBF787220FAB267C44433E0CFE47713
Block: 356
Transacion 0: F09ED1E006F39C4B9D49E3CEC362EE052438DFEE57B60D3BB8B31DD1194D3B6B
Block: 357
Transacion 0: 5EF8635853C98DB3FB1BFBCFB08E1617BC24CBE442CE0AF56AF8F21AA99A2F53
Block: 358
Transacion 0: DFC03A58B170B6244A97C2207188601D2C93FFE61483CDF6B95B3D34C4A8EC5A
Block: 359
Transacion 0: 78FF80396E51F5688468B6F2CE72BFEF36E5B474AEF07772059FE3A1008DE4DD
Block: 360
Transacion 0: DE2386BEFCE7D2934F53FEEB632A291EB329069816E708784269F382F880D3FB
Block: 361
Transacion 0: B8F38E7AA14AFF384CEF118EAFE364AEAE6DB1BE7BD57D016C11EB2BA2FA588E
Block: 362
Transacion 0: 85A87B92A8A4393F2602BA45179FA9296C0C72FE3036AA9AFDD83B1D5330D7E1
Block: 363
Transacion 0: 5C10C7F312B6E5D80363D168430CEA4118FAEB3CD5663BFC155ACF006452CA31
Block: 364
Transacion 0: C5E412DDE2BE6FC6C4F150EA2F8C92BDE8FE662ADCFADDEFE1264274EF16D326
Block: 365
Transacion 0: D778D6BF6A6EBBA3A4C33838214587F24BED311CB2BF3A1E12AAC926065446C7
Block: 366
Transacion 0: 438E41EDAD640494590741B6105EDF9E3DA85730A4D89B8FE0C4E541BF7BBD43
Block: 367
Transacion 0: 9FFAA000736EB73EFEAC89AA4F2FCD9358EEA8616A271E8F9F4D7E3E79C35DC7
Block: 368
Transacion 0: 178FE851AA72D32A9DA1D93D1F77A699BFB0BEF3742A86264E66411E13730B88
Block: 369
Transacion 0: F938C68D867385EE6A891E7E2A4F29FE4A6E69344D5B7DDC3D98E5B0E27D3C0B
Block: 370
Transacion 0: 7769CDA03EA71EA44847C758A4BC073C8F37A3161A06A83B84FDCEF13B2702E5
Block: 371
Transacion 0: B77B35FE0F7C5888EF6846E3DBFAFA65AB7C22F6D5BC66BE90945690CE8B8C50
Block: 372
Transacion 0: 55D0DB951F6797C7ED0169E7D9D05C3C88816554D3F8C9202A9FE7A9FFC8AA40
Block: 373
Transacion 0: BDC4623D731C77710B3A6590E50279E35504BC1C16B2E1F39C22E5E14820BC72
Block: 374
Transacion 0: 5C6E48FC0AB0AAB94A3C133799C40E61A05DB1D1731B71DC69D01EC7EDAED98E
Block: 375
Transacion 0: D50BD0A86C0AB145BE4F8681AB6827C81041CE05843E311416FF0EE01DE3A4C3
Block: 376
Transacion 0: 8B011A55762D2C6B44B934FE325F13855540BA6C7AB340DB803BB4158578C8D4
Block: 377
Transacion 0: 27C8C2A828A410A45073E44D08CBFCD761C5F34F4B41EC0D82EFD2D60B183DEA
Block: 378
Transacion 0: D11603AB55FC62A9BFBB41DFEE89C54D4DE3A6A1DC2C62A4624E95F55C3D86C8
Block: 379
Transacion 0: BB6EF035598980E62580AF72361758E315249470CF9E439C013857EE93B129B7
Block: 380
Transacion 0: 699EA87979D27AFC031F13272C76B9B316320C9A105C9002748C4FD12DFEE4D7
Block: 381
Transacion 0: 8E8518921E64EE0BAAA7DB3C95F0C89502CCF54FD2FA502CB3924DEAB515CF22
Transacion 1: E726E1BE2078A40B938A65F63DF654196EE5AC561383572281245CD36E09D7C6
Block: 382
Transacion 0: D62508A97EB750BA19C9BF50C27A4998F2262BE5D76802C09158905C4BAF9699
Block: 383
Transacion 0: 2898FBBE9E8F2E7EADCC82B2FB00F43FE5A6CB4B4492680EFFE435E8B9AEDCEA
Transacion 1: 227E8E0666F063B8C556C372B240540A26D591DFCE20CF51E89F08A0C5A3708E
Transacion 2: 2F16FD4A15E9D87D1521DA89D7C928A229DC32D6757D4A68309FB6FF2F865342
Block: 384
Transacion 0: AC520F75AD7B0AF214965F51167958484D8B0C3E21A0B7B257F481EC95C76DB2
Transacion 1: 34DC823C5B563492E82E463E0CE12FDD189872B60D1CFCB6686209817C01EC82
Transacion 2: AB4001EB2CE2BCA9B526093813B18170ABD28D6EE86116432F67C4EEA73EB15A
Transacion 3: 3C3255FE1993305732405C297ED7297DCB2D1CBCD41DC7A3728F665FEA100EA7
Block: 385
Transacion 0: 04E527C66B6925E81CB850A3B81AD55D3050E4DDD392C2979CFCCBF6B9CC0E81
Transacion 1: 4AD4043B1AA4ACF391CC4F2744FEA407DE200DF0D548C0835736869E7ACC421B
Block: 386
Transacion 0: 32B636C9DF02C715EE9159BFC45BFC608B6D06305720BAADD2FD13047BF4EB7E
Block: 387
Transacion 0: FB83034C0C5DA5874753F2C0FE2F926AAC593AF06748F90FA0A79BF2EA4E9EC0
Transacion 1: 9AF31C323A2FEC3E1FDBF7064D8982207730A22BE01D0900C443B6CD966E7549
Transacion 2: 7D8400C988BACABF8D0DADBF55250F07A0619F3AF54F513889D8F90716C89117
Block: 388
Transacion 0: D4FBA46266A7D8B70FFA3351A1B2FEA755A3CE47064262A69229A52845E99F07
Transacion 1: 317DFA8CCBBC2CF0649313792C51C0542D20755BE0A5B200A7BD28BCC6218C2B
Transacion 2: 5F912F835CE402BB14B84B15C37E454845D69128009A10EB5551E221FC8A6225
Block: 389
Transacion 0: 5E70FCA75E3E1F0F50878A30097A7F6119DD223C7B3CD8EB699826A555662B0E
Transacion 1: B3E5EC565F885DFB33CCE989EF57993129FB79DB775C83AD260EF01FB2947058
Block: 390
Transacion 0: 19F1401F10E728631AF6294CE0C5758A06A60F7CD445A55810145EF0F97D735A
Transacion 1: 920F91EC56AC7CA728EADF76285C70AAEDAA79D83F1879F3BA59C82DEC8C8238
Block: 391
Transacion 0: C331B8CE4CAADD98E5038EB84BFA0DAFEBDDCF409917259A12F877B2204F4022
Block: 392
Transacion 0: 1916C6C9E984615DB98F97D4BF71B1058E81717B4CD186931186B4E285EBDCA2
Transacion 1: E5A12574182D1108748C95A34C5D4CB30034060D47B5C77F01EF58AD00405400
Transacion 2: 86A78DCA2B352AB665FC7E84040CD6A2D160BF8766E7F2C57462A24E7B7C22A0
Block: 393
Transacion 0: D7F0AE58D2C8407B8F40426A60801AD0429BEC3A038B9ECD25458DDCFECEDA09
Block: 394
Transacion 0: 3673D57B4E344E199CB9FC64EC9424D25007F8386B35539C53ED0E0A8655BEFF
Transacion 1: 20082DF2A8AA12B0E98C050976CE5C32FB9706D93887CC6591867548C84FC24E
Transacion 2: 3B1CD9874B59B39674714AD789258FAEC1DCC49FA354ABE2340A9FD7C7BD6255
Block: 395
Transacion 0: 3BE24FBE826513125DD8A21EB33EAEC8A0B5A41F74C3FFB10E33930D53004337
Block: 396
Transacion 0: 38D507C7E9C2DCE2F2090B1C2BCB97BDF16942EBE355284102697AA0CA6AA190
Block: 397
Transacion 0: 2B714EABF8CC8A4DE641032FE78FB6650D6A8A5161AE7A3FA384D65A77212BCE
Block: 398
Transacion 0: 5590BA3AF5F8F283307E90941BC59ECA29B66D1C865F415F058C57511218F097
Transacion 1: F9ED8FA26E2A650122C60DA24277F8E21E207EC17B440E8A7069EEA98616A781
Block: 399
Transacion 0: 31F20390249989D70E2945981B0A8A97386BCD187F80AAB6D1549A30564F0997
Transacion 1: 30E8B9F9ECAA536141F21E7AD0370A60F5094AA74BD49C910450CF5B9966B47D
Transacion 2: 8493E2F7076AEB57F771F35E294D142318B4BBAA01410A739832C23613059763
Transacion 3: B0E03F28C5F55FBE5D01EAEAA9A87D06C88ABF7D12C469474B3FF000939EF692
Transacion 4: F8E287D4658934A5B2357704BCC9AF3DCAD329B9EAB2F3F0AB68978D46B81F23
Transacion 5: B3C539D8E0C3F483779512747737F98CEB3DE907A99287F4D1D56294E17687ED
Transacion 6: F4BAF4CF420BD9DA834D2598B6F41C9F5293B133A2846ED698149CFFA9DC3F55
Transacion 7: D30051683F838A45B26C9C8970679A144B8FA246D9D5E299E074AC8E5A744BF9
Transacion 8: 246901E399CA7EADC38AF2067C9EBDA772F7B2BBFB5F850D67F8EC0A4FEAE7C9
Block: 400
Transacion 0: AB736A9180F675EE3B9751FC9B83AA726C49998DA7E09227CD3D8B486DD50B6C
Transacion 1: 166E31153CC1AF37C80D88E75B09B41B483656F1823ACF66637EF5F0E109930D
Transacion 2: 801054F7282B2575E17275DA1D7CA714F482DC92EA819B33942588771D0EC9B0
Transacion 3: 2FDF7AD3E27CA9AC1EAC317215A216AA0EE44E305E5CA894C896A9DBC9FE3C4A
Transacion 4: 60EF5D279702D3060686297D41898CFB1D323F75F4887A4ACA1E9311DF956F0D
Transacion 5: 9C53B59700B0AE869DAF70D8E0375A5AB36D4D4BF66499A3AC2E3835A07A3715
Transacion 6: 9154CC92C8B025C1DF13EF7D09A0F9662F46B40368175AD76A92948C5C2D86DE
Transacion 7: B01773AB0DFE7D44CA21EBEF4F5A5D9FD1F532C4F16BEA2F8385CE1E3188919C
Transacion 8: 667B07D690B83D6B4E57A57A242F87B101A53B86F521CAD2A54A7FBC63565D89
Transacion 9: 14F72D1D00EA8092D43191E2D0226D6857F3D36B7CCA0BE8F22DDCA7BA6DD076
Transacion 10: 9D3A8B333CBE818D9A6AACD363A4A06E7DB158CE136A2EB8AEEF8769DC512F4F
Transacion 11: 506830763DE017845A7D45EB55D49AE8663F3E0C6B0153AEDF67FB6D5EEB64AB
Transacion 12: 34AC918C91C2B47A94FAE82B7F86FEA65368E902BD737B13BAB395CE6C09717B
Transacion 13: 2F75BC9B48BDA054C7203E9BD11F579EDEB1373C269285B39261080E04C074AD
Transacion 14: 2B309C29DA939833FE0D9FA7D8CCA40E0B8F644FAFAC5D44B475EA07BC44A271
Transacion 15: 02BA2EED6BBE7F432E67AAA254871415DF97FD2AC15379755E5C01637D3EB802
Transacion 16: 34A6DA66683A4718758BCD0B68B3AB427418A7C3B06AA8B18DA398449BEF3505
Transacion 17: 1FFBE330992ACBE9D0BD834A97E097E4F78787B2C7DAAE1572357F7E4C4D6239
Block: 401
Transacion 0: CC3E7A487087173B934A76752009F90F6689C56994A2EB186B08A9973586A788
Transacion 1: 5540F54A2BCC34F68E4FA2DDE4C3349BBB4249CDAD285474777B67675A284D98
Transacion 2: 31B4242928B779163EA407D2CA8F72A32B2FFB326364250AF99561EAE73889F7
Transacion 3: 2CC456BF4B09A88F94483224A1DCCA468FFBC18E0DFC846542B93B1E15A15DF0
Transacion 4: 259CC9DEE90C5CE17633F64717A68A171F2450243C79135EDF04EE936946E53C
Transacion 5: 55B8E3917B02EB8DE033D4E2F5F02C195FF7C51621369D3624551CF0CFF3C464
Transacion 6: 8F0670606178B0BEA00BC79AE337A84E801E4574D082302E39393AEFBCBD288B
Transacion 7: 2B8364FC33E2FCF8C36D8CADBCBD3F3FF85DCCCB3A5A1436347A419676754CF9
Transacion 8: 497A65786A1FC2BD18DCBA12366F2AAEF3D7AF5D0A74A2C68119CC173FFA6E7E
Transacion 9: E3F2B3DD38EE4A87F6F9B77B5196BE61F74101D5D0D5272F8EEA2D3C1371965A
Transacion 10: 252889D738E6359A7D34DA06C61F825313BD6DB00161D1A7ED3692E895EBB545
Transacion 11: 63B54B162A7115D16ECC97D304993785BB0585A1BD53C24A861B7D2692C6B5F3
Transacion 12: E1437992533EEA32784AE5CD2AA3B655B4023D2CC23D154BAAADC93FB7FBFCBA
Transacion 13: 0354A724AF498ACB80DF9142F100E5FE1428309327DC2728C0997785997BBAB2
Transacion 14: 38476DF82697A98B415802D37D34C15FEB6A1E19EAE5A733F739D48335D7890F
Transacion 15: F3639BE5B1177A21598AAABCCAC919381B9715D00D13E9744B3C57F19DF35DA1
Transacion 16: F47AA32D864FEB22F17E046FD44C0958462A4AA5B47B6E8B36EC0229BD4E332F
Transacion 17: 63898138C43B38C01B0940C3988CFA95AC78B6C53CB04C3AF9B1EC62EC016E5F
Transacion 18: F9D27109D07A1482192886505A5AD356774E575336AEE5766002520E15443981
Transacion 19: FADF1E4F4BC5E18D5486E80F6861B14FFABECA1F91061A1364BF47C2CFB136B1
Transacion 20: 8EF1FDBBD43CD52A85B3F219182164393C72E14E7D371599A4CAC3B8E6F08231
Transacion 21: 0C449A4923A306883D6DF6B005523BA7B3EA0A575CB285F782CE26DF51B0ADC6
Transacion 22: CCA520E80023A0CEB3CBBB7B647F866E8FC7FD627F916B4549E65986A06D3FD9
Transacion 23: 8557C7118BC5C3C952FDE43F0056B5BD3901123A8EC805268765D5349E6740E1
Transacion 24: 560E22884260B6421D73B23F803BC5493A64D1CB8D04516B501C7B7873ECEFFF
Transacion 25: 0284ADDC20DA18B93C762094AE369FB65CF206AEF66EEB77387A51906D5E1E16
Transacion 26: D6E0031E30443B61C12670937998A2F91F1F6D51445D61054B8DAC3C2C407EBC
Block: 402
Transacion 0: 57F707DB2C7C4429E5C97AE81C32E923426A2908A3FEBE51FC9B4F4114C735D7
Transacion 1: A12FEB03072F6A6E285AE321D281252C1F0E6E0793EC0374AB4950159007EADD
Transacion 2: 9B3FC1BFB5848C8DE86A731BAD35EE81EA4306BABC1937AE6DB548DF7D4BDDBA
Transacion 3: FBE5294B5385A716165C9DFDB1775918A99BEFBAD0417930985DD9C87FBF34D9
Transacion 4: 760FF5C22245795691FD1643662F55DEDE45473FB2BC2ACDC5C4089C3AF1C469
Transacion 5: FBE8E5EB3E3624955160FAF7174E2D21C1391E0AE6F50609D7B4367AEA1CC2C9
Transacion 6: 1E6619B55B40E54E9E59287753EE1D8F44FB3AAF3969B6E99901CC61B4463A3F
Transacion 7: A85001E3B9C55DC71B7326298E01FF46EC9838D8DCEA68F0845856B940FAD036
Transacion 8: 562E8C325CADABAFBBFFDF3A9989CED2F5318463A5B9719C3DC4AFFFF2A9FC4D
Block: 403
Transacion 0: 6140D0FDFA767DAB82B9EEE930305EF058B9AB4FEEC0C8B78D3884387E37BE5C
Block: 404
Transacion 0: E01622E1F3B2E1E99140A5738BE1759FB8653F68B9B0F94F6769A4A69BAD1317
Transacion 1: E6DDFE780E85BDA4EE79B1D118074F8378DFA68378137D1E29B27DB94CF26231
Transacion 2: 312A5482D7ADEB582E31DEE8C28BF1008B803D665C82834524E3DFFF1267F1DC
Transacion 3: 1B69B43EEC780F491D55707C37F28D4019A764046ED70C2314D71444A9D5B714
Transacion 4: E00F4D4FFC3F97AA8397AB55F9042B59885ADB91770EFED93B52832B2801C888
Transacion 5: A87FE6378BE30A4E1EED78C65017FC8C3FAD65B3D5EA06E88AC30F157D5D5916
Block: 405
Transacion 0: A7B74FA49643B6503E5D5ABA47A0984A996C47E0BFFF2307911F0B847446AB67
Transacion 1: 3CB2A7EAF51C0CA9809C7A4E4017C48E0E1CBA4BF0C95BC9A13FAFCA9C62832B
Transacion 2: 7092DE5D3C8E2BACFAD9706ADED2BCF6A7F56675FA40B42C1C18B46E4D363585
Transacion 3: B92B2AC3CF40BAC2DE944E938BC3FBBC141BEFEEB19D7AC6ACE2FDD28F563E81
Transacion 4: 8A354968D7B703167D79E02C8F27DDFF4DAEFC6694CD6050BDA4B0FD89A786FF
Transacion 5: 7DD2AB651779FC13766E1041C28E0F76D4E739ED33BE7A83D496DD9AD974F196
Transacion 6: A20011493A82E7EBFC8A13E9F4B31B9C21092BAB1674E21854662CBDE888FE00
Transacion 7: 67ABFB78B7C70BC1390BAE543A5CC8FD93ABDEA82343283307FA69ADD0FEDAAA
Transacion 8: 15748D09E43E2FBC6940C95AA8A77FDE82D27F7CE5A3B600564C606FCFBEC3FA
Transacion 9: 587368B85A026F51DB6967C26E0C1193DEF7320293A6061E07BE30A46AD67559
Transacion 10: 7EF287E1CF1422C43FD7A10A6CF34A56A5686B743263226E353BE83B3D971BCC
Transacion 11: 8C405B78EFB6BF9BE62CCE6B897A2A0C89CC41D83DC164560E0BCA5A28067EB7
Transacion 12: 78DA3B5FE00FE94804BC8104CDE134FAC0C2DB8B58B953D61BDE4844AFDD19B0
Transacion 13: 644E36F29F4166A0BD8DDF25232646953FB21EB5CFBE3DCF845FB40DE17E4E91
Transacion 14: DC6F7949E46EC006FDF46C84F81499C427E567EC4BE05EF5E720CB5EC540C895

View File

@ -0,0 +1,197 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: dah.proto
/*
Package util is a generated protocol buffer package.
It is generated from these files:
dah.proto
It has these top-level messages:
TX
*/
package util
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type TX struct {
Version uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
LockTime uint32 `protobuf:"varint,2,opt,name=lockTime" json:"lockTime,omitempty"`
Txin []*TX_TXIN `protobuf:"bytes,3,rep,name=txin" json:"txin,omitempty"`
Txout []*TX_TXOUT `protobuf:"bytes,4,rep,name=txout" json:"txout,omitempty"`
Blocks [][]byte `protobuf:"bytes,5,rep,name=blocks,proto3" json:"blocks,omitempty"`
Fee uint64 `protobuf:"varint,6,opt,name=fee" json:"fee,omitempty"`
}
func (m *TX) Reset() { *m = TX{} }
func (m *TX) String() string { return proto.CompactTextString(m) }
func (*TX) ProtoMessage() {}
func (*TX) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *TX) GetVersion() uint32 {
if m != nil {
return m.Version
}
return 0
}
func (m *TX) GetLockTime() uint32 {
if m != nil {
return m.LockTime
}
return 0
}
func (m *TX) GetTxin() []*TX_TXIN {
if m != nil {
return m.Txin
}
return nil
}
func (m *TX) GetTxout() []*TX_TXOUT {
if m != nil {
return m.Txout
}
return nil
}
func (m *TX) GetBlocks() [][]byte {
if m != nil {
return m.Blocks
}
return nil
}
func (m *TX) GetFee() uint64 {
if m != nil {
return m.Fee
}
return 0
}
type TX_TXIN struct {
Ix uint32 `protobuf:"varint,1,opt,name=ix" json:"ix,omitempty"`
SourceHash []byte `protobuf:"bytes,2,opt,name=sourceHash,proto3" json:"sourceHash,omitempty"`
Script []byte `protobuf:"bytes,3,opt,name=script,proto3" json:"script,omitempty"`
Sequence uint32 `protobuf:"varint,4,opt,name=sequence" json:"sequence,omitempty"`
}
func (m *TX_TXIN) Reset() { *m = TX_TXIN{} }
func (m *TX_TXIN) String() string { return proto.CompactTextString(m) }
func (*TX_TXIN) ProtoMessage() {}
func (*TX_TXIN) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
func (m *TX_TXIN) GetIx() uint32 {
if m != nil {
return m.Ix
}
return 0
}
func (m *TX_TXIN) GetSourceHash() []byte {
if m != nil {
return m.SourceHash
}
return nil
}
func (m *TX_TXIN) GetScript() []byte {
if m != nil {
return m.Script
}
return nil
}
func (m *TX_TXIN) GetSequence() uint32 {
if m != nil {
return m.Sequence
}
return 0
}
type TX_TXOUT struct {
Value uint64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
Script []byte `protobuf:"bytes,2,opt,name=script,proto3" json:"script,omitempty"`
Color []byte `protobuf:"bytes,3,opt,name=color,proto3" json:"color,omitempty"`
Quantity uint64 `protobuf:"varint,4,opt,name=quantity" json:"quantity,omitempty"`
}
func (m *TX_TXOUT) Reset() { *m = TX_TXOUT{} }
func (m *TX_TXOUT) String() string { return proto.CompactTextString(m) }
func (*TX_TXOUT) ProtoMessage() {}
func (*TX_TXOUT) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 1} }
func (m *TX_TXOUT) GetValue() uint64 {
if m != nil {
return m.Value
}
return 0
}
func (m *TX_TXOUT) GetScript() []byte {
if m != nil {
return m.Script
}
return nil
}
func (m *TX_TXOUT) GetColor() []byte {
if m != nil {
return m.Color
}
return nil
}
func (m *TX_TXOUT) GetQuantity() uint64 {
if m != nil {
return m.Quantity
}
return 0
}
func init() {
proto.RegisterType((*TX)(nil), "util.TX")
proto.RegisterType((*TX_TXIN)(nil), "util.TX.TXIN")
proto.RegisterType((*TX_TXOUT)(nil), "util.TX.TXOUT")
}
func init() { proto.RegisterFile("dah.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 329 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0xc1, 0x4b, 0xc3, 0x30,
0x18, 0xc5, 0x59, 0x9b, 0x4e, 0x8d, 0xdb, 0x90, 0x30, 0x24, 0xec, 0x20, 0x55, 0x3c, 0xf4, 0xd4,
0x82, 0x9e, 0x45, 0xf0, 0xa4, 0x17, 0x85, 0x50, 0x61, 0x78, 0x6b, 0xb3, 0x6f, 0x6d, 0xb4, 0x6b,
0xba, 0x34, 0x19, 0xdd, 0xd5, 0xbf, 0x5c, 0x92, 0x76, 0x63, 0x5e, 0x42, 0x7e, 0x79, 0x1f, 0xef,
0xbd, 0x8f, 0xe0, 0x8b, 0x55, 0x56, 0xc6, 0x8d, 0x92, 0x5a, 0x12, 0x64, 0xb4, 0xa8, 0xee, 0x7e,
0x7d, 0xec, 0xa5, 0x4b, 0x42, 0xf1, 0xd9, 0x0e, 0x54, 0x2b, 0x64, 0x4d, 0x47, 0xe1, 0x28, 0x9a,
0xb2, 0x03, 0x92, 0x05, 0x3e, 0xaf, 0x24, 0xff, 0x49, 0xc5, 0x06, 0xa8, 0xe7, 0xa4, 0x23, 0x93,
0x5b, 0x8c, 0x74, 0x27, 0x6a, 0xea, 0x87, 0x7e, 0x74, 0xf9, 0x30, 0x8d, 0xad, 0x63, 0x9c, 0x2e,
0xe3, 0x74, 0xf9, 0xf6, 0xce, 0x9c, 0x44, 0xee, 0x71, 0xa0, 0x3b, 0x69, 0x34, 0x45, 0x6e, 0x66,
0x76, 0x32, 0xf3, 0xf1, 0x99, 0xb2, 0x5e, 0x24, 0xd7, 0x78, 0x9c, 0x5b, 0xd7, 0x96, 0x06, 0xa1,
0x1f, 0x4d, 0xd8, 0x40, 0xe4, 0x0a, 0xfb, 0x6b, 0x00, 0x3a, 0x0e, 0x47, 0x11, 0x62, 0xf6, 0xba,
0xf8, 0xc6, 0xc8, 0xba, 0x93, 0x19, 0xf6, 0x44, 0x37, 0x74, 0xf5, 0x44, 0x47, 0x6e, 0x30, 0x6e,
0xa5, 0x51, 0x1c, 0x5e, 0xb3, 0xb6, 0x74, 0x45, 0x27, 0xec, 0xe4, 0xc5, 0x26, 0xb4, 0x5c, 0x89,
0x46, 0x53, 0xdf, 0x69, 0x03, 0xd9, 0xf5, 0x5a, 0xd8, 0x1a, 0xa8, 0x39, 0x50, 0xd4, 0xaf, 0x77,
0xe0, 0x45, 0x81, 0x03, 0xd7, 0x92, 0xcc, 0x71, 0xb0, 0xcb, 0x2a, 0x03, 0x2e, 0x0f, 0xb1, 0x1e,
0x4e, 0x2c, 0xbd, 0x7f, 0x96, 0x73, 0x1c, 0x70, 0x59, 0x49, 0x35, 0x24, 0xf5, 0x60, 0x83, 0xb6,
0x26, 0xab, 0xb5, 0xd0, 0x7b, 0x17, 0x84, 0xd8, 0x91, 0x5f, 0x9e, 0xbf, 0x9e, 0x0a, 0xa1, 0x4b,
0x93, 0xc7, 0x5c, 0x6e, 0x92, 0x72, 0xdf, 0x80, 0xaa, 0x60, 0x55, 0x80, 0x4a, 0xd6, 0x59, 0xae,
0x04, 0x4f, 0xa0, 0xcb, 0x36, 0x4d, 0x05, 0x6d, 0xc2, 0xcb, 0x4c, 0xd4, 0x5c, 0xae, 0x20, 0x29,
0x64, 0x62, 0x74, 0x67, 0x0f, 0x51, 0xe5, 0x63, 0xf7, 0xa5, 0x8f, 0x7f, 0x01, 0x00, 0x00, 0xff,
0xff, 0xbb, 0x8b, 0x8c, 0x33, 0xdf, 0x01, 0x00, 0x00,
}

View File

@ -0,0 +1,43 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
syntax = "proto3";
option go_package = "github.com/hyperledger/fabric/examples/chaincode/go/utxo/util" ;
package util;
message TX {
uint32 version = 1;
uint32 lockTime = 2;
message TXIN {
uint32 ix = 1;
bytes sourceHash = 2;
bytes script = 3;
uint32 sequence = 4;
}
repeated TXIN txin = 3;
message TXOUT {
uint64 value = 1;
bytes script = 2;
bytes color = 3;
uint64 quantity = 4;
}
repeated TXOUT txout = 4;
repeated bytes blocks = 5;
uint64 fee = 6;
}

View File

@ -0,0 +1,72 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
// Store interface describes the storage used by this chaincode. The interface
// was created so either the state database store can be used or a in memory
// store can be used for unit testing.
type Store interface {
GetState(Key) (*TX_TXOUT, bool, error)
PutState(Key, *TX_TXOUT) error
DelState(Key) error
GetTran(string) ([]byte, bool, error)
PutTran(string, []byte) error
}
// InMemoryStore used for unit testing
type InMemoryStore struct {
Map map[Key]*TX_TXOUT
TranMap map[string][]byte
}
// MakeInMemoryStore creates a new in memory store
func MakeInMemoryStore() Store {
ims := &InMemoryStore{}
ims.Map = make(map[Key]*TX_TXOUT)
ims.TranMap = make(map[string][]byte)
return ims
}
// GetState returns the transaction for the given key
func (ims *InMemoryStore) GetState(key Key) (*TX_TXOUT, bool, error) {
value, ok := ims.Map[key]
return value, ok, nil
}
// DelState deletes the given key and corresponding transactions
func (ims *InMemoryStore) DelState(key Key) error {
delete(ims.Map, key)
return nil
}
// PutState saves the key and transaction in memory
func (ims *InMemoryStore) PutState(key Key, value *TX_TXOUT) error {
ims.Map[key] = value
return nil
}
// GetTran returns the transaction for the given hash
func (ims *InMemoryStore) GetTran(key string) ([]byte, bool, error) {
value, ok := ims.TranMap[key]
return value, ok, nil
}
// PutTran saves the hash and transaction in memory
func (ims *InMemoryStore) PutTran(key string, value []byte) error {
ims.TranMap[key] = value
return nil
}

View File

@ -0,0 +1,104 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"bytes"
"encoding/binary"
)
func decodeInt32(input []byte) (int32, []byte, error) {
var myint32 int32
buf1 := bytes.NewBuffer(input[0:4])
binary.Read(buf1, binary.LittleEndian, &myint32)
return myint32, input, nil
}
// ReadVarInt reads an int that is formatted in the Bitcoin style
// variable int format
func ReadVarInt(buffer *bytes.Buffer) uint64 {
var finalResult uint64
var variableLenInt uint8
binary.Read(buffer, binary.LittleEndian, &variableLenInt)
if variableLenInt < 253 {
finalResult = uint64(variableLenInt)
} else if variableLenInt == 253 {
var result uint16
binary.Read(buffer, binary.LittleEndian, &result)
finalResult = uint64(result)
} else if variableLenInt == 254 {
var result uint32
binary.Read(buffer, binary.LittleEndian, &result)
finalResult = uint64(result)
} else if variableLenInt == 255 {
var result uint64
binary.Read(buffer, binary.LittleEndian, &result)
finalResult = result
}
return finalResult
}
// ParseUTXOBytes parses a bitcoin style transaction
func ParseUTXOBytes(txAsUTXOBytes []byte) *TX {
buffer := bytes.NewBuffer(txAsUTXOBytes)
var version int32
binary.Read(buffer, binary.LittleEndian, &version)
inputCount := ReadVarInt(buffer)
newTX := &TX{}
for i := 0; i < int(inputCount); i++ {
newTXIN := &TX_TXIN{}
newTXIN.SourceHash = buffer.Next(32)
binary.Read(buffer, binary.LittleEndian, &newTXIN.Ix)
// Parse the script length and script bytes
scriptLength := ReadVarInt(buffer)
newTXIN.Script = buffer.Next(int(scriptLength))
// Appears to not be used currently
binary.Read(buffer, binary.LittleEndian, &newTXIN.Sequence)
newTX.Txin = append(newTX.Txin, newTXIN)
}
// Now the outputs
outputCount := ReadVarInt(buffer)
for i := 0; i < int(outputCount); i++ {
newTXOUT := &TX_TXOUT{}
binary.Read(buffer, binary.LittleEndian, &newTXOUT.Value)
// Parse the script length and script bytes
scriptLength := ReadVarInt(buffer)
newTXOUT.Script = buffer.Next(int(scriptLength))
newTX.Txout = append(newTX.Txout, newTXOUT)
}
binary.Read(buffer, binary.LittleEndian, &newTX.LockTime)
return newTX
}

View File

@ -0,0 +1,144 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"math"
"github.com/hyperledger/fabric/examples/chaincode/go/utxo/consensus"
)
// UTXO includes the storage for the chaincode API or an in memory
// store for testing
type UTXO struct {
Store Store
}
// MakeUTXO constructs a new UTXO with the given store
func MakeUTXO(store Store) *UTXO {
utxo := &UTXO{}
utxo.Store = store
return utxo
}
// Key represents the key for a transaction in storage. It has both a
// hash and index
type Key struct {
TxHashAsHex string
TxIndex uint32
}
// GetTransactionHash returns the Bitcoin hash (double sha256) of
// the given transaction
func (u *UTXO) GetTransactionHash(txData []byte) [32]byte {
firstHash := sha256.Sum256(txData)
txHash := sha256.Sum256(firstHash[:])
return txHash
}
// IsCoinbase returns true if this is a coinbase transaction, false otherwise
func (u *UTXO) IsCoinbase(index uint32) bool {
return index == math.MaxUint32
}
var mandatoryFlags = consensus.Verify_flags_p2sh
var standardFlags = mandatoryFlags |
consensus.Verify_flags_dersig |
consensus.Verify_flags_strictenc |
consensus.Verify_flags_minimaldata |
consensus.Verify_flags_nulldummy |
consensus.Verify_flags_discourage_upgradable_nops |
consensus.Verify_flags_cleanstack |
consensus.Verify_flags_checklocktimeverify |
consensus.Verify_flags_low_s
// ExecResult is the result of processing a transaction
type ExecResult struct {
SumCurrentOutputs uint64
SumPriorOutputs uint64
IsCoinbase bool
}
// Execute processes the given transaction and outputs a result
func (u *UTXO) Execute(txData []byte) (*ExecResult, error) {
newTX := ParseUTXOBytes(txData)
txHash := u.GetTransactionHash(txData)
execResult := &ExecResult{}
// Loop through outputs first
for index, output := range newTX.Txout {
currKey := &Key{TxHashAsHex: hex.EncodeToString(txHash[:]), TxIndex: uint32(index)}
_, ok, err := u.Store.GetState(*currKey)
if err != nil {
return nil, fmt.Errorf("Error getting state from store: %s", err)
}
if ok == true {
// COLLISION
return nil, fmt.Errorf("COLLISION detected for key = %v, with output script length = %d", currKey, len(output.Script))
}
// Store the output in utxo
u.Store.PutState(*currKey, &TX_TXOUT{Script: output.Script, Value: output.Value})
execResult.SumCurrentOutputs += output.Value
}
// Now loop over inputs,
for index, input := range newTX.Txin {
prevTxHash := input.SourceHash
prevOutputIx := input.Ix
if u.IsCoinbase(prevOutputIx) {
execResult.IsCoinbase = true
//fmt.Println("COINBASE!!")
} else {
//fmt.Println("NOT COINBASE!!")
// NOT coinbase, need to verify
keyToPrevOutput := &Key{TxHashAsHex: hex.EncodeToString(prevTxHash), TxIndex: prevOutputIx}
value, ok, err := u.Store.GetState(*keyToPrevOutput)
if err != nil {
return nil, fmt.Errorf("Error getting state from store: %s", err)
}
if !ok {
// Previous output not fouund,
return nil, fmt.Errorf("Could not find previous transaction output with key = %v", keyToPrevOutput)
}
// Call Verify_script
txInputIndex := uint(index)
result := consensus.Verify_script(&txData[0], int64(len(txData)), &value.Script[0], int64(len(value.Script)), txInputIndex, uint(standardFlags))
if result != consensus.Verify_result_eval_true {
result = consensus.Verify_script(&txData[0], int64(len(txData)), &value.Script[0], int64(len(value.Script)), txInputIndex, uint(mandatoryFlags))
if result != consensus.Verify_result_eval_true {
return nil, fmt.Errorf("Unexpected result from verify_script, expected %d, got %d, perhaps it is %d", consensus.Verify_result_eval_true, result, consensus.Verify_result_invalid_stack_operation)
}
}
// Verified, now remove prior outputs
u.Store.DelState(*keyToPrevOutput)
execResult.SumPriorOutputs += value.Value
}
hex := hex.EncodeToString(txHash[:])
fmt.Printf("PUT TRAN %s", hex)
u.Store.PutTran(hex, txData)
}
return execResult, nil
}
// Query search the storage for a given transaction hash
func (u *UTXO) Query(txHashHex string) pb.Response {
tx, _, err := u.Store.GetTran(txHashHex)
return tx, err
}

View File

@ -0,0 +1,206 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"encoding/base64"
"encoding/hex"
"fmt"
"io/ioutil"
"strings"
"sync"
"testing"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/examples/chaincode/go/utxo/consensus"
)
// func TestMain(m *testing.M) {
// // viper.Set("ledger.blockchain.deploy-system-chaincode", "false")
//
// os.Exit(m.Run())
// }
const txFileHashes = "./Hashes_for_first_500_transactions_on_testnet3.txt"
const txFile = "./First_500_transactions_base64_encoded_on_testnet3.txt"
const consensusScriptVerifyTx = "01000000017d01943c40b7f3d8a00a2d62fa1d560bf739a2368c180615b0a7937c0e883e7c000000006b4830450221008f66d188c664a8088893ea4ddd9689024ea5593877753ecc1e9051ed58c15168022037109f0d06e6068b7447966f751de8474641ad2b15ec37f4a9d159b02af68174012103e208f5403383c77d5832a268c9f71480f6e7bfbdfa44904becacfad66163ea31ffffffff01c8af0000000000001976a91458b7a60f11a904feef35a639b6048de8dd4d9f1c88ac00000000"
const consensusScriptVerifyPreviousOutputScript = "76a914c564c740c6900b93afc9f1bdaef0a9d466adf6ee88ac"
type block struct {
transactions []string
}
func makeBlock() *block {
//return &block{transactions: make([]string, 0)}
return &block{}
}
func (b *block) addTxAsBase64String(txAsString string) error {
b.transactions = append(b.transactions, txAsString)
return nil
}
//getTransactionsAsUTXOBytes returns a readonly channel of the transactions within this block as UTXO []byte
func (b *block) getTransactionsAsUTXOBytes() <-chan []byte {
resChannel := make(chan []byte)
go func() {
defer close(resChannel)
for _, txAsText := range b.transactions {
data, err := base64.StdEncoding.DecodeString(txAsText)
if err != nil {
panic(fmt.Errorf("Could not decode transaction (%s) into bytes use base64 decoding: %s\n", txAsText, err))
}
resChannel <- data
}
}()
return resChannel
}
var blocksFromFile []*block
var once sync.Once
// getBlocks returns the blocks parsed from txFile, but only parses once.
func getBlocks() ([]*block, error) {
var err error
once.Do(func() {
contents, err := ioutil.ReadFile(txFile)
if err != nil {
return
}
lines := strings.Split(string(contents), string('\n'))
var currBlock *block
for _, line := range lines {
if strings.HasPrefix(line, "Block") {
currBlock = makeBlock()
blocksFromFile = append(blocksFromFile, currBlock)
} else {
// Trim out the 'Transacion XX:' part
//currBlock.addTxAsBase64String(strings.Split(line, ": ")[1])
currBlock.addTxAsBase64String(line)
}
}
})
return blocksFromFile, err
}
func TestVerifyScript_InvalidTranscation(t *testing.T) {
arg1 := []byte("arg1")
arg2 := int64(4)
arg3 := []byte("arg2")
arg4 := int64(4)
arg5 := uint(100)
arg6 := uint(1)
//func Verify_script(arg1 *byte, arg2 int64, arg3 *byte, arg4 int64, arg5 uint, arg6 uint) (_swig_ret LibbitcoinConsensusVerify_result_type)
result := consensus.Verify_script(&arg1[0], arg2, &arg3[0], arg4, arg5, arg6)
t.Log(result)
t.Log(consensus.Verify_result_tx_invalid)
if result != consensus.Verify_result_tx_invalid {
t.Fatalf("Should have failed to verify transaction")
}
}
func TestParse_GetBlocksFromFile(t *testing.T) {
blocks, err := getBlocks()
if err != nil {
t.Fatalf("Error getting blocks from tx file: %s", err)
}
for index, b := range blocks {
t.Logf("block %d has len transactions = %d", index, len(b.transactions))
}
t.Logf("Number of blocks = %d from file %s", len(blocks), txFile)
}
//TestBlocks_GetTransactionsAsUTXOBytes will range over blocks and then transactions in UTXO bytes form.
func TestBlocks_GetTransactionsAsUTXOBytes(t *testing.T) {
blocks, err := getBlocks()
if err != nil {
t.Fatalf("Error getting blocks from tx file: %s", err)
}
// Loop through the blocks and then range over their transactions in UTXO bytes form.
for index, b := range blocks {
t.Logf("block %d has len transactions = %d", index, len(b.transactions))
for txAsUTXOBytes := range b.getTransactionsAsUTXOBytes() {
//t.Logf("Tx as bytes = %v", txAsUTXOBytes)
_ = len(txAsUTXOBytes)
}
}
}
func TestParse_UTXOTransactionBytes(t *testing.T) {
blocks, err := getBlocks()
if err != nil {
t.Fatalf("Error getting blocks from tx file: %s", err)
}
utxo := MakeUTXO(MakeInMemoryStore())
// Loop through the blocks and then range over their transactions in UTXO bytes form.
for index, b := range blocks {
t.Logf("block %d has len transactions = %d", index, len(b.transactions))
for txAsUTXOBytes := range b.getTransactionsAsUTXOBytes() {
newTX := ParseUTXOBytes(txAsUTXOBytes)
t.Logf("Block = %d, txInputCount = %d, outputCount=%d", index, len(newTX.Txin), len(newTX.Txout))
// Now store the HEX of txHASH
execResult, err := utxo.Execute(txAsUTXOBytes)
if err != nil {
t.Fatalf("Error executing TX: %s", err)
}
if execResult.IsCoinbase == false {
if execResult.SumCurrentOutputs > execResult.SumPriorOutputs {
t.Fatalf("sumOfCurrentOutputs > sumOfPriorOutputs: sumOfCurrentOutputs = %d, sumOfPriorOutputs = %d", execResult.SumCurrentOutputs, execResult.SumPriorOutputs)
}
}
txHash := utxo.GetTransactionHash(txAsUTXOBytes)
retrievedTx := utxo.Query(hex.EncodeToString(txHash))
if !proto.Equal(newTX, retrievedTx) {
t.Fatal("Expected TX to be equal. ")
}
}
}
}
func TestParse_LibbitconTX(t *testing.T) {
txData, err := hex.DecodeString(consensusScriptVerifyTx)
if err != nil {
t.Fatalf("Error decoding HEX tx from libbitcoin: %s", err)
return
}
prevTxScript, err := hex.DecodeString(consensusScriptVerifyPreviousOutputScript)
if err != nil {
t.Fatalf("Error decoding HEX tx from libbitcoin: %s", err)
return
}
t.Logf("TX data from libbitcoin: %v", txData)
tx := ParseUTXOBytes(txData)
// Call Verify_script
txInputIndex := uint(0)
result := consensus.Verify_script(&txData[0], int64(len(txData)), &prevTxScript[0], int64(len(prevTxScript)), txInputIndex, uint(consensus.Verify_flags_p2sh))
if result != consensus.Verify_result_eval_true {
t.Fatalf("Unexpected result from verify_script, expected %d, got %d", consensus.Verify_result_eval_true, result)
}
t.Log(result)
t.Log(consensus.Verify_result_eval_true)
t.Logf("TX from %v", tx)
}